[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] [metrics-web/master] Replace all graphs with dynamically generated ones.
Author: Karsten Loesing <karsten.loesing@xxxxxxx>
Date: Thu, 7 Oct 2010 09:26:22 +0200
Subject: Replace all graphs with dynamically generated ones.
Commit: c8c0406a2152eedd41acb4f80175539f92c136ec
Instead of static graphs that are generated every 2 hours, we now serve
dynamically generated graphs and allow the user to customize them. This
allows us to clean up the graphs pages a lot and add new graph types more
easily. Also clean up navigation by grouping related graphs on four graphs
sub pages and by removing the metrics database processor log.
---
rserve/graphs.R | 13 +-
.../torproject/ernie/web/ExoneraTorServlet.java | 1 -
.../torproject/ernie/web/GraphImageServlet.java | 10 +-
.../torproject/ernie/web/RelaySearchServlet.java | 1 -
war/WEB-INF/templates/banner.tpl.jsp | 29 +--
war/WEB-INF/templates/graphs.tpl.jsp | 122 +--------
war/WEB-INF/templates/graphs_bridge-users.tpl.jsp | 72 -----
war/WEB-INF/templates/graphs_custom-graph.tpl.jsp | 99 -------
war/WEB-INF/templates/graphs_exit-relays.tpl.jsp | 57 ----
war/WEB-INF/templates/graphs_gettor.tpl.jsp | 12 -
war/WEB-INF/templates/graphs_network-size.tpl.jsp | 65 -----
war/WEB-INF/templates/graphs_network.tpl.jsp | 284 +++++++++++++++++++
war/WEB-INF/templates/graphs_new-users.tpl.jsp | 68 -----
war/WEB-INF/templates/graphs_packages.tpl.jsp | 71 +++++
war/WEB-INF/templates/graphs_performance.tpl.jsp | 80 ++++++
.../templates/graphs_recurring-users.tpl.jsp | 73 -----
war/WEB-INF/templates/graphs_torperf.tpl.jsp | 37 ---
war/WEB-INF/templates/graphs_users.tpl.jsp | 292 ++++++++++++++++++++
war/WEB-INF/templates/index.tpl.jsp | 54 +---
war/WEB-INF/templates/status.tpl.jsp | 3 -
war/WEB-INF/urlrewrite.xml | 32 +--
war/WEB-INF/web.xml | 4 -
war/bridge-users-graphs.jsp | 4 -
war/consensus-graphs.jsp | 4 -
war/custom-graph.jsp | 6 -
war/exit-relays-graphs.jsp | 4 -
war/gettor-graphs.jsp | 4 -
war/network.jsp | 4 +
war/new-users-graphs.jsp | 4 -
war/packages.jsp | 4 +
war/performance.jsp | 4 +
war/recurring-users-graphs.jsp | 4 -
war/torperf-graphs.jsp | 4 -
war/users.jsp | 4 +
34 files changed, 792 insertions(+), 737 deletions(-)
delete mode 100644 war/WEB-INF/templates/graphs_bridge-users.tpl.jsp
delete mode 100644 war/WEB-INF/templates/graphs_custom-graph.tpl.jsp
delete mode 100644 war/WEB-INF/templates/graphs_exit-relays.tpl.jsp
delete mode 100644 war/WEB-INF/templates/graphs_gettor.tpl.jsp
delete mode 100644 war/WEB-INF/templates/graphs_network-size.tpl.jsp
create mode 100644 war/WEB-INF/templates/graphs_network.tpl.jsp
delete mode 100644 war/WEB-INF/templates/graphs_new-users.tpl.jsp
create mode 100644 war/WEB-INF/templates/graphs_packages.tpl.jsp
create mode 100644 war/WEB-INF/templates/graphs_performance.tpl.jsp
delete mode 100644 war/WEB-INF/templates/graphs_recurring-users.tpl.jsp
delete mode 100644 war/WEB-INF/templates/graphs_torperf.tpl.jsp
create mode 100644 war/WEB-INF/templates/graphs_users.tpl.jsp
delete mode 100644 war/bridge-users-graphs.jsp
delete mode 100644 war/consensus-graphs.jsp
delete mode 100644 war/custom-graph.jsp
delete mode 100644 war/exit-relays-graphs.jsp
delete mode 100644 war/gettor-graphs.jsp
create mode 100644 war/network.jsp
delete mode 100644 war/new-users-graphs.jsp
create mode 100644 war/packages.jsp
create mode 100644 war/performance.jsp
delete mode 100644 war/recurring-users-graphs.jsp
delete mode 100644 war/torperf-graphs.jsp
create mode 100644 war/users.jsp
diff --git a/rserve/graphs.R b/rserve/graphs.R
index d94553a..b786990 100644
--- a/rserve/graphs.R
+++ b/rserve/graphs.R
@@ -159,7 +159,7 @@ plot_new_users <- function(start, end, country, path) {
"WHERE (source = '68333D0761BCF397A587A0C0B963E4A9E99EC4D3' ",
"OR source = 'F2044413DAC2E02E3D6BCF4735A19BCA1DE97281') ",
"AND date >= '", start, "' AND date <= '", end, "' AND country = '",
- country, "'", sep = "")
+ ifelse(country == "all", "zy", country), "'", sep = "")
rs <- dbSendQuery(con, q)
newusers <- fetch(rs, n = -1)
dbDisconnect(con)
@@ -179,7 +179,7 @@ plot_new_users <- function(start, end, country, path) {
"Iranian", "Italian", "Japanese", "South Korean", "Burmese", "Polish",
"Russian", "Saudi", "Swedish", "Syrian", "Tunisian", "Turkmen",
"U.S.", "Uzbek", "Vietnamese", "Yemeni"), stringsAsFactors = FALSE)
- title <- ifelse(country == "zy",
+ title <- ifelse(country == "all",
"Total new or returning, directly connecting Tor users (all data)\n",
paste("New or returning, directly connecting",
peoples[peoples$country == country, "people"], "Tor users\n"))
@@ -200,7 +200,7 @@ plot_direct_users <- function(start, end, country, path) {
"FROM dirreq_stats WHERE share >= 1 ",
"AND source = '8522EB98C91496E80EC238E732594D1509158E77' ",
"AND date >= '", start, "' AND date <= '", end, "' AND country = '",
- country, "'", sep = "")
+ ifelse(country == "all", "zy", country), "'", sep = "")
rs <- dbSendQuery(con, q)
directusers <- fetch(rs, n = -1)
dbDisconnect(con)
@@ -220,7 +220,7 @@ plot_direct_users <- function(start, end, country, path) {
"Iranian", "Italian", "Japanese", "South Korean", "Burmese", "Polish",
"Russian", "Saudi", "Swedish", "Syrian", "Tunisian", "Turkmen",
"U.S.", "Uzbek", "Vietnamese", "Yemeni"), stringsAsFactors = FALSE)
- title <- ifelse(country == "zy",
+ title <- ifelse(country == "all",
"Total recurring, directly connecting Tor users (all data)\n",
paste("Recurring, directly connecting",
peoples[peoples$country == country, "people"], "Tor users\n"))
@@ -240,7 +240,8 @@ plot_bridge_users <- function(start, end, country, path) {
q <- paste("SELECT date, users FROM bridge_stats ",
"WHERE date >= '", start, "' AND date <= '", end, "' ",
"AND date < (SELECT MAX(date) FROM bridge_stats) ",
- "AND country = '", country, "'", sep = "")
+ " AND country = '", ifelse(country == "all", "zy", country), "'",
+ sep = "")
rs <- dbSendQuery(con, q)
bridgeusers <- fetch(rs, n = -1)
dbDisconnect(con)
@@ -260,7 +261,7 @@ plot_bridge_users <- function(start, end, country, path) {
"Iranian", "Italian", "Japanese", "South Korean", "Burmese", "Polish",
"Russian", "Saudi", "Swedish", "Syrian", "Tunisian", "Turkmen",
"U.S.", "Uzbek", "Vietnamese", "Yemeni"), stringsAsFactors = FALSE)
- title <- ifelse(country == "zy",
+ title <- ifelse(country == "all",
"Total users via bridges (all data)\n",
paste(peoples[peoples$country == country, "people"],
"users via bridges\n"))
diff --git a/src/org/torproject/ernie/web/ExoneraTorServlet.java b/src/org/torproject/ernie/web/ExoneraTorServlet.java
index da44e2f..f1efeb0 100644
--- a/src/org/torproject/ernie/web/ExoneraTorServlet.java
+++ b/src/org/torproject/ernie/web/ExoneraTorServlet.java
@@ -48,7 +48,6 @@ public class ExoneraTorServlet extends HttpServlet {
+ " <a href=\"relay-search.html\">Relay Search</a>\n"
+ " <a href=\"consensus-health.html\">Consensus Health</a>\n"
- + " <a href=\"log.html\">Last Log</a>\n"
+ " </font>\n"
+ " </td>\n"
+ " <td class=\"banner-right\"></td>\n"
diff --git a/src/org/torproject/ernie/web/GraphImageServlet.java b/src/org/torproject/ernie/web/GraphImageServlet.java
index 304b103..8534049 100644
--- a/src/org/torproject/ernie/web/GraphImageServlet.java
+++ b/src/org/torproject/ernie/web/GraphImageServlet.java
@@ -46,9 +46,9 @@ public class GraphImageServlet extends HttpServlet {
this.knownParameterValues = new HashMap<String, String>();
this.knownParameterValues.put("flag",
"Running,Exit,Guard,Fast,Stable");
- this.knownParameterValues.put("country", "au,bh,br,ca,cn,cu,de,et,"
- + "fr,gb,ir,it,jp,kr,mm,pl,ru,sa,se,sy,tn,tm,us,uz,vn,ye");
- this.knownParameterValues.put("bundle", "en,zh_cn,fa");
+ this.knownParameterValues.put("country", "all,au,bh,br,ca,cn,cu,de,"
+ + "et,fr,gb,ir,it,jp,kr,mm,pl,ru,sa,se,sy,tn,tm,us,uz,vn,ye");
+ this.knownParameterValues.put("bundle", "all,en,zh_CN,fa");
this.knownParameterValues.put("source", "siv,moria,torperf");
this.knownParameterValues.put("filesize", "50kb,1mb,5mb");
}
@@ -149,7 +149,7 @@ public class GraphImageServlet extends HttpServlet {
}
/* Parse country codes if supported by the graph type. If no countries
- * are passed, use country code "zy" (all countries) as default. */
+ * are passed, use country code "all" (all countries) as default. */
if (supportedGraphParameters.contains("country")) {
String[] countryParameters = request.getParameterValues("country");
List<String> knownCountries = Arrays.asList(
@@ -163,7 +163,7 @@ public class GraphImageServlet extends HttpServlet {
}
}
} else {
- countryParameters = new String[] { "zy" };
+ countryParameters = new String[] { "all" };
}
recognizedGraphParameters.put("country", countryParameters);
}
diff --git a/src/org/torproject/ernie/web/RelaySearchServlet.java b/src/org/torproject/ernie/web/RelaySearchServlet.java
index 83f1a64..f6c44a7 100644
--- a/src/org/torproject/ernie/web/RelaySearchServlet.java
+++ b/src/org/torproject/ernie/web/RelaySearchServlet.java
@@ -119,7 +119,6 @@ public class RelaySearchServlet extends HttpServlet {
+ " <a class=\"current\">Relay Search</a>\n"
+ " <a href=\"consensus-health.html\">Consensus "
+ "Health</a>\n"
- + " <a href=\"log.html\">Last Log</a>\n"
+ " </font>\n"
+ " </td>\n"
+ " <td class=\"banner-right\"></td>\n"
diff --git a/war/WEB-INF/templates/banner.tpl.jsp b/war/WEB-INF/templates/banner.tpl.jsp
index 53e9d1c..bb29789 100644
--- a/war/WEB-INF/templates/banner.tpl.jsp
+++ b/war/WEB-INF/templates/banner.tpl.jsp
@@ -18,30 +18,18 @@
<%if (template.getTemplateName().startsWith("graphs")) {%>
<br/>
<font size="2">
- <a <%if (template.getTemplateName().contains("network-size")){%>
+ <a <%if (template.getTemplateName().contains("network")){%>
class="current" <%} else {%>
- href="/consensus-graphs.html"<%}%>>Network Size</a>
- <a <%if (template.getTemplateName().contains("exit-relays")) {%>
+ href="/network.html"<%}%>>Network</a>
+ <a <%if (template.getTemplateName().contains("users")) {%>
class="current" <%} else {%>
- href="/exit-relays-graphs.html"<%}%>>Exit Relays</a>
- <a <%if (template.getTemplateName().contains("new-users")) {%>
+ href="/users.html"<%}%>>Users</a>
+ <a <%if (template.getTemplateName().contains("packages")) {%>
class="current" <%} else {%>
- href="/new-users-graphs.html"<%}%>>New Users</a>
- <a <%if (template.getTemplateName().contains("recurring-users")) {%>
+ href="/packages.html"<%}%>>Packages</a>
+ <a <%if (template.getTemplateName().contains("performance")) {%>
class="current" <%} else {%>
- href="/recurring-users-graphs.html"<%}%>>Recurring Users</a>
- <a <%if (template.getTemplateName().contains("bridge-users")) {%>
- class="current" <%} else {%>
- href="/bridge-users-graphs.html"<%}%>>Bridge Users</a>
- <a <%if (template.getTemplateName().contains("torperf")) {%>
- class="current" <%} else {%>
- href="/torperf-graphs.html"<%}%>>torperf</a>
- <a <%if (template.getTemplateName().contains("gettor")) {%>
- class="current" <%} else {%>
- href="/gettor-graphs.html"<%}%>>GetTor</a>
- <a <%if (template.getTemplateName().contains("custom-graph")) {%>
- class="current" <%} else {%>
- href="/custom-graph.html"<%}%>>Custom Graph</a>
+ href="/performance.html"<%}%>>Performance</a>
</font>
<%} else if (template.getTemplateName().startsWith("status")) {%>
<br/>
@@ -49,7 +37,6 @@
<a href="/exonerator.html">ExoneraTor</a>
<a href="/relay-search.html">Relay Search</a>
<a href="/consensus-health.html">Consensus Health</a>
- <a href="/log.html">Last Log</a>
</font>
<%} else if (template.getTemplateName().startsWith("research")) { %>
<br/>
diff --git a/war/WEB-INF/templates/graphs.tpl.jsp b/war/WEB-INF/templates/graphs.tpl.jsp
index 4dc8624..f6a4647 100644
--- a/war/WEB-INF/templates/graphs.tpl.jsp
+++ b/war/WEB-INF/templates/graphs.tpl.jsp
@@ -1,116 +1,18 @@
<h2>Tor Metrics Portal: Graphs</h2>
<br/>
<p>The graphs on this page visualize a small portion of the data
- gathered in the Tor Metrics Project. They are generated by a
- combination of shell scripts, Java applications, and R code (for
- details see the <a href="tools.html">Tools</a> section). The
- following graphs are available:</p>
+ gathered in the Tor Metrics Project. The following graphs are
+ available:</p>
<ul>
- <li><a href="#relays">Relays in the Tor network</a></li>
- <li><a href="#newusers">New or returning, directly connecting
- Tor users</a></li>
- <li><a href="#recurringusers">Recurring, directly connecting Tor
- users</a></li>
- <li><a href="#bridgeusers">Tor users via bridges</a></li>
- <li><a href="#torperf">Time to complete requests</a></li>
- <li><a href="#gettor">Packages requested from GetTor</a></li>
- <li><a href="#versions">Relay versions</a></li>
- <li><a href="#platforms">Relay platforms</a></li>
- <li><a href="#bandwidth">Relay bandwidth</a></li>
+ <li>The <a href="network.html">Network page</a> has numerous
+ statistics on the network of relays and bridges.</li>
+ <li>The <a href="users.html">Users page</a> attempts to estimate
+ the number of users in the network.</li>
+ <li>There are numerous ways to download the Tor software. The
+ <a href="packages.html">Packages page</a> has statistics on the
+ number of packages requested from GetTor.</li>
+ <li>There are active and passive performance measurements of the
+ Tor network available on the
+ <a href="performance.html">Performance page</a>.</li>
</ul>
<br/>
- <a id="relays"/>
- <h3>Relays in the Tor network</h3>
- <br/>
- <p>The number of relays in the Tor network can be extracted from
- the hourly published network status consensuses.</p>
- <img src="graphs/networksize/networksize-30d.png"/>
- <p>Other graphs related to <a href="consensus-graphs.html">network
- size</a> and <a href="exit-relays-graphs.html">exit relays</a> can
- be found on separate pages.</p>
- <br/>
- <a id="newusers"/>
- <h3>New or returning, directly connecting Tor users</h3>
- <br/>
- <p>Users connecting to the Tor network for the first time request
- a list of running relays from one of currently seven directory
- authorities. Likewise, returning users whose network information
- is out of date connect to one of the directory authorities to
- download a fresh list of relays. The following graphs display an
- estimate of new or returning Tor users based on the requests as
- seen by gabelmoo, one of the directory authorities.</p>
- <img src="graphs/new-users/iran-new-30d.png"/>
- <p>Graphs for other countries can be found on a
- <a href="new-users-graphs.html">separate page</a>.</p>
- <br/>
- <a id="recurringusers"/>
- <h3>Recurring, directly connecting Tor users</h3>
- <br/>
- <p>After being connected to the Tor network, users need to refresh
- their list of running relays on a regular basis. They send their
- requests to one out of a few hundred directory mirrors to save
- bandwidth of the directory authorities. The following graphs show
- an estimate of recurring Tor users based on the requests as seen
- by trusted, a particularly fast directory mirror.</p>
- <img src="graphs/direct-users/iran-direct-30d.png"/>
- <p>Graphs for other countries can be found on a
- <a href="recurring-users-graphs.html">separate page</a>.</p>
- <br/>
- <a id="bridgeusers"/>
- <h3>Tor users via bridges</h3>
- <br/>
- <p>Users who cannot connect directly to the Tor network instead
- connect via bridges, which are non-public relays. The following
- graphs display an estimate of Tor users via bridges based on the
- unique IP addresses as seen by a few hundred bridges.</p>
- <img src="graphs/bridge-users/iran-bridges-30d.png"/>
- <p>Graphs for other countries can be found on a
- <a href="bridge-users-graphs.html">separate page</a>.</p>
- <br/>
- <a id="torperf"/>
- <h3>Time to complete requests</h3>
- <br/>
- <p>The following graphs show the performance of the Tor network as
- experienced by its users. The graphs contain the average (median)
- time to request files of three different sizes over the network as
- well as first and third quartile of request times.</p>
- <img src="graphs/torperf/torperf-50kb-torperf-6m.png"/>
- <p>Graphs for other file sizes or time intervals can be found on a
- <a href="torperf-graphs.html">separate page</a>.</p>
- <br/>
- <a id="gettor"/>
- <h3>Packages requested from GetTor</h3>
- <br/>
- <p>GetTor allows users to fetch Tor via email. The following
- graphs show the number of requested packages per day.</p>
- <img src="graphs/gettor/gettor-total.png"/>
- <p>More graphs about specific packages can be found on a
- <a href="gettor-graphs.html">separate page</a>.</p>
- <br/>
- <a id="versions"/>
- <h3>Relay versions</h3>
- <br/>
- <p>Relays report the Tor version that they are running in their
- server descriptors that they send to the directory authorities.
- The following graph shows the number of relays running specific
- Tor versions.</p>
- <img src="versions.png" width=576 height=360 />
- <br/>
- <a id="platforms"/>
- <h3>Relay platforms</h3>
- <br/>
- <p>Relays further report the operating systems in their server
- descriptors that they send to the directory authorities. The
- following graph shows the number of relays running specific
- platforms.</p>
- <img src="platforms.png" width=576 height=360 />
- <br/>
- <a id="bandwidth"/>
- <h3>Relay bandwidth</h3>
- <br/>
- <p>Relays advertise how much bandwidth they are willing and
- to contribute in their server descriptors. The following graph
- shows the sum of advertised bandwidth of all relays in the
- network.</p>
- <img src="bandwidth.png" width=576 height=360 />
- <br/>
diff --git a/war/WEB-INF/templates/graphs_bridge-users.tpl.jsp b/war/WEB-INF/templates/graphs_bridge-users.tpl.jsp
deleted file mode 100644
index 526160c..0000000
--- a/war/WEB-INF/templates/graphs_bridge-users.tpl.jsp
+++ /dev/null
@@ -1,72 +0,0 @@
-<%@page import="java.io.*" %>
-<%@page import="java.util.*" %>
- <h2>Tor Metrics Portal: Graphs</h2>
- <br/>
- <h3>Tor users via bridges</h3>
- <br/>
- <p>Users who cannot connect directly to the Tor network instead
- connect via bridges, which are non-public relays. The following
- graphs display an estimate of Tor users via bridges based on the
- unique IP addresses as seen by a few hundred bridges.</p>
- <ul>
- <li><a href="#total">All users</a></li>
- <li><a href="#australia">Australia</a></li>
- <li><a href="#bahrain">Bahrain</a></li>
- <li><a href="#brazil">Brazil</a></li>
- <li><a href="#burma">Burma</a></li>
- <li><a href="#canada">Canada</a></li>
- <li><a href="#china">China</a></li>
- <li><a href="#cuba">Cuba</a></li>
- <li><a href="#ethiopia">Ethiopia</a></li>
- <li><a href="#france">France</a></li>
- <li><a href="#germany">Germany</a></li>
- <li><a href="#iran">Iran</a></li>
- <li><a href="#italy">Italy</a></li>
- <li><a href="#japan">Japan</a></li>
- <li><a href="#poland">Poland</a></li>
- <li><a href="#russia">Russia</a></li>
- <li><a href="#saudi">Saudi</a></li>
- <li><a href="#southkorea">South Korea</a></li>
- <li><a href="#sweden">Sweden</a></li>
- <li><a href="#syria">Syria</a></li>
- <li><a href="#tunisia">Tunisia</a></li>
- <li><a href="#turkmenistan">Turkmenistan</a></li>
- <li><a href="#uk">U.K.</a></li>
- <li><a href="#usa">U.S.A.</a></li>
- <li><a href="#uzbekistan">Uzbekistan</a></li>
- <li><a href="#vietnam">Vietnam</a></li>
- <li><a href="#yemen">Yemen</a></li>
- </ul>
- <ul>
- <li><a href="csv/bridge-users.csv">CSV</a> file containing all
- data.</li>
- <li><a href="csv/monthly-users-peak.csv">CSV</a> file
- containing peak daily Tor users (recurring and bridge) per month
- by country.</li>
- <li><a href="csv/monthly-users-average.csv">CSV</a> file
- containing average daily Tor users (recurring and bridge) per
- month by country.</li>
- </ul>
-<%
- List<String> countries = Arrays.asList(("total,australia,bahrain,"
- + "brazil,burma,canada,china,cuba,ethiopia,france,germany,iran,"
- + "italy,japan,poland,russia,saudi,southkorea,sweden,syria,"
- + "tunisia,turkmenistan,uk,usa,uzbekistan,vietnam,yemen").
- split(","));
- List<String> suffixes = new ArrayList<String>(Arrays.asList(
- "30d,90d,180d,all".split(",")));
- Calendar now = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
- suffixes.add(String.format("%tY", now));
- suffixes.add(String.format("%1$tY-q%2$d", now,
- 1 + now.get(Calendar.MONTH) / 3));
- suffixes.add(String.format("%1$tY-%1$tm", now));
- for (String country : countries) {
- out.print("<p><a id=\"" + country + "\"/>\n");
- for (String suffix : suffixes) {
- out.print(" <img src=\"graphs/bridge-users/" + country
- + "-bridges-" + suffix + ".png\"/>\n");
- }
- out.print(" </p>");
- }
- out.print("<br/>\n");
-%>
diff --git a/war/WEB-INF/templates/graphs_custom-graph.tpl.jsp b/war/WEB-INF/templates/graphs_custom-graph.tpl.jsp
deleted file mode 100644
index 6df8b7b..0000000
--- a/war/WEB-INF/templates/graphs_custom-graph.tpl.jsp
+++ /dev/null
@@ -1,99 +0,0 @@
-<jsp:useBean id="customgraph"
- class="org.torproject.ernie.web.CustomGraphController"
- scope="request" />
-<h2>Tor Metrics Portal: Custom Graph</h2>
-<br/>
-<p>Custom graphs can be requested based on a specific range of
-dates and parameters available. Many similar graphs are available in the
-other sections of the metrics portal, however, the need may arise
-for tracking a more specific part of the Tor network.</p>
-<p>Date format: yyyy-mm-dd</p>
-<div id="graphmenu">
- <form action="<%=request.getRequestURI()%>">
- <div class="formrow">
- <label class="graphname">Network size</label>
- <input type="hidden" name="graph" value="networksize"/>
- <label class="startend" for="start">start</label>
- <input type="text" name="start" id="start"
- value="<%=("networksize".equals(request.getParameter("graph")) &&
- request.getParameter("start") != null) ?
- request.getParameter("start") : ""%>"/>
- <label class="startend" for="end">end</label>
- <input type="text" name="end" id="end"
- value="<%=("networksize".equals(request.getParameter("graph")) &&
- request.getParameter("end") != null) ?
- request.getParameter("end") : ""%>"/>
- <input class="submit" type="submit"/>
- </div>
- </form>
- <form action="<%=request.getRequestURI()%>">
- <div class="formrow">
- <label class="graphname">Platforms</label>
- <input type="hidden" name="graph" value="platforms"/>
- <label class="startend" for="start">start</label>
- <input type="text" name="start" id="start"
- value="<%=("platforms".equals(request.getParameter("graph")) &&
- request.getParameter("start") != null) ?
- request.getParameter("start") : ""%>"/>
- <label class="startend" for="end">end</label>
- <input type="text" name="end" id="end"
- value="<%=("platforms".equals(request.getParameter("graph")) &&
- request.getParameter("end") != null) ?
- request.getParameter("end") : ""%>"/>
- <input class="submit" type="submit"/>
- </div>
- </form>
- <form action="<%=request.getRequestURI()%>">
- <div class="formrow">
- <label class="graphname">Versions</label>
- <input type="hidden" name="graph" value="versions"/>
- <label class="startend" for="start">start</label>
- <input type="text" name="start" id="start"
- value="<%=("versions".equals(request.getParameter("graph")) &&
- request.getParameter("start") != null) ?
- request.getParameter("start") : ""%>"/>
- <label class="startend" for="end">end</label>
- <input type="text" name="end" id="end"
- value="<%=("versions".equals(request.getParameter("graph")) &&
- request.getParameter("end") != null) ?
- request.getParameter("end") : ""%>"/>
- <input class="submit" type="submit"/>
- </div>
- </form>
- <form action="<%=request.getRequestURI()%>">
- <div class="formrow">
- <label class="graphname">Bandwidth</label>
- <input type="hidden" name="graph" value="bandwidth"/>
- <label class="startend" for="start">start</label>
- <input type="text" name="start" id="start"
- value="<%=("bandwidth".equals(request.getParameter("graph")) &&
- request.getParameter("start") != null) ?
- request.getParameter("start") : ""%>"/>
- <label class="startend" for="end">end</label>
- <input type="text" name="end" id="end"
- value="<%=("bandwidth".equals(request.getParameter("graph")) &&
- request.getParameter("end") != null) ?
- request.getParameter("end") : ""%>"/>
- <input class="submit" type="submit"/>
- </div>
- </form>
- <br/>
-</div>
-
-<%if (request.getParameter("start") != null &&
- request.getParameter("end") != null &&
- request.getParameter("graph") != null) {
- customgraph.getGraphURL();
- if (!customgraph.getError().isEmpty()) {
- for(String err : customgraph.getError()) { %>
- <p class="error"><%=err%></p>
- <%} } else {%>
- <p><strong><jsp:getProperty name="customgraph" property="graphName"/> graph from
- <jsp:getProperty name="customgraph" property="graphStart"/> to
- <jsp:getProperty name="customgraph" property="graphEnd"/></strong></p>
- <img src="<jsp:getProperty name="customgraph" property="graphURL"/>"
- href="<jsp:getProperty name="customgraph" property="graphURL"/>"
- width=576 height=360 />
- <%}
-}%>
-<div style="clear:both;"></div>
diff --git a/war/WEB-INF/templates/graphs_exit-relays.tpl.jsp b/war/WEB-INF/templates/graphs_exit-relays.tpl.jsp
deleted file mode 100644
index f433d1e..0000000
--- a/war/WEB-INF/templates/graphs_exit-relays.tpl.jsp
+++ /dev/null
@@ -1,57 +0,0 @@
-<%@page import="java.io.*" %>
-<%@page import="java.util.*" %>
- <h2>Tor Metrics Portal: Graphs</h2>
- <br/>
- <h3>Exit relays in the Tor network</h3>
- <br/>
- <p>The number of exit relays in the Tor network can be extracted from
- the hourly published network status consensuses.</p>
- <ul>
- <li>Past <a href="#exit-72h">72 hours</a> up to
- now</li>
- <li>Past <a href="#exit-30d">30</a>,
- <a href="#exit-90d">90</a>,
- <a href="#exit-180d">180</a> days</li>
- <li><a href="#exit-all">All data</a> up to today</li>
-<%
- Calendar now = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
- Calendar lastQuarter = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
- lastQuarter.add(Calendar.MONTH, -3);
- Calendar lastMonth = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
- lastMonth.add(Calendar.MONTH, -1);
- out.print(" <li>Annual graphs of\n");
- for (int i = now.get(Calendar.YEAR); i > 2006; i--) {
- out.print(" <a href=\"#exit-" + i + "\">"
- + i + "</a>,\n");
- }
- out.print(" <a href=\"#exit-2006\">2006</a></li>\n");
- out.print(" <li>Quarterly graphs of\n");
- out.print(String.format(" <a href=\"#exit-%1$tY-q%2$d\">"
- + "Q%2$d %1$tY</a>,%n", now, 1 + now.get(Calendar.MONTH) / 3));
- out.print(String.format(" <a href=\"#exit-%1$tY-q%2$d\">"
- + "Q%2$d %1$tY</a></li>%n", lastQuarter, 1 + lastQuarter.get(Calendar.MONTH) / 3));
- out.print(" <li>Monthly graphs of\n");
- out.print(String.format(" <a href=\"#exit-%1$tY-%1$tm\">"
- + "%1$tb %1$tY</a>,%n", now));
- out.print(String.format(" <a href=\"#exit-%1$tY-%1$tm\">"
- + "%1$tb %1$tY</a></li>%n", lastMonth));
- out.print(" <li><a href=\"csv/exit.csv\">CSV</a> file\n"
- + " containing raw data</li>\n"
- + " </ul>\n");
- out.print(" </p><p><a id=\"exit-72h\"/><img src=\"graphs/exit/exit-72h.png\"/>\n"
- + " </p><p><a id=\"exit-30d\"/><img src=\"graphs/exit/exit-30d.png\"/>\n"
- + " </p><p><a id=\"exit-90d\"/><img src=\"graphs/exit/exit-90d.png\"/>\n"
- + " </p><p><a id=\"exit-180d\"/><img src=\"graphs/exit/exit-180d.png\"/>\n"
- + " </p><p><a id=\"exit-all\"/><img src=\"graphs/exit/exit-all.png\"/>\n");
- for (int i = now.get(Calendar.YEAR); i > 2006; i--) {
- out.print(" </p><p><a id=\"exit-" + i + "\"/><img src=\"graphs/exit/exit-" + i + ".png\"/>\n");
- }
- out.print(" </p><p><a id=\"exit-2006\"/><img src=\"graphs/exit/exit-2006.png\"/>\n");
- out.print(String.format(" </p><p><a id=\"exit-%1$tY-q%2$d\"/><img src=\"graphs/exit/exit-%1$tY-q%2$d.png\"/>\n",
- now, 1 + now.get(Calendar.MONTH) / 3));
- out.print(String.format(" </p><p><a id=\"exit-%1$tY-q%2$d\"/><img src=\"graphs/exit/exit-%1$tY-q%2$d.png\"/>\n",
- lastQuarter, 1 + lastQuarter.get(Calendar.MONTH) / 3));
- out.print(String.format(" </p><p><a id=\"exit-%1$tY-%1$tm\"/><img src=\"graphs/exit/exit-%1$tY-%1$tm.png\"/>\n", now));
- out.print(String.format(" </p><p><a id=\"exit-%1$tY-%1$tm\"/><img src=\"graphs/exit/exit-%1$tY-%1$tm.png\"/>\n", lastMonth));
- out.print(" </p><br/>\n");
-%>
diff --git a/war/WEB-INF/templates/graphs_gettor.tpl.jsp b/war/WEB-INF/templates/graphs_gettor.tpl.jsp
deleted file mode 100644
index 0d03363..0000000
--- a/war/WEB-INF/templates/graphs_gettor.tpl.jsp
+++ /dev/null
@@ -1,12 +0,0 @@
- <h2>Tor Metrics Portal: Graphs</h2>
- <br/>
- <h3>Packages requested from GetTor</h3>
- <br/>
- <p>GetTor allows users to fetch Tor via email. The following
- graphs show the number of requested packages per day.</p>
- <p><a href="csv/gettor.csv">CSV</a> file containing all data.</p>
- <img src="graphs/gettor/gettor-total.png"/>
- <img src="graphs/gettor/gettor-en.png"/>
- <img src="graphs/gettor/gettor-zh_cn.png"/>
- <img src="graphs/gettor/gettor-fa.png"/>
- <br/>
diff --git a/war/WEB-INF/templates/graphs_network-size.tpl.jsp b/war/WEB-INF/templates/graphs_network-size.tpl.jsp
deleted file mode 100644
index 199fbec..0000000
--- a/war/WEB-INF/templates/graphs_network-size.tpl.jsp
+++ /dev/null
@@ -1,65 +0,0 @@
-<%@page import="java.util.*" %>
-<%@page import="java.io.*" %>
- <h2>Tor Metrics Portal: Graphs</h2>
- <br/>
- <h3>Relays and bridges in the Tor network</h3>
- <br/>
- <p>The number of relays and bridges in the Tor network can be
- extracted from the hourly published network status consensuses
- and sanitized bridge statuses.</p>
- <ul>
- <li>Past <a href="#networksize-30d">30</a>,
- <a href="#networksize-90d">90</a>,
- <a href="#networksize-180d">180</a> days</li>
- <li><a href="#networksize-all">All data</a> up to today</li>
-<%
- Calendar now = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
- Calendar lastQuarter = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
- lastQuarter.add(Calendar.MONTH, -3);
- Calendar lastMonth = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
- lastMonth.add(Calendar.MONTH, -1);
- out.print(" <li>Annual graphs of\n");
- for (int i = now.get(Calendar.YEAR); i > 2006; i--) {
- out.print(" <a href=\"#networksize-" + i + "\">"
- + i + "</a>,\n");
- }
- out.print(" <a href=\"#networksize-2006\">2006</a></li>\n");
- out.print(" <li>Quarterly graphs of\n");
- out.print(String.format(" <a href=\"#networksize-%1$tY-q%2$d\">"
- + "Q%2$d %1$tY</a>,%n", now, 1 + now.get(Calendar.MONTH) / 3));
- out.print(String.format(" <a href=\"#networksize-%1$tY-q%2$d\">"
- + "Q%2$d %1$tY</a></li>%n", lastQuarter, 1 + lastQuarter.get(Calendar.MONTH) / 3));
- out.print(" <li>Monthly graphs of\n");
- out.print(String.format(" <a href=\"#networksize-%1$tY-%1$tm\">"
- + "%1$tb %1$tY</a>,%n", now));
- out.print(String.format(" <a href=\"#networksize-%1$tY-%1$tm\">"
- + "%1$tb %1$tY</a></li>%n", lastMonth));
- out.print(" <li><a href=\"csv/networksize.csv\">CSV</a> file\n"
- + " containing raw data</li>\n"
- + " </ul>\n"
- + " <p><a id=\"networksize-30d\"/>\n"
- + " <img src=\"graphs/networksize/networksize-30d.png\"/>\n"
- + " </p><p><a id=\"networksize-90d\"/>\n"
- + " <img src=\"graphs/networksize/networksize-90d.png\"/>\n"
- + " </p><p><a id=\"networksize-180d\"/>\n"
- + " <img src=\"graphs/networksize/networksize-180d.png\"/>\n"
- + " </p><p><a id=\"networksize-all\"/>\n"
- + " <img src=\"graphs/networksize/networksize-all.png\"/>\n");
- for (int i = now.get(Calendar.YEAR); i > 2006; i--) {
- out.print(" </p><p><a id=\"networksize-" + i + "\"/>\n"
- + " <img src=\"graphs/networksize/networksize-" + i + ".png\"/>\n");
- }
- out.print(" </p><p><a id=\"networksize-2006\"/>\n"
- + " <img src=\"graphs/networksize/networksize-2006.png\"/>\n");
- out.print(String.format(" </p><p><a id=\"networksize-%1$tY-q%2$d\"/>\n"
- + " <img src=\"graphs/networksize/networksize-%1$tY-q%2$d.png\"/>\n",
- now, 1 + now.get(Calendar.MONTH) / 3));
- out.print(String.format(" </p><p><a id=\"networksize-%1$tY-q%2$d\"/>\n"
- + " <img src=\"graphs/networksize/networksize-%1$tY-q%2$d.png\"/>\n",
- lastQuarter, 1 + lastQuarter.get(Calendar.MONTH) / 3));
- out.print(String.format(" </p><p><a id=\"networksize-%1$tY-%1$tm\"/>\n"
- + " <img src=\"graphs/networksize/networksize-%1$tY-%1$tm.png\"/>\n", now));
- out.print(String.format(" </p><p><a id=\"networksize-%1$tY-%1$tm\"/>\n"
- + " <img src=\"graphs/networksize/networksize-%1$tY-%1$tm.png\"/>\n", lastMonth));
- out.print(" </p><br/>\n");
-%>
diff --git a/war/WEB-INF/templates/graphs_network.tpl.jsp b/war/WEB-INF/templates/graphs_network.tpl.jsp
new file mode 100644
index 0000000..88f7087
--- /dev/null
+++ b/war/WEB-INF/templates/graphs_network.tpl.jsp
@@ -0,0 +1,284 @@
+<%@page import="java.util.*" %>
+<h2>Tor Metrics Portal: Network</h2>
+<br/>
+<h3>Relays and bridges in the network</h3>
+<br/>
+<p>The following graph shows the average daily number of relays and
+bridges in the network.</p>
+<a id="networksize" />
+<%
+StringBuilder networksizeUrl = new StringBuilder("networksize.png");
+if ("networksize".equals(request.getParameter("graph"))) {
+ List<String> parameters = new ArrayList<String>();
+// TODO check values here!
+ String startParameter = request.getParameter("start"),
+ endParameter = request.getParameter("end");
+ if (startParameter != null && startParameter.length() > 0) {
+ parameters.add("start=" + startParameter);
+ }
+ if (endParameter != null && endParameter.length() > 0) {
+ parameters.add("end=" + endParameter);
+ }
+ if (parameters.size() > 0) {
+ networksizeUrl.append("?" + parameters.get(0));
+ if (parameters.size() > 1) {
+ for (int i = 1; i < parameters.size(); i++) {
+ networksizeUrl.append("&" + parameters.get(i));
+ }
+ }
+ }
+}
+out.println("<img src=\"" + networksizeUrl.toString() + "\" width=\"576\" "
+ + "height=\"360\" />");
+%>
+</p>
+<form action="network.html#networksize">
+ <div class="formrow">
+ <input type="hidden" name="graph" value="networksize"/>
+ <p>
+ <label class="startend" for="start">Start date (yyyy-mm-dd):</label>
+ <input type="text" name="start" id="start" size="10"
+ value="<%=("networksize".equals(request.getParameter("graph")) &&
+ request.getParameter("start") != null) ?
+ request.getParameter("start") : ""%>"/>
+ <label class="startend" for="end">End date (yyyy-mm-dd):</label>
+ <input type="text" name="end" id="end" size="10"
+ value="<%=("networksize".equals(request.getParameter("graph")) &&
+ request.getParameter("end") != null) ?
+ request.getParameter("end") : ""%>"/>
+ </p><p>
+ <input class="submit" type="submit" value="Update graph"/>
+ </p>
+ </div>
+</form>
+<p><a href="csv/networksize.csv">CSV</a> file containing all data.</p>
+<br/>
+
+<h3>Relays with Exit, Fast, Guard, and Stable flags</h3>
+<br/>
+<p>The directory authorities assign certain flags to relays that clients
+use for their path selection decisions. The following graph shows the
+average number of relays with these flags assigned.</p>
+<a id="relayflags" />
+<%
+StringBuilder relayflagsUrl = new StringBuilder("relayflags.png");
+if ("relayflags".equals(request.getParameter("graph"))) {
+ List<String> parameters = new ArrayList<String>();
+// TODO check values here!
+ String startParameter = request.getParameter("start"),
+ endParameter = request.getParameter("end");
+ String[] flagParameters = request.getParameterValues("flag");
+ if (startParameter != null && startParameter.length() > 0) {
+ parameters.add("start=" + startParameter);
+ }
+ if (endParameter != null && endParameter.length() > 0) {
+ parameters.add("end=" + endParameter);
+ }
+ if (flagParameters != null && flagParameters.length > 0) {
+ for (String flag : flagParameters) {
+ if (flag != null && flag.length() > 0) {
+ parameters.add("flag=" + flag);
+ }
+ }
+ }
+ if (parameters.size() > 0) {
+ relayflagsUrl.append("?" + parameters.get(0));
+ if (parameters.size() > 1) {
+ for (int i = 1; i < parameters.size(); i++) {
+ relayflagsUrl.append("&" + parameters.get(i));
+ }
+ }
+ }
+}
+out.println("<img src=\"" + relayflagsUrl.toString() + "\" width=\"576\" "
+ + "height=\"360\" />");
+%>
+</p>
+<form action="network.html#relayflags">
+ <div class="formrow">
+ <input type="hidden" name="graph" value="relayflags"/>
+ <p>
+ <label class="startend" for="start">Start date (yyyy-mm-dd):</label>
+ <input type="text" name="start" id="start" size="10"
+ value="<%=("relayflags".equals(request.getParameter("graph")) &&
+ request.getParameter("start") != null) ?
+ request.getParameter("start") : ""%>"/>
+ <label class="startend" for="end">End date (yyyy-mm-dd):</label>
+ <input type="text" name="end" id="end" size="10"
+ value="<%=("relayflags".equals(request.getParameter("graph")) &&
+ request.getParameter("end") != null) ?
+ request.getParameter("end") : ""%>"/>
+ </p><p>
+ <label>Relay flags: </label>
+ <input type="checkbox" name="flag" value="Running"> Running</input>
+ <input type="checkbox" name="flag" value="Exit"> Exit</input>
+ <input type="checkbox" name="flag" value="Fast"> Fast</input>
+ <input type="checkbox" name="flag" value="Guard"> Guard</input>
+ <input type="checkbox" name="flag" value="Stable"> Stable</input>
+ </p><p>
+ <input class="submit" type="submit" value="Update graph"/>
+ </p>
+ </div>
+</form>
+<br/>
+
+<h3>Relays by version</h3>
+<br/>
+<p>Relays report the Tor version that they are running to the directory
+authorities. The following graph shows the number of relays by
+version.</p>
+<a id="versions" />
+<%
+StringBuilder versionsUrl = new StringBuilder("versions.png");
+if ("versions".equals(request.getParameter("graph"))) {
+ List<String> parameters = new ArrayList<String>();
+// TODO check values here!
+ String startParameter = request.getParameter("start"),
+ endParameter = request.getParameter("end");
+ if (startParameter != null && startParameter.length() > 0) {
+ parameters.add("start=" + startParameter);
+ }
+ if (endParameter != null && endParameter.length() > 0) {
+ parameters.add("end=" + endParameter);
+ }
+ if (parameters.size() > 0) {
+ versionsUrl.append("?" + parameters.get(0));
+ if (parameters.size() > 1) {
+ for (int i = 1; i < parameters.size(); i++) {
+ versionsUrl.append("&" + parameters.get(i));
+ }
+ }
+ }
+}
+out.println("<img src=\"" + versionsUrl.toString() + "\" width=\"576\" "
+ + "height=\"360\" />");
+%>
+</p>
+<form action="network.html#versions">
+ <div class="formrow">
+ <input type="hidden" name="graph" value="versions"/>
+ <p>
+ <label class="startend" for="start">Start date (yyyy-mm-dd):</label>
+ <input type="text" name="start" id="start" size="10"
+ value="<%=("versions".equals(request.getParameter("graph")) &&
+ request.getParameter("start") != null) ?
+ request.getParameter("start") : ""%>"/>
+ <label class="startend" for="end">End date (yyyy-mm-dd):</label>
+ <input type="text" name="end" id="end" size="10"
+ value="<%=("versions".equals(request.getParameter("graph")) &&
+ request.getParameter("end") != null) ?
+ request.getParameter("end") : ""%>"/>
+ </p><p>
+ <input class="submit" type="submit" value="Update graph"/>
+ </p>
+ </div>
+</form>
+<br/>
+
+<h3>Relays by platform</h3>
+<br/>
+<p>Relays report the operating system they are running to the directory
+authorities. The following graph shows the number of relays by
+platform.</p>
+<a id="platforms" />
+<%
+StringBuilder platformsUrl = new StringBuilder("platforms.png");
+if ("platforms".equals(request.getParameter("graph"))) {
+ List<String> parameters = new ArrayList<String>();
+// TODO check values here!
+ String startParameter = request.getParameter("start"),
+ endParameter = request.getParameter("end");
+ if (startParameter != null && startParameter.length() > 0) {
+ parameters.add("start=" + startParameter);
+ }
+ if (endParameter != null && endParameter.length() > 0) {
+ parameters.add("end=" + endParameter);
+ }
+ if (parameters.size() > 0) {
+ platformsUrl.append("?" + parameters.get(0));
+ if (parameters.size() > 1) {
+ for (int i = 1; i < parameters.size(); i++) {
+ platformsUrl.append("&" + parameters.get(i));
+ }
+ }
+ }
+}
+out.println("<img src=\"" + platformsUrl.toString() + "\" width=\"576\" "
+ + "height=\"360\" />");
+%>
+</p>
+<form action="network.html#platforms">
+ <div class="formrow">
+ <input type="hidden" name="graph" value="platforms"/>
+ <p>
+ <label class="startend" for="start">Start date (yyyy-mm-dd):</label>
+ <input type="text" name="start" id="start" size="10"
+ value="<%=("platforms".equals(request.getParameter("graph")) &&
+ request.getParameter("start") != null) ?
+ request.getParameter("start") : ""%>"/>
+ <label class="startend" for="end">End date (yyyy-mm-dd):</label>
+ <input type="text" name="end" id="end" size="10"
+ value="<%=("platforms".equals(request.getParameter("graph")) &&
+ request.getParameter("end") != null) ?
+ request.getParameter("end") : ""%>"/>
+ </p><p>
+ <input class="submit" type="submit" value="Update graph"/>
+ </p>
+ </div>
+</form>
+<br/>
+
+<h3>Total relay bandwidth in the network</h3>
+<br/>
+<p>Relays report how much bandwidth they are willing to contribute and how
+many bytes they have read and written in the past 24 hours. The following
+graph shows total advertised bandwidth and bandwidth history of all relays
+in the network.</p>
+<a id="bandwidth" />
+<%
+StringBuilder bandwidthUrl = new StringBuilder("bandwidth.png");
+if ("bandwidth".equals(request.getParameter("graph"))) {
+ List<String> parameters = new ArrayList<String>();
+// TODO check values here!
+ String startParameter = request.getParameter("start"),
+ endParameter = request.getParameter("end");
+ if (startParameter != null && startParameter.length() > 0) {
+ parameters.add("start=" + startParameter);
+ }
+ if (endParameter != null && endParameter.length() > 0) {
+ parameters.add("end=" + endParameter);
+ }
+ if (parameters.size() > 0) {
+ bandwidthUrl.append("?" + parameters.get(0));
+ if (parameters.size() > 1) {
+ for (int i = 1; i < parameters.size(); i++) {
+ bandwidthUrl.append("&" + parameters.get(i));
+ }
+ }
+ }
+}
+out.println("<img src=\"" + bandwidthUrl.toString() + "\" width=\"576\" "
+ + "height=\"360\" />");
+%>
+</p>
+<form action="network.html#bandwidth">
+ <div class="formrow">
+ <input type="hidden" name="graph" value="bandwidth"/>
+ <p>
+ <label class="startend" for="start">Start date (yyyy-mm-dd):</label>
+ <input type="text" name="start" id="start" size="10"
+ value="<%=("bandwidth".equals(request.getParameter("graph")) &&
+ request.getParameter("start") != null) ?
+ request.getParameter("start") : ""%>"/>
+ <label class="startend" for="end">End date (yyyy-mm-dd):</label>
+ <input type="text" name="end" id="end" size="10"
+ value="<%=("bandwidth".equals(request.getParameter("graph")) &&
+ request.getParameter("end") != null) ?
+ request.getParameter("end") : ""%>"/>
+ </p><p>
+ <input class="submit" type="submit" value="Update graph"/>
+ </p>
+ </div>
+</form>
+<br/>
+
diff --git a/war/WEB-INF/templates/graphs_new-users.tpl.jsp b/war/WEB-INF/templates/graphs_new-users.tpl.jsp
deleted file mode 100644
index e5c5f95..0000000
--- a/war/WEB-INF/templates/graphs_new-users.tpl.jsp
+++ /dev/null
@@ -1,68 +0,0 @@
-<%@page import="java.util.*" %>
- <h2>Tor Metrics Portal: Graphs</h2>
- <br/>
- <h3>New or returning, directly connecting Tor users</h3>
- <br/>
- <p>Users connecting to the Tor network for the first time request
- a list of running relays from one of currently seven directory
- authorities. Likewise, returning users whose network information is
- out of date connect to one of the directory authorities to
- download a fresh list of relays. The following graphs display an
- estimate of new or returning Tor users based on the requests as
- seen by gabelmoo, one of the directory authorities.</p>
- <ul>
- <li><a href="#total">All users</a></li>
- <li><a href="#australia">Australia</a></li>
- <li><a href="#bahrain">Bahrain</a></li>
- <li><a href="#brazil">Brazil</a></li>
- <li><a href="#burma">Burma</a></li>
- <li><a href="#canada">Canada</a></li>
- <li><a href="#china">China</a></li>
- <li><a href="#cuba">Cuba</a></li>
- <li><a href="#ethiopia">Ethiopia</a></li>
- <li><a href="#france">France</a></li>
- <li><a href="#germany">Germany</a></li>
- <li><a href="#iran">Iran</a></li>
- <li><a href="#italy">Italy</a></li>
- <li><a href="#japan">Japan</a></li>
- <li><a href="#poland">Poland</a></li>
- <li><a href="#russia">Russia</a></li>
- <li><a href="#saudi">Saudi</a></li>
- <li><a href="#southkorea">South Korea</a></li>
- <li><a href="#sweden">Sweden</a></li>
- <li><a href="#syria">Syria</a></li>
- <li><a href="#tunisia">Tunisia</a></li>
- <li><a href="#turkmenistan">Turkmenistan</a></li>
- <li><a href="#uk">U.K.</a></li>
- <li><a href="#usa">U.S.A.</a></li>
- <li><a href="#uzbekistan">Uzbekistan</a></li>
- <li><a href="#vietnam">Vietnam</a></li>
- <li><a href="#yemen">Yemen</a></li>
- </ul>
- <ul>
- <li><a href="csv/new-users.csv">CSV</a> file containing all
- data.</li>
- </ul>
-<%
- List<String> countries = Arrays.asList(("total,australia,bahrain,"
- + "brazil,burma,canada,china,cuba,ethiopia,france,germany,iran,"
- + "italy,japan,poland,russia,saudi,southkorea,sweden,syria,"
- + "tunisia,turkmenistan,uk,usa,uzbekistan,vietnam,yemen").
- split(","));
- List<String> suffixes = new ArrayList<String>(Arrays.asList(
- "30d,90d,180d,all".split(",")));
- Calendar now = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
- suffixes.add(String.format("%tY", now));
- suffixes.add(String.format("%1$tY-q%2$d", now,
- 1 + now.get(Calendar.MONTH) / 3));
- suffixes.add(String.format("%1$tY-%1$tm", now));
- for (String country : countries) {
- out.print(" <p><a id=\"" + country + "\"/>\n");
- for (String suffix : suffixes) {
- out.print(" <img src=\"graphs/new-users/" + country
- + "-new-" + suffix + ".png\"/>\n");
- }
- out.print(" </p>");
- }
-%>
- <br/>
diff --git a/war/WEB-INF/templates/graphs_packages.tpl.jsp b/war/WEB-INF/templates/graphs_packages.tpl.jsp
new file mode 100644
index 0000000..704dcc8
--- /dev/null
+++ b/war/WEB-INF/templates/graphs_packages.tpl.jsp
@@ -0,0 +1,71 @@
+<%@page import="java.util.*" %>
+<h2>Tor Metrics Portal: Downloaded Packages</h2>
+<br/>
+<h3>Packages requested from GetTor</h3>
+<br/>
+<p>GetTor allows users to fetch the Tor software via email. The following
+graph shows the number of packages requested from GetTor per day.</p>
+<p>
+<a id="gettor" />
+<%
+if ("gettor".equals(request.getParameter("graph"))) {
+ List<String> parameters = new ArrayList<String>();
+// TODO check values here!
+ String startParameter = request.getParameter("start"),
+ endParameter = request.getParameter("end"),
+ bundleParameter = request.getParameter("bundle");
+ if (startParameter != null && startParameter.length() > 0) {
+ parameters.add("start=" + startParameter);
+ }
+ if (endParameter != null && endParameter.length() > 0) {
+ parameters.add("end=" + endParameter);
+ }
+ if (bundleParameter != null && bundleParameter.length() > 0) {
+ parameters.add("bundle=" + bundleParameter);
+ }
+ StringBuilder url = new StringBuilder("gettor.png");
+ if (parameters.size() > 0) {
+ url.append("?" + parameters.get(0));
+ if (parameters.size() > 1) {
+ for (int i = 1; i < parameters.size(); i++) {
+ url.append("&" + parameters.get(i));
+ }
+ }
+ }
+ out.println("<img src=\"" + url.toString() + "\" width=\"576\" "
+ + "height=\"360\" />");
+} else {%>
+ <img src="gettor.png" width="576" height="360" />
+<%
+}
+%>
+</p>
+
+<form action="packages.html#gettor">
+ <div class="formrow">
+ <input type="hidden" name="graph" value="gettor"/>
+ <p>
+ <label class="startend" for="start">Start date (yyyy-mm-dd):</label>
+ <input type="text" name="start" id="start" size="10"
+ value="<%=("gettor".equals(request.getParameter("graph")) &&
+ request.getParameter("start") != null) ?
+ request.getParameter("start") : ""%>"/>
+ <label class="startend" for="end">End date (yyyy-mm-dd):</label>
+ <input type="text" name="end" id="end" size="10"
+ value="<%=("gettor".equals(request.getParameter("graph")) &&
+ request.getParameter("end") != null) ?
+ request.getParameter("end") : ""%>"/>
+ </p><p>
+ <label>Packages: </label>
+ <input type="radio" name="bundle" value="all"> Total packages</input>
+ <input type="radio" name="bundle" value="en"> TBB (en)</input>
+ <input type="radio" name="bundle" value="zh_CN"> TBB (zh_CN)</input>
+ <input type="radio" name="bundle" value="fa"> TBB (fa)</input>
+ </p><p>
+ <input class="submit" type="submit" value="Update graph"/>
+ </p>
+ </div>
+</form>
+
+<p><a href="csv/gettor.csv">CSV</a> file containing all data.</p>
+<br/>
diff --git a/war/WEB-INF/templates/graphs_performance.tpl.jsp b/war/WEB-INF/templates/graphs_performance.tpl.jsp
new file mode 100644
index 0000000..862b435
--- /dev/null
+++ b/war/WEB-INF/templates/graphs_performance.tpl.jsp
@@ -0,0 +1,80 @@
+<%@page import="java.util.*" %>
+<h2>Tor Metrics Portal: Performance</h2>
+<br/>
+<h3>Time to download files over Tor</h3>
+<br/>
+<p>The following graphs show the performance of the Tor network as
+experienced by its users. The graphs contain the average (median) time to
+request files of three different sizes over Tor as well as first and third
+quartile of request times.</p>
+<a id="torperf" />
+<%
+if ("torperf".equals(request.getParameter("graph"))) {
+ List<String> parameters = new ArrayList<String>();
+// TODO check values here!
+ String startParameter = request.getParameter("start"),
+ endParameter = request.getParameter("end"),
+ sourceParameter = request.getParameter("source"),
+ filesizeParameter = request.getParameter("filesize");
+ if (startParameter != null && startParameter.length() > 0) {
+ parameters.add("start=" + startParameter);
+ }
+ if (endParameter != null && endParameter.length() > 0) {
+ parameters.add("end=" + endParameter);
+ }
+ if (sourceParameter != null && sourceParameter.length() > 0) {
+ parameters.add("source=" + sourceParameter);
+ }
+ if (filesizeParameter != null && filesizeParameter.length() > 0) {
+ parameters.add("filesize=" + filesizeParameter);
+ }
+ StringBuilder url = new StringBuilder("torperf.png");
+ if (parameters.size() > 0) {
+ url.append("?" + parameters.get(0));
+ if (parameters.size() > 1) {
+ for (int i = 1; i < parameters.size(); i++) {
+ url.append("&" + parameters.get(i));
+ }
+ }
+ }
+ out.println("<img src=\"" + url.toString() + "\" width=\"576\" "
+ + "height=\"360\" />");
+} else {%>
+ <img src="torperf.png" width="576" height="360" />
+<%
+}
+%>
+
+</p>
+<form action="performance.html#torperf">
+ <div class="formrow">
+ <input type="hidden" name="graph" value="torperf"/>
+ <p>
+ <label class="startend" for="start">Start date (yyyy-mm-dd):</label>
+ <input type="text" name="start" id="start" size="10"
+ value="<%=("torperf".equals(request.getParameter("graph")) &&
+ request.getParameter("start") != null) ?
+ request.getParameter("start") : ""%>"/>
+ <label class="startend" for="end">End date (yyyy-mm-dd):</label>
+ <input type="text" name="end" id="end" size="10"
+ value="<%=("torperf".equals(request.getParameter("graph")) &&
+ request.getParameter("end") != null) ?
+ request.getParameter("end") : ""%>"/>
+ </p><p>
+ <label>Source: </label>
+ <input type="radio" name="source" value="torperf"> torperf</input>
+ <input type="radio" name="source" value="moria"> moria</input>
+ <input type="radio" name="source" value="siv"> siv</input>
+ </p><p>
+ <label>File size: </label>
+ <input type="radio" name="filesize" value="50kb"> 50 KiB</input>
+ <input type="radio" name="filesize" value="1mb"> 1 MiB</input>
+ <input type="radio" name="filesize" value="5mb"> 5 MiB</input>
+ </p><p>
+ <input class="submit" type="submit" value="Update graph"/>
+ </p>
+ </div>
+</form>
+
+<p><a href="csv/torperf.csv">CSV</a> file containing all data.</p>
+<br/>
diff --git a/war/WEB-INF/templates/graphs_recurring-users.tpl.jsp b/war/WEB-INF/templates/graphs_recurring-users.tpl.jsp
deleted file mode 100644
index 0235f02..0000000
--- a/war/WEB-INF/templates/graphs_recurring-users.tpl.jsp
+++ /dev/null
@@ -1,73 +0,0 @@
-<%@ page import="java.util.*" %>
- <h2>Tor Metrics Portal: Graphs</h2>
- <br/>
- <h3>Recurring, directly connecting Tor users</h3>
- <br/>
- <p>After being connected to the Tor network, users need to refresh
- their list of running relays on a regular basis. They send their
- requests to one out of a few hundred directory mirrors to save
- bandwidth of the directory authorities. The following graphs show
- an estimate of recurring Tor users based on the requests as seen
- by trusted, a particularly fast directory mirror.</p>
- <ul>
- <li><a href="#total">All users</a></li>
- <li><a href="#australia">Australia</a></li>
- <li><a href="#bahrain">Bahrain</a></li>
- <li><a href="#brazil">Brazil</a></li>
- <li><a href="#burma">Burma</a></li>
- <li><a href="#canada">Canada</a></li>
- <li><a href="#china">China</a></li>
- <li><a href="#cuba">Cuba</a></li>
- <li><a href="#ethiopia">Ethiopia</a></li>
- <li><a href="#france">France</a></li>
- <li><a href="#germany">Germany</a></li>
- <li><a href="#iran">Iran</a></li>
- <li><a href="#italy">Italy</a></li>
- <li><a href="#japan">Japan</a></li>
- <li><a href="#poland">Poland</a></li>
- <li><a href="#russia">Russia</a></li>
- <li><a href="#saudi">Saudi</a></li>
- <li><a href="#southkorea">South Korea</a></li>
- <li><a href="#sweden">Sweden</a></li>
- <li><a href="#syria">Syria</a></li>
- <li><a href="#tunisia">Tunisia</a></li>
- <li><a href="#turkmenistan">Turkmenistan</a></li>
- <li><a href="#uk">U.K.</a></li>
- <li><a href="#usa">U.S.A.</a></li>
- <li><a href="#uzbekistan">Uzbekistan</a></li>
- <li><a href="#vietnam">Vietnam</a></li>
- <li><a href="#yemen">Yemen</a></li>
- </ul>
- <ul>
- <li><a href="csv/recurring-users.csv">CSV</a> file containing
- all data.</li>
- <li><a href="csv/monthly-users-peak.csv">CSV</a> file containing
- peak daily Tor users (recurring and bridge) per month by
- country.</li>
- <li><a href="csv/monthly-users-average.csv">CSV</a> file
- containing average daily Tor users (recurring and bridge) per
- month by country.</li>
- </ul>
-<%
- List<String> countries = Arrays.asList(("total,australia,bahrain,"
- + "brazil,burma,canada,china,cuba,ethiopia,france,germany,iran,"
- + "italy,japan,poland,russia,saudi,southkorea,sweden,syria,"
- + "tunisia,turkmenistan,uk,usa,uzbekistan,vietnam,yemen").
- split(","));
- List<String> suffixes = new ArrayList<String>(Arrays.asList(
- "30d,90d,180d,all".split(",")));
- Calendar now = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
- suffixes.add(String.format("%tY", now));
- suffixes.add(String.format("%1$tY-q%2$d", now,
- 1 + now.get(Calendar.MONTH) / 3));
- suffixes.add(String.format("%1$tY-%1$tm", now));
- for (String country : countries) {
- out.print(" <p><a id=\"" + country + "\"/>\n");
- for (String suffix : suffixes) {
- out.print(" <img src=\"graphs/direct-users/" + country
- + "-direct-" + suffix + ".png\"/>\n");
- }
- out.print(" </p>\n");
- }
-%>
- <br/>
diff --git a/war/WEB-INF/templates/graphs_torperf.tpl.jsp b/war/WEB-INF/templates/graphs_torperf.tpl.jsp
deleted file mode 100644
index f617240..0000000
--- a/war/WEB-INF/templates/graphs_torperf.tpl.jsp
+++ /dev/null
@@ -1,37 +0,0 @@
- <h2>Tor Metrics Portal: Graphs</h2>
- <br/>
- <h3>Time to complete requests</h3>
- <br/>
- <p>The following graphs show the performance of the Tor network as
- experienced by its users. The graphs contain the average (median)
- time to request files of three different sizes over the network as
- well as first and third quartile of request times.</p>
- <p><a href="csv/torperf.csv">CSV</a> file containing all data.</p>
- <img src="graphs/torperf/torperf-50kb-torperf-12m.png"/>
- <img src="graphs/torperf/torperf-50kb-moria-12m.png"/>
- <img src="graphs/torperf/torperf-50kb-siv-12m.png"/>
- <img src="graphs/torperf/torperf-50kb-torperf-6m.png"/>
- <img src="graphs/torperf/torperf-50kb-moria-6m.png"/>
- <img src="graphs/torperf/torperf-50kb-siv-6m.png"/>
- <img src="graphs/torperf/torperf-50kb-torperf-2w.png"/>
- <img src="graphs/torperf/torperf-50kb-moria-2w.png"/>
- <img src="graphs/torperf/torperf-50kb-siv-2w.png"/>
- <img src="graphs/torperf/torperf-1mb-torperf-12m.png"/>
- <img src="graphs/torperf/torperf-1mb-moria-12m.png"/>
- <img src="graphs/torperf/torperf-1mb-siv-12m.png"/>
- <img src="graphs/torperf/torperf-1mb-torperf-6m.png"/>
- <img src="graphs/torperf/torperf-1mb-moria-6m.png"/>
- <img src="graphs/torperf/torperf-1mb-siv-6m.png"/>
- <img src="graphs/torperf/torperf-1mb-torperf-2w.png"/>
- <img src="graphs/torperf/torperf-1mb-moria-2w.png"/>
- <img src="graphs/torperf/torperf-1mb-siv-2w.png"/>
- <img src="graphs/torperf/torperf-5mb-torperf-12m.png"/>
- <img src="graphs/torperf/torperf-5mb-moria-12m.png"/>
- <img src="graphs/torperf/torperf-5mb-siv-12m.png"/>
- <img src="graphs/torperf/torperf-5mb-torperf-6m.png"/>
- <img src="graphs/torperf/torperf-5mb-moria-6m.png"/>
- <img src="graphs/torperf/torperf-5mb-siv-6m.png"/>
- <img src="graphs/torperf/torperf-5mb-torperf-2w.png"/>
- <img src="graphs/torperf/torperf-5mb-moria-2w.png"/>
- <img src="graphs/torperf/torperf-5mb-siv-2w.png"/>
- <br/>
diff --git a/war/WEB-INF/templates/graphs_users.tpl.jsp b/war/WEB-INF/templates/graphs_users.tpl.jsp
new file mode 100644
index 0000000..d8ea449
--- /dev/null
+++ b/war/WEB-INF/templates/graphs_users.tpl.jsp
@@ -0,0 +1,292 @@
+<%@page import="java.util.*" %>
+<h2>Tor Metrics Portal: Users</h2>
+<br/>
+<h3>New or returning, directly connecting Tor users</h3>
+<br/>
+<p>Users connecting to the Tor network for the first time request a list
+of running relays from one of currently seven directory authorities.
+Likewise, returning users whose network information is out of date connect
+to one of the directory authorities to download a fresh list of relays.
+The following graphs display an estimate of new or returning Tor users
+based on the requests as seen by gabelmoo, one of the directory
+authorities.</p>
+<a id="new-users" />
+<%
+StringBuilder newUsersUrl = new StringBuilder("new-users.png");
+if ("new-users".equals(request.getParameter("graph"))) {
+ List<String> parameters = new ArrayList<String>();
+// TODO check values here!
+ String startParameter = request.getParameter("start"),
+ endParameter = request.getParameter("end");
+ String[] countryParameters = request.getParameterValues("country");
+ if (startParameter != null && startParameter.length() > 0) {
+ parameters.add("start=" + startParameter);
+ }
+ if (endParameter != null && endParameter.length() > 0) {
+ parameters.add("end=" + endParameter);
+ }
+ if (countryParameters != null && countryParameters.length > 0) {
+ for (String country : countryParameters) {
+ if (country != null && country.length() > 0) {
+ parameters.add("country=" + country);
+ }
+ }
+ }
+ if (parameters.size() > 0) {
+ newUsersUrl.append("?" + parameters.get(0));
+ if (parameters.size() > 1) {
+ for (int i = 1; i < parameters.size(); i++) {
+ newUsersUrl.append("&" + parameters.get(i));
+ }
+ }
+ }
+}
+out.println("<img src=\"" + newUsersUrl.toString() + "\" width=\"576\" "
+ + "height=\"360\" />");
+%>
+</p>
+<form action="users.html#new-users">
+ <div class="formrow">
+ <input type="hidden" name="graph" value="new-users"/>
+ <p>
+ <label class="startend" for="start">Start date (yyyy-mm-dd):</label>
+ <input type="text" name="start" id="start" size="10"
+ value="<%=("new-users".equals(request.getParameter("graph")) &&
+ request.getParameter("start") != null) ?
+ request.getParameter("start") : ""%>"/>
+ <label class="startend" for="end">End date (yyyy-mm-dd):</label>
+ <input type="text" name="end" id="end" size="10"
+ value="<%=("new-users".equals(request.getParameter("graph")) &&
+ request.getParameter("end") != null) ?
+ request.getParameter("end") : ""%>"/>
+ </p><p>
+ <label>Source: </label>
+ <input type="radio" name="country" value="all">All users</input>
+ <input type="radio" name="country" value="au">Australia</input>
+ <input type="radio" name="country" value="bh">Bahrain</input>
+ <input type="radio" name="country" value="br">Brazil</input>
+ <input type="radio" name="country" value="ca">Canada</input>
+ <input type="radio" name="country" value="cn">China</input>
+ <input type="radio" name="country" value="cu">Cuba</input>
+ <input type="radio" name="country" value="de">Germany</input>
+ <input type="radio" name="country" value="et">Ethiopia</input>
+ <input type="radio" name="country" value="fr">France</input>
+ <input type="radio" name="country" value="gb">U.K.</input>
+ <input type="radio" name="country" value="ir">Iran</input>
+ <input type="radio" name="country" value="it">Italy</input>
+ <input type="radio" name="country" value="jp">Japan</input>
+ <input type="radio" name="country" value="kr">South Korea</input>
+ <input type="radio" name="country" value="mm">Burma</input>
+ <input type="radio" name="country" value="pl">Poland</input>
+ <input type="radio" name="country" value="ru">Russia</input>
+ <input type="radio" name="country" value="sa">Saudi Arabia</input>
+ <input type="radio" name="country" value="se">Sweden</input>
+ <input type="radio" name="country" value="sy">Syria</input>
+ <input type="radio" name="country" value="tn">Tunisia</input>
+ <input type="radio" name="country" value="tm">Turkmenistan</input>
+ <input type="radio" name="country" value="us">U.S.A.</input>
+ <input type="radio" name="country" value="uz">Uzbekistan</input>
+ <input type="radio" name="country" value="vn">Vietnam</input>
+ <input type="radio" name="country" value="ye">Yemen</input>
+ </p><p>
+ <input class="submit" type="submit" value="Update graph"/>
+ </p>
+ </div>
+</form>
+<p><a href="csv/new-users.csv">CSV</a> file containing all data.</p>
+<br/>
+
+<h3>Recurring, directly connecting Tor users</h3>
+<br/>
+<p>After being connected to the Tor network, users need to refresh their
+list of running relays on a regular basis. They send their requests to one
+out of a few hundred directory mirrors to save bandwidth of the directory
+authorities. The following graphs show an estimate of recurring Tor users
+based on the requests as seen by trusted, a particularly fast directory
+mirror.</p>
+<a id="direct-users" />
+<%
+StringBuilder directUsersUrl = new StringBuilder("direct-users.png");
+if ("direct-users".equals(request.getParameter("graph"))) {
+ List<String> parameters = new ArrayList<String>();
+// TODO check values here!
+ String startParameter = request.getParameter("start"),
+ endParameter = request.getParameter("end");
+ String[] countryParameters = request.getParameterValues("country");
+ if (startParameter != null && startParameter.length() > 0) {
+ parameters.add("start=" + startParameter);
+ }
+ if (endParameter != null && endParameter.length() > 0) {
+ parameters.add("end=" + endParameter);
+ }
+ if (countryParameters != null && countryParameters.length > 0) {
+ for (String country : countryParameters) {
+ if (country != null && country.length() > 0) {
+ parameters.add("country=" + country);
+ }
+ }
+ }
+ if (parameters.size() > 0) {
+ directUsersUrl.append("?" + parameters.get(0));
+ if (parameters.size() > 1) {
+ for (int i = 1; i < parameters.size(); i++) {
+ directUsersUrl.append("&" + parameters.get(i));
+ }
+ }
+ }
+}
+out.println("<img src=\"" + directUsersUrl.toString() + "\" width=\"576\" "
+ + "height=\"360\" />");
+%>
+</p>
+<form action="users.html#direct-users">
+ <div class="formrow">
+ <input type="hidden" name="graph" value="direct-users"/>
+ <p>
+ <label class="startend" for="start">Start date (yyyy-mm-dd):</label>
+ <input type="text" name="start" id="start" size="10"
+ value="<%=("direct-users".equals(request.getParameter("graph")) &&
+ request.getParameter("start") != null) ?
+ request.getParameter("start") : ""%>"/>
+ <label class="startend" for="end">End date (yyyy-mm-dd):</label>
+ <input type="text" name="end" id="end" size="10"
+ value="<%=("direct-users".equals(request.getParameter("graph")) &&
+ request.getParameter("end") != null) ?
+ request.getParameter("end") : ""%>"/>
+ </p><p>
+ <label>Source: </label>
+ <input type="radio" name="country" value="all">All users</input>
+ <input type="radio" name="country" value="au">Australia</input>
+ <input type="radio" name="country" value="bh">Bahrain</input>
+ <input type="radio" name="country" value="br">Brazil</input>
+ <input type="radio" name="country" value="ca">Canada</input>
+ <input type="radio" name="country" value="cn">China</input>
+ <input type="radio" name="country" value="cu">Cuba</input>
+ <input type="radio" name="country" value="de">Germany</input>
+ <input type="radio" name="country" value="et">Ethiopia</input>
+ <input type="radio" name="country" value="fr">France</input>
+ <input type="radio" name="country" value="gb">U.K.</input>
+ <input type="radio" name="country" value="ir">Iran</input>
+ <input type="radio" name="country" value="it">Italy</input>
+ <input type="radio" name="country" value="jp">Japan</input>
+ <input type="radio" name="country" value="kr">South Korea</input>
+ <input type="radio" name="country" value="mm">Burma</input>
+ <input type="radio" name="country" value="pl">Poland</input>
+ <input type="radio" name="country" value="ru">Russia</input>
+ <input type="radio" name="country" value="sa">Saudi Arabia</input>
+ <input type="radio" name="country" value="se">Sweden</input>
+ <input type="radio" name="country" value="sy">Syria</input>
+ <input type="radio" name="country" value="tn">Tunisia</input>
+ <input type="radio" name="country" value="tm">Turkmenistan</input>
+ <input type="radio" name="country" value="us">U.S.A.</input>
+ <input type="radio" name="country" value="uz">Uzbekistan</input>
+ <input type="radio" name="country" value="vn">Vietnam</input>
+ <input type="radio" name="country" value="ye">Yemen</input>
+ </p><p>
+ <input class="submit" type="submit" value="Update graph"/>
+ </p>
+ </div>
+</form>
+<p><a href="csv/direct-users.csv">CSV</a> file containing all data.</p>
+<p><a href="csv/monthly-users-peak.csv">CSV</a> file containing peak daily
+Tor users (recurring and bridge) per month by country.</p>
+<p><a href="csv/monthly-users-average.csv">CSV</a> file containing average
+daily Tor users (recurring and bridge) per month by country.</p>
+<br/>
+
+<h3>Tor users via bridges</h3>
+<br/>
+<p>Users who cannot connect directly to the Tor network instead connect
+via bridges, which are non-public relays. The following graphs display an
+estimate of Tor users via bridges based on the unique IP addresses as seen
+by a few hundred bridges.</p>
+<a id="bridge-users" />
+<%
+StringBuilder bridgeUsersUrl = new StringBuilder("bridge-users.png");
+if ("bridge-users".equals(request.getParameter("graph"))) {
+ List<String> parameters = new ArrayList<String>();
+// TODO check values here!
+ String startParameter = request.getParameter("start"),
+ endParameter = request.getParameter("end");
+ String[] countryParameters = request.getParameterValues("country");
+ if (startParameter != null && startParameter.length() > 0) {
+ parameters.add("start=" + startParameter);
+ }
+ if (endParameter != null && endParameter.length() > 0) {
+ parameters.add("end=" + endParameter);
+ }
+ if (countryParameters != null && countryParameters.length > 0) {
+ for (String country : countryParameters) {
+ if (country != null && country.length() > 0) {
+ parameters.add("country=" + country);
+ }
+ }
+ }
+ if (parameters.size() > 0) {
+ bridgeUsersUrl.append("?" + parameters.get(0));
+ if (parameters.size() > 1) {
+ for (int i = 1; i < parameters.size(); i++) {
+ bridgeUsersUrl.append("&" + parameters.get(i));
+ }
+ }
+ }
+}
+out.println("<img src=\"" + bridgeUsersUrl.toString() + "\" width=\"576\" "
+ + "height=\"360\" />");
+%>
+</p>
+<form action="users.html#bridge-users">
+ <div class="formrow">
+ <input type="hidden" name="graph" value="bridge-users"/>
+ <p>
+ <label class="startend" for="start">Start date (yyyy-mm-dd):</label>
+ <input type="text" name="start" id="start" size="10"
+ value="<%=("bridge-users".equals(request.getParameter("graph")) &&
+ request.getParameter("start") != null) ?
+ request.getParameter("start") : ""%>"/>
+ <label class="startend" for="end">End date (yyyy-mm-dd):</label>
+ <input type="text" name="end" id="end" size="10"
+ value="<%=("bridge-users".equals(request.getParameter("graph")) &&
+ request.getParameter("end") != null) ?
+ request.getParameter("end") : ""%>"/>
+ </p><p>
+ <label>Source: </label>
+ <input type="radio" name="country" value="all">All users</input>
+ <input type="radio" name="country" value="au">Australia</input>
+ <input type="radio" name="country" value="bh">Bahrain</input>
+ <input type="radio" name="country" value="br">Brazil</input>
+ <input type="radio" name="country" value="ca">Canada</input>
+ <input type="radio" name="country" value="cn">China</input>
+ <input type="radio" name="country" value="cu">Cuba</input>
+ <input type="radio" name="country" value="de">Germany</input>
+ <input type="radio" name="country" value="et">Ethiopia</input>
+ <input type="radio" name="country" value="fr">France</input>
+ <input type="radio" name="country" value="gb">U.K.</input>
+ <input type="radio" name="country" value="ir">Iran</input>
+ <input type="radio" name="country" value="it">Italy</input>
+ <input type="radio" name="country" value="jp">Japan</input>
+ <input type="radio" name="country" value="kr">South Korea</input>
+ <input type="radio" name="country" value="mm">Burma</input>
+ <input type="radio" name="country" value="pl">Poland</input>
+ <input type="radio" name="country" value="ru">Russia</input>
+ <input type="radio" name="country" value="sa">Saudi Arabia</input>
+ <input type="radio" name="country" value="se">Sweden</input>
+ <input type="radio" name="country" value="sy">Syria</input>
+ <input type="radio" name="country" value="tn">Tunisia</input>
+ <input type="radio" name="country" value="tm">Turkmenistan</input>
+ <input type="radio" name="country" value="us">U.S.A.</input>
+ <input type="radio" name="country" value="uz">Uzbekistan</input>
+ <input type="radio" name="country" value="vn">Vietnam</input>
+ <input type="radio" name="country" value="ye">Yemen</input>
+ </p><p>
+ <input class="submit" type="submit" value="Update graph"/>
+ </p>
+ </div>
+</form>
+<p><a href="csv/bridge-users.csv">CSV</a> file containing all data.</p>
+<p><a href="csv/monthly-users-peak.csv">CSV</a> file containing peak daily
+Tor users (recurring and bridge) per month by country.</p>
+<p><a href="csv/monthly-users-average.csv">CSV</a> file containing average
+daily Tor users (recurring and bridge) per month by country.</p>
+<br/>
+
diff --git a/war/WEB-INF/templates/index.tpl.jsp b/war/WEB-INF/templates/index.tpl.jsp
index 8bf9132..f3c5472 100644
--- a/war/WEB-INF/templates/index.tpl.jsp
+++ b/war/WEB-INF/templates/index.tpl.jsp
@@ -20,58 +20,22 @@
<br/>
<h3>News</h3>
<ul>
- <li>September 9, 2010: <a href="custom-graph.html">Custom
- graphs</a> on network size, relay platforms, versions, and
+ <li>October 7, 2010: Custom graphs are now available for all
+ <a href="graphs.html">graphs</a>. Based on work by Kevin
+ Berry.</li>
+ <li>September 9, 2010: Custom
+ graphs on network size, relay platforms, versions, and
observed bandwidth available. Implemented by Kevin Berry.</li>
<li>September 2, 2010: New <a href="relay-search.html">relay
search</a> feature available.</li>
<li>August 31, 2010: Named relays can now be found more easily
on the consensus-health page by using anchors, e.g.,
<a href="consensus-health.html#gabelmoo">https://metrics.torproject.org/consensus-health.html#gabelmoo</a> .</li>
- <li>August 16, 2010: There are now graphs for total
- <a href="new-users-graphs.html">new or returning</a> and
- <a href="recurring-users-graphs.html">recurring</a> directly
- connecting users and total
- <a href="bridge-users-graphs.html">bridge users</a> as well as
+ <li>August 16, 2010: There are now
+ <a href="users.html">graphs</a> for total new or returning and
+ recurring directly connecting users and total bridge users as
+ well as
for users coming from Australia, Brazil, Canada, France,
Germany, Italy, Japan, Poland, Russia, South Korea, Sweden,
U.K., and U.S.A.</li>
- <li>June 7, 2010: The <a href="exonerator.html">ExoneraTor</a>
- now uses the most recent network information as its data basis
- (as opposed to monthly snapshots). As a by-product,
- <a href="consensus?valid-after=2010-06-01-12-00-00">network
- status consensuses</a> and <a href="serverdesc?desc-id=b7461d591738b4c7d54393acde0efc6d66d1e7fc">server
- descriptors</a> are now browsable by valid-after time and
- descriptor digest, respectively. More sophisticated descriptor
- search functions will follow.</li>
- <li>June 7, 2010: The <a href="torperf-graphs.html">graphs on
- user-experienced download times</a> are now drawn using
- (a modified) <a href="http://had.co.nz/ggplot2/">ggplot2</a>.
- Modifications to ggplot2 include
- <a href="https://stat.ethz.ch/pipermail/r-help/2010-June/241559.html">drawing
- a ribbon only for intervals with non-NA values</a> and
- <a href="https://stat.ethz.ch/pipermail/r-help/2010-June/241618.html">positioning
- the legend at the top of a graph</a>. This concludes the
- transition to ggplot2 and will greatly facilitate dynamic graph
- generation in the future.</li>
- <li>May 26, 2010: The monthly
- <a href="data.html#relaydesc">relay</a> and
- <a href="data.html#bridgedesc">bridge descriptor tarballs</a>
- are now updated every day. Beginning with May 2010, the bridge
- descriptor tarballs do not contain country codes anymore,
- because it was tough to maintain. If your research requires this
- or any other detail, contact us and we'll sort something out.
- <li>May 25, 2010: The
- <a href="bridge-users-graphs.html">graphs on daily bridge users</a>
- are now more
- accurate by excluding broken "geoip-stats" data of 0.2.2.x
- versions and including "bridge-stats" data of bridges running
- 0.2.2.7-alpha or higher.</li>
- <li>May 19, 2010: The graphs on
- <a href="recurring-users-graphs.html">recurring users</a> and
- <a href="bridge-users-graphs.html">bridge users</a> are now
- accompanied by CSV files containing
- <a href="csv/monthly-users-peak.csv">peak</a> and
- <a href="csv/monthly-users-average.csv">average</a>
- daily users per month by country.</li>
</ul>
diff --git a/war/WEB-INF/templates/status.tpl.jsp b/war/WEB-INF/templates/status.tpl.jsp
index 9470edb..760efcf 100644
--- a/war/WEB-INF/templates/status.tpl.jsp
+++ b/war/WEB-INF/templates/status.tpl.jsp
@@ -9,6 +9,3 @@
descriptor archive for a relay, and the
<a href="consensus-health.html">Consensus Health</a> summarizes
information about the latest network consensus voting process.
- The <a href="log.html">Last Log</a> of the metrics portal software
- execution also falls under this category to evaluate how recent
- and complete the presented data are.
diff --git a/war/WEB-INF/urlrewrite.xml b/war/WEB-INF/urlrewrite.xml
index 349793f..6c8b654 100644
--- a/war/WEB-INF/urlrewrite.xml
+++ b/war/WEB-INF/urlrewrite.xml
@@ -31,36 +31,20 @@
<to>/status.jsp</to>
</rule>
<rule>
- <from>/consensus-graphs.html</from>
- <to>/consensus-graphs.jsp</to>
+ <from>/network.html</from>
+ <to>/network.jsp</to>
</rule>
<rule>
- <from>/exit-relays-graphs.html</from>
- <to>/exit-relays-graphs.jsp</to>
+ <from>/users.html</from>
+ <to>/users.jsp</to>
</rule>
<rule>
- <from>/new-users-graphs.html</from>
- <to>/new-users-graphs.jsp</to>
+ <from>/packages.html</from>
+ <to>/packages.jsp</to>
</rule>
<rule>
- <from>/recurring-users-graphs.html</from>
- <to>/recurring-users-graphs.jsp</to>
- </rule>
- <rule>
- <from>/bridge-users-graphs.html</from>
- <to>/bridge-users-graphs.jsp</to>
- </rule>
- <rule>
- <from>/torperf-graphs.html</from>
- <to>/torperf-graphs.jsp</to>
- </rule>
- <rule>
- <from>/gettor-graphs.html</from>
- <to>/gettor-graphs.jsp</to>
- </rule>
- <rule>
- <from>/custom-graph.html</from>
- <to>/custom-graph.jsp</to>
+ <from>/performance.html</from>
+ <to>/performance.jsp</to>
</rule>
<rule>
<from>/papers.html</from>
diff --git a/war/WEB-INF/web.xml b/war/WEB-INF/web.xml
index ed0ce53..be2137a 100644
--- a/war/WEB-INF/web.xml
+++ b/war/WEB-INF/web.xml
@@ -127,10 +127,6 @@
</servlet>
<servlet-mapping>
<servlet-name>ErnieGeneratedFile</servlet-name>
- <url-pattern>/log.html</url-pattern>
- </servlet-mapping>
- <servlet-mapping>
- <servlet-name>ErnieGeneratedFile</servlet-name>
<url-pattern>/consensus-health.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
diff --git a/war/bridge-users-graphs.jsp b/war/bridge-users-graphs.jsp
deleted file mode 100644
index 50278a0..0000000
--- a/war/bridge-users-graphs.jsp
+++ /dev/null
@@ -1,4 +0,0 @@
-<jsp:useBean id="template" class="org.torproject.ernie.web.TemplateController" scope="request" />
-<jsp:setProperty name="template" property="template" value="graphs_bridge-users"/>
-<jsp:setProperty name="template" property="title" value="Tor Metrics Portal: Graphs"/>
-<%@ include file="/WEB-INF/templates/main.tpl.jsp" %>
diff --git a/war/consensus-graphs.jsp b/war/consensus-graphs.jsp
deleted file mode 100644
index 028bf41..0000000
--- a/war/consensus-graphs.jsp
+++ /dev/null
@@ -1,4 +0,0 @@
-<jsp:useBean id="template" class="org.torproject.ernie.web.TemplateController" scope="request" />
-<jsp:setProperty name="template" property="template" value="graphs_network-size"/>
-<jsp:setProperty name="template" property="title" value="Tor Metrics Portal: Graphs"/>
-<%@ include file="/WEB-INF/templates/main.tpl.jsp" %>
diff --git a/war/custom-graph.jsp b/war/custom-graph.jsp
deleted file mode 100644
index ef9faf4..0000000
--- a/war/custom-graph.jsp
+++ /dev/null
@@ -1,6 +0,0 @@
-<jsp:useBean id="template" class="org.torproject.ernie.web.TemplateController" scope="request" />
-<jsp:useBean id="customgraph" class="org.torproject.ernie.web.CustomGraphController" scope="request" />
-<jsp:setProperty name="customgraph" property="parameterMap" value="<%=request.getParameterMap()%>" />
-<jsp:setProperty name="template" property="template" value="graphs_custom-graph"/>
-<jsp:setProperty name="template" property="title" value="Tor Metrics Portal: Custom Graph"/>
-<%@ include file="/WEB-INF/templates/main.tpl.jsp" %>
diff --git a/war/exit-relays-graphs.jsp b/war/exit-relays-graphs.jsp
deleted file mode 100644
index 0a4c393..0000000
--- a/war/exit-relays-graphs.jsp
+++ /dev/null
@@ -1,4 +0,0 @@
-<jsp:useBean id="template" class="org.torproject.ernie.web.TemplateController" scope="request" />
-<jsp:setProperty name="template" property="template" value="graphs_exit-relays"/>
-<jsp:setProperty name="template" property="title" value="Tor Metrics Portal: Graphs"/>
-<%@ include file="/WEB-INF/templates/main.tpl.jsp" %>
diff --git a/war/gettor-graphs.jsp b/war/gettor-graphs.jsp
deleted file mode 100644
index 0d7d7c4..0000000
--- a/war/gettor-graphs.jsp
+++ /dev/null
@@ -1,4 +0,0 @@
-<jsp:useBean id="template" class="org.torproject.ernie.web.TemplateController" scope="request" />
-<jsp:setProperty name="template" property="template" value="graphs_gettor"/>
-<jsp:setProperty name="template" property="title" value="Tor Metrics Portal: Graphs"/>
-<%@ include file="/WEB-INF/templates/main.tpl.jsp" %>
diff --git a/war/network.jsp b/war/network.jsp
new file mode 100644
index 0000000..e144505
--- /dev/null
+++ b/war/network.jsp
@@ -0,0 +1,4 @@
+<jsp:useBean id="template" class="org.torproject.ernie.web.TemplateController" scope="request" />
+<jsp:setProperty name="template" property="template" value="graphs_network"/>
+<jsp:setProperty name="template" property="title" value="Tor Metrics Portal: Network"/>
+<%@ include file="/WEB-INF/templates/main.tpl.jsp" %>
diff --git a/war/new-users-graphs.jsp b/war/new-users-graphs.jsp
deleted file mode 100644
index 60469e3..0000000
--- a/war/new-users-graphs.jsp
+++ /dev/null
@@ -1,4 +0,0 @@
-<jsp:useBean id="template" class="org.torproject.ernie.web.TemplateController" scope="request" />
-<jsp:setProperty name="template" property="template" value="graphs_new-users"/>
-<jsp:setProperty name="template" property="title" value="Tor Metrics Portal: Graphs"/>
-<%@ include file="/WEB-INF/templates/main.tpl.jsp" %>
diff --git a/war/packages.jsp b/war/packages.jsp
new file mode 100644
index 0000000..904b248
--- /dev/null
+++ b/war/packages.jsp
@@ -0,0 +1,4 @@
+<jsp:useBean id="template" class="org.torproject.ernie.web.TemplateController" scope="request" />
+<jsp:setProperty name="template" property="template" value="graphs_packages"/>
+<jsp:setProperty name="template" property="title" value="Tor Metrics Portal: Packages"/>
+<%@ include file="/WEB-INF/templates/main.tpl.jsp" %>
diff --git a/war/performance.jsp b/war/performance.jsp
new file mode 100644
index 0000000..56204b4
--- /dev/null
+++ b/war/performance.jsp
@@ -0,0 +1,4 @@
+<jsp:useBean id="template" class="org.torproject.ernie.web.TemplateController" scope="request" />
+<jsp:setProperty name="template" property="template" value="graphs_performance"/>
+<jsp:setProperty name="template" property="title" value="Tor Metrics Portal: Performance"/>
+<%@ include file="/WEB-INF/templates/main.tpl.jsp" %>
diff --git a/war/recurring-users-graphs.jsp b/war/recurring-users-graphs.jsp
deleted file mode 100644
index 2b6230a..0000000
--- a/war/recurring-users-graphs.jsp
+++ /dev/null
@@ -1,4 +0,0 @@
-<jsp:useBean id="template" class="org.torproject.ernie.web.TemplateController" scope="request" />
-<jsp:setProperty name="template" property="template" value="graphs_recurring-users"/>
-<jsp:setProperty name="template" property="title" value="Tor Metrics Portal: Graphs"/>
-<%@ include file="/WEB-INF/templates/main.tpl.jsp" %>
diff --git a/war/torperf-graphs.jsp b/war/torperf-graphs.jsp
deleted file mode 100644
index 5cc8a62..0000000
--- a/war/torperf-graphs.jsp
+++ /dev/null
@@ -1,4 +0,0 @@
-<jsp:useBean id="template" class="org.torproject.ernie.web.TemplateController" scope="request" />
-<jsp:setProperty name="template" property="template" value="graphs_torperf"/>
-<jsp:setProperty name="template" property="title" value="Tor Metrics Portal: Graphs"/>
-<%@ include file="/WEB-INF/templates/main.tpl.jsp" %>
diff --git a/war/users.jsp b/war/users.jsp
new file mode 100644
index 0000000..bb0c143
--- /dev/null
+++ b/war/users.jsp
@@ -0,0 +1,4 @@
+<jsp:useBean id="template" class="org.torproject.ernie.web.TemplateController" scope="request" />
+<jsp:setProperty name="template" property="template" value="graphs_users"/>
+<jsp:setProperty name="template" property="title" value="Tor Metrics Portal: Users"/>
+<%@ include file="/WEB-INF/templates/main.tpl.jsp" %>
--
1.7.1