[tor-commits] [metrics-web/master] Allow multiple transports to be displayed at once.

karsten at torproject.org karsten at torproject.org
Sat Sep 13 06:03:52 UTC 2014


commit 2e474bd7e77d67708c91fce9257ee39cff828082
Author: Karsten Loesing <karsten.loesing at gmx.net>
Date:   Tue Sep 9 10:23:48 2014 +0200

    Allow multiple transports to be displayed at once.
    
    Implements a feature requested by asn in #12432.
---
 website/rserve/graphs.R                            |   91 +++++++++++++++-----
 .../metrics/web/graphs/GraphParameterChecker.java  |    8 +-
 website/web/WEB-INF/users.jsp                      |   21 +++--
 3 files changed, 87 insertions(+), 33 deletions(-)

diff --git a/website/rserve/graphs.R b/website/rserve/graphs.R
index 68a8b7d..d546127 100644
--- a/website/rserve/graphs.R
+++ b/website/rserve/graphs.R
@@ -795,19 +795,56 @@ plot_userstats <- function(start, end, node, variable, value, events,
              u$node == 'relay', ]
       title <- "Directly connecting users\n"
     }
+    u <- aggregate(list(lower = u$lower, upper = u$upper,
+                        users = u$clients),
+                   by = list(date = as.Date(u$date, "%Y-%m-%d"),
+                             value = u$country),
+                   FUN = sum)
   } else if (variable == 'transport') {
-    if (value != '!<*>') {
-        u <- u[u$transport == value & u$node == 'bridge', ]
-        title <- paste("Bridge users using transport ", value, "\n",
-                    sep = "")
+    if ('!<OR>' %in% value) {
+      n <- u[u$transport != '' & u$transport != '<OR>' &
+             u$node == 'bridge', ]
+      n <- aggregate(list(lower = n$lower, upper = n$upper,
+                          clients = n$clients),
+                     by = list(date = n$date),
+                     FUN = sum)
+      u <- rbind(u, data.frame(date = n$date, node = 'bridge',
+                               country = '', transport = '!<OR>',
+                               version = '', lower = n$lower,
+                               upper = n$upper, clients = n$clients,
+                               frac = NA))
+    }
+    if (length(value) > 1) {
+      u <- u[u$transport %in% value & u$node == 'bridge', ]
+      u <- aggregate(list(lower = u$lower, upper = u$upper,
+                          users = u$clients),
+                     by = list(date = as.Date(u$date, "%Y-%m-%d"),
+                               value = u$transport),
+                     FUN = sum)
+      title <- paste("Bridge users by transport\n")
     } else {
-        u <- u[u$transport != '' & u$transport != '<OR>' &
-               u$node == 'bridge', ]
-        title <- paste("Bridge users using any pluggable transport\n")
+      u <- u[u$transport == value & u$node == 'bridge', ]
+      u <- aggregate(list(lower = u$lower, upper = u$upper,
+                          users = u$clients),
+                     by = list(date = as.Date(u$date, "%Y-%m-%d"),
+                               value = u$transport),
+                     FUN = sum)
+      title <- paste("Bridge users using ",
+               ifelse(value == '<??>', 'unknown pluggable transport(s)',
+               ifelse(value == '<OR>', 'default OR protocol',
+               ifelse(value == '!<OR>', 'any pluggable transport',
+               ifelse(value == 'fte', 'FTE',
+               ifelse(value == 'websocket', 'Flash proxy/websocket',
+               paste('transport', value)))))), "\n", sep = "")
     }
   } else if (variable == 'version') {
-    u <- u[u$version== value & u$node == 'bridge', ]
+    u <- u[u$version == value & u$node == 'bridge', ]
     title <- paste("Bridge users using IP", value, "\n", sep = "")
+    u <- aggregate(list(lower = u$lower, upper = u$upper,
+                        users = u$clients),
+                   by = list(date = as.Date(u$date, "%Y-%m-%d"),
+                             value = u$version),
+                   FUN = sum)
   } else {
     if (value != 'all') {
       u <- u[u$country == value & u$node == 'bridge', ]
@@ -818,26 +855,28 @@ plot_userstats <- function(start, end, node, variable, value, events,
              u$node == 'bridge', ]
       title <- "Bridge users\n"
     }
+    u <- aggregate(list(lower = u$lower, upper = u$upper,
+                        users = u$clients),
+                   by = list(date = as.Date(u$date, "%Y-%m-%d"),
+                             value = u$country),
+                   FUN = sum)
   }
-  u <- aggregate(list(lower = u$lower, upper = u$upper,
-                      users = u$clients),
-                 by = list(date = as.Date(u$date, "%Y-%m-%d")), FUN = sum)
-  dates <- seq(from = as.Date(start, "%Y-%m-%d"),
-      to = as.Date(end, "%Y-%m-%d"), by="1 day")
-  missing <- setdiff(dates, u$date)
-  if (length(missing) > 0) {
-    u <- rbind(u,
-        data.frame(date = as.Date(missing, origin = "1970-01-01"),
-        users = NA, lower = NA, upper = NA))
-  }
+  u <- merge(x = u, all.y = TRUE, y = data.frame(expand.grid(
+             date = seq(from = as.Date(start, "%Y-%m-%d"),
+             to = as.Date(end, "%Y-%m-%d"), by="1 day"),
+             value = ifelse(value == 'all', '', value))))
   formatter <- function(x, ...) { format(x, scientific = FALSE, ...) }
   date_breaks <- date_breaks(
     as.numeric(max(u$date) - min(u$date)))
   max_y <- ifelse(length(na.omit(u$users)) == 0, 0,
       max(u$users, na.rm = TRUE))
-  plot <- ggplot(u, aes(x = date, y = users))
+  if (length(value) > 1) {
+    plot <- ggplot(u, aes(x = date, y = users, colour = value))
+  } else {
+    plot <- ggplot(u, aes(x = date, y = users))
+  }
   if (length(na.omit(u$users)) > 0 & events != "off" &
-      variable == 'country' & value != "all") {
+      variable == 'country' & length(value) == 1 && value != "all") {
     upturns <- u[u$users > u$upper, c("date", "users")]
     downturns <- u[u$users <= u$lower, c("date", "users")]
     if (events == "on") {
@@ -865,6 +904,16 @@ plot_userstats <- function(start, end, node, variable, value, events,
     scale_y_continuous(name = "", limits = c(0, max_y),
         formatter = formatter) +
     opts(title = title)
+  if (length(value) > 1) {
+    plot <- plot +
+      scale_colour_hue(name = "", breaks = value,
+            labels = ifelse(value == '<??>', 'Unknown PT',
+                     ifelse(value == '<OR>', 'Default OR protocol',
+                     ifelse(value == '!<OR>', 'Any PT',
+                     ifelse(value == 'fte', 'FTE',
+                     ifelse(value == 'websocket', 'Flash proxy/websocket',
+                     value))))))
+  }
   ggsave(filename = path, width = 8, height = 5, dpi = 72)
 }
 
diff --git a/website/src/org/torproject/metrics/web/graphs/GraphParameterChecker.java b/website/src/org/torproject/metrics/web/graphs/GraphParameterChecker.java
index ab77943..223a289 100644
--- a/website/src/org/torproject/metrics/web/graphs/GraphParameterChecker.java
+++ b/website/src/org/torproject/metrics/web/graphs/GraphParameterChecker.java
@@ -59,7 +59,7 @@ public class GraphParameterChecker {
     this.knownParameterValues.put("source", "all,siv,moria,torperf");
     this.knownParameterValues.put("filesize", "50kb,1mb,5mb");
     this.knownParameterValues.put("transport",
-        "obfs2,obfs3,websocket,fte,meek,scramblesuit,<OR>,<??>,!<*>");
+        "obfs2,obfs3,websocket,fte,meek,scramblesuit,<OR>,<??>,!<OR>");
     this.knownParameterValues.put("version", "v4,v6");
     this.knownParameterValues.put("p", "100,99,98,97,95,91,90,80,75,70,"
         + "60,50,40,30,25,20,10,9,5,3,2,1,0");
@@ -161,6 +161,9 @@ public class GraphParameterChecker {
       List<String> knownCountries = Arrays.asList(
           this.knownParameterValues.get("country").split(","));
       if (countryParameters != null) {
+        if (countryParameters.length != 1) {
+          return null;
+        }
         for (String country : countryParameters) {
           if (country == null || country.length() == 0 ||
               !knownCountries.contains(country)) {
@@ -265,6 +268,9 @@ public class GraphParameterChecker {
       List<String> knownVersions = Arrays.asList(
           this.knownParameterValues.get("version").split(","));
       if (versionParameters != null) {
+        if (versionParameters.length != 1) {
+          return null;
+        }
         for (String version : versionParameters) {
           if (version == null || version.length() == 0 ||
               !knownVersions.contains(version)) {
diff --git a/website/web/WEB-INF/users.jsp b/website/web/WEB-INF/users.jsp
index 400fd31..04eeaf9 100644
--- a/website/web/WEB-INF/users.jsp
+++ b/website/web/WEB-INF/users.jsp
@@ -232,17 +232,16 @@ Bridge users by transport:
       <input type="text" name="end" size="10"
              value="<c:choose><c:when test="${fn:length(userstats_bridge_transport_end) == 0}">${default_end_date}</c:when><c:otherwise>${userstats_bridge_transport_end[0]}</c:otherwise></c:choose>">
     </p><p>
-      Source: <select name="transport">
-        <option value="<OR>"<c:if test="${userstats_bridge_transport_transport[0] eq '<OR>'}"> selected</c:if>>Default OR protocol</option>
-        <option value="obfs2"<c:if test="${userstats_bridge_transport_transport[0] eq 'obfs2'}"> selected</c:if>>obfs2</option>
-        <option value="obfs3"<c:if test="${userstats_bridge_transport_transport[0] eq 'obfs3'}"> selected</c:if>>obfs3</option>
-        <option value="websocket"<c:if test="${userstats_bridge_transport_transport[0] eq 'websocket'}"> selected</c:if>>Flash proxy/websocket</option>
-        <option value="fte"<c:if test="${userstats_bridge_transport_transport[0] eq 'fte'}"> selected</c:if>>FTE</option>
-        <option value="meek"<c:if test="${userstats_bridge_transport_transport[0] eq 'meek'}"> selected</c:if>>meek</option>
-        <option value="scramblesuit"<c:if test="${userstats_bridge_transport_transport[0] eq 'scramblesuit'}"> selected</c:if>>scramblesuit</option>
-        <option value="<??>"<c:if test="${userstats_bridge_transport_transport[0] eq '<??>'}"> selected</c:if>>Unknown transport</option>
-        <option value="!<*>"<c:if test="${userstats_bridge_transport_transport[0] eq '!<*>'}"> selected</c:if>>Any non-OR transport</option>
-      </select>
+      <label>Source: </label>
+      <input type="checkbox" name="transport" value="<OR>"<c:if test="${fn:length(userstats_bridge_transport_transport) == 0 or fn:contains(fn:join(userstats_bridge_transport_transport, ','), '<OR>')}"> checked</c:if>> Default OR protocol
+      <input type="checkbox" name="transport" value="obfs2"<c:if test="${fn:length(userstats_bridge_transport_transport) > 0 and fn:contains(fn:join(userstats_bridge_transport_transport, ','), 'obfs2')}"> checked</c:if>> obfs2
+      <input type="checkbox" name="transport" value="obfs3"<c:if test="${fn:length(userstats_bridge_transport_transport) > 0 and fn:contains(fn:join(userstats_bridge_transport_transport, ','), 'obfs3')}"> checked</c:if>> obfs3
+      <input type="checkbox" name="transport" value="websocket"<c:if test="${fn:length(userstats_bridge_transport_transport) > 0 and fn:contains(fn:join(userstats_bridge_transport_transport, ','), 'websocket')}"> checked</c:if>> Flash proxy/websocket
+      <input type="checkbox" name="transport" value="fte"<c:if test="${fn:length(userstats_bridge_transport_transport) > 0 and fn:contains(fn:join(userstats_bridge_transport_transport, ','), 'fte')}"> checked</c:if>> FTE
+      <input type="checkbox" name="transport" value="meek"<c:if test="${fn:length(userstats_bridge_transport_transport) > 0 and fn:contains(fn:join(userstats_bridge_transport_transport, ','), 'meek')}"> checked</c:if>> meek
+      <input type="checkbox" name="transport" value="scramblesuit"<c:if test="${fn:length(userstats_bridge_transport_transport) > 0 and fn:contains(fn:join(userstats_bridge_transport_transport, ','), 'scramblesuit')}"> checked</c:if>> scramblesuit
+      <input type="checkbox" name="transport" value="<??>"<c:if test="${fn:length(userstats_bridge_transport_transport) > 0 and fn:contains(fn:join(userstats_bridge_transport_transport, ','), '<??>')}"> checked</c:if>> Unknown pluggable transport(s)
+      <input type="checkbox" name="transport" value="!<OR>"<c:if test="${fn:length(userstats_bridge_transport_transport) > 0 and fn:contains(fn:join(userstats_bridge_transport_transport, ','), '!<OR>')}"> checked</c:if>> Any pluggable transport
     </p><p>
     <input class="submit" type="submit" value="Update graph">
     </p>



More information about the tor-commits mailing list