[tor-commits] [metrics-web/master] Add graph download links for PDF and SVG.

karsten at torproject.org karsten at torproject.org
Sat Oct 20 20:51:23 UTC 2012


commit b415e8d0cf55993d2c600b4dd51cfe6c4d1b0830
Author: Karsten Loesing <karsten.loesing at gmx.net>
Date:   Sat Oct 20 16:39:23 2012 -0400

    Add graph download links for PDF and SVG.
    
    Implements #7050.
---
 etc/web.xml                                        |   87 ++++++++------------
 .../torproject/ernie/web/GraphImageServlet.java    |   16 ++--
 src/org/torproject/ernie/web/RObjectGenerator.java |   15 +++-
 web/WEB-INF/fast-exits.jsp                         |    6 ++
 web/WEB-INF/network.jsp                            |   30 +++++++
 web/WEB-INF/performance.jsp                        |    9 ++
 web/WEB-INF/users.jsp                              |    6 ++
 7 files changed, 108 insertions(+), 61 deletions(-)

diff --git a/etc/web.xml b/etc/web.xml
index ccf6dd2..903f23d 100644
--- a/etc/web.xml
+++ b/etc/web.xml
@@ -158,74 +158,59 @@
   <servlet-mapping>
     <servlet-name>GraphImage</servlet-name>
     <url-pattern>/networksize.png</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>GraphImage</servlet-name>
+    <url-pattern>/networksize.pdf</url-pattern>
+    <url-pattern>/networksize.svg</url-pattern>
     <url-pattern>/cloudbridges.png</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>GraphImage</servlet-name>
+    <url-pattern>/cloudbridges.pdf</url-pattern>
+    <url-pattern>/cloudbridges.svg</url-pattern>
     <url-pattern>/relaycountries.png</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>GraphImage</servlet-name>
+    <url-pattern>/relaycountries.pdf</url-pattern>
+    <url-pattern>/relaycountries.svg</url-pattern>
     <url-pattern>/relayflags.png</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>GraphImage</servlet-name>
+    <url-pattern>/relayflags.pdf</url-pattern>
+    <url-pattern>/relayflags.svg</url-pattern>
     <url-pattern>/relayflags-hour.png</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>GraphImage</servlet-name>
+    <url-pattern>/relayflags-hour.pdf</url-pattern>
+    <url-pattern>/relayflags-hour.svg</url-pattern>
     <url-pattern>/versions.png</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>GraphImage</servlet-name>
+    <url-pattern>/versions.pdf</url-pattern>
+    <url-pattern>/versions.svg</url-pattern>
     <url-pattern>/platforms.png</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>GraphImage</servlet-name>
+    <url-pattern>/platforms.pdf</url-pattern>
+    <url-pattern>/platforms.svg</url-pattern>
     <url-pattern>/bandwidth.png</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>GraphImage</servlet-name>
+    <url-pattern>/bandwidth.pdf</url-pattern>
+    <url-pattern>/bandwidth.svg</url-pattern>
     <url-pattern>/bwhist-flags.png</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>GraphImage</servlet-name>
+    <url-pattern>/bwhist-flags.pdf</url-pattern>
+    <url-pattern>/bwhist-flags.svg</url-pattern>
     <url-pattern>/bandwidth-flags.png</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>GraphImage</servlet-name>
+    <url-pattern>/bandwidth-flags.pdf</url-pattern>
+    <url-pattern>/bandwidth-flags.svg</url-pattern>
     <url-pattern>/dirbytes.png</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>GraphImage</servlet-name>
+    <url-pattern>/dirbytes.pdf</url-pattern>
+    <url-pattern>/dirbytes.svg</url-pattern>
     <url-pattern>/direct-users.png</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>GraphImage</servlet-name>
+    <url-pattern>/direct-users.pdf</url-pattern>
+    <url-pattern>/direct-users.svg</url-pattern>
     <url-pattern>/bridge-users.png</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>GraphImage</servlet-name>
+    <url-pattern>/bridge-users.pdf</url-pattern>
+    <url-pattern>/bridge-users.svg</url-pattern>
     <url-pattern>/torperf.png</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>GraphImage</servlet-name>
+    <url-pattern>/torperf.pdf</url-pattern>
+    <url-pattern>/torperf.svg</url-pattern>
     <url-pattern>/torperf-failures.png</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>GraphImage</servlet-name>
+    <url-pattern>/torperf-failures.pdf</url-pattern>
+    <url-pattern>/torperf-failures.svg</url-pattern>
     <url-pattern>/connbidirect.png</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>GraphImage</servlet-name>
+    <url-pattern>/connbidirect.pdf</url-pattern>
+    <url-pattern>/connbidirect.svg</url-pattern>
     <url-pattern>/fast-exits.png</url-pattern>
-  </servlet-mapping>
-  <servlet-mapping>
-    <servlet-name>GraphImage</servlet-name>
+    <url-pattern>/fast-exits.pdf</url-pattern>
+    <url-pattern>/fast-exits.svg</url-pattern>
     <url-pattern>/almost-fast-exits.png</url-pattern>
+    <url-pattern>/almost-fast-exits.pdf</url-pattern>
+    <url-pattern>/almost-fast-exits.svg</url-pattern>
   </servlet-mapping>
 
   <servlet>
diff --git a/src/org/torproject/ernie/web/GraphImageServlet.java b/src/org/torproject/ernie/web/GraphImageServlet.java
index 5777172..ea24d44 100644
--- a/src/org/torproject/ernie/web/GraphImageServlet.java
+++ b/src/org/torproject/ernie/web/GraphImageServlet.java
@@ -34,11 +34,15 @@ public class GraphImageServlet extends HttpServlet {
       ServletException {
 
     /* Find out which graph type was requested and make sure we know this
-     * graph type. */
+     * graph type and file type. */
     String requestedGraph = request.getRequestURI();
-    if (requestedGraph.endsWith(".png")) {
+    String fileType = null;
+    if (requestedGraph.endsWith(".png") ||
+        requestedGraph.endsWith(".pdf") ||
+        requestedGraph.endsWith(".svg")) {
+      fileType = requestedGraph.substring(requestedGraph.length() - 3);
       requestedGraph = requestedGraph.substring(0, requestedGraph.length()
-          - ".png".length());
+          - 4);
     }
     if (requestedGraph.contains("/")) {
       requestedGraph = requestedGraph.substring(requestedGraph.
@@ -48,17 +52,17 @@ public class GraphImageServlet extends HttpServlet {
     /* Request graph from R object generator, which either returns it from
      * its cache or asks Rserve to generate it. */
     RObject graph = rObjectGenerator.generateGraph(requestedGraph,
-        request.getParameterMap(), true);
+        fileType, request.getParameterMap(), true);
 
     /* Make sure that we have a graph to return. */
-    if (graph == null || graph.getBytes() == null) {
+    if (graph == null || graph.getBytes() == null || fileType == null) {
       response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
       return;
     }
 
     /* Write graph bytes to response. */
     BufferedOutputStream output = null;
-    response.setContentType("image/png");
+    response.setContentType("image/" + fileType);
     response.setHeader("Content-Length",
         String.valueOf(graph.getBytes().length));
     response.setHeader("Content-Disposition",
diff --git a/src/org/torproject/ernie/web/RObjectGenerator.java b/src/org/torproject/ernie/web/RObjectGenerator.java
index b964958..c599807 100644
--- a/src/org/torproject/ernie/web/RObjectGenerator.java
+++ b/src/org/torproject/ernie/web/RObjectGenerator.java
@@ -13,8 +13,10 @@ import java.io.InputStreamReader;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
@@ -38,6 +40,7 @@ public class RObjectGenerator implements ServletContextListener {
   private SortedSet<String> availableCsvFiles;
   private Map<String, String> availableTables;
   private Map<String, String> availableGraphs;
+  private Set<String> availableGraphFileTypes;
 
   public void contextInitialized(ServletContextEvent event) {
 
@@ -104,6 +107,8 @@ public class RObjectGenerator implements ServletContextListener {
     this.availableGraphs.put("fast-exits", "start,end,filename,dpi");
     this.availableGraphs.put("almost-fast-exits",
         "start,end,filename,dpi");
+    this.availableGraphFileTypes = new HashSet<String>(Arrays.asList(
+        "png,pdf,svg".split(",")));
     GraphParameterChecker.getInstance().setAvailableGraphs(
         availableGraphs);
 
@@ -129,7 +134,9 @@ public class RObjectGenerator implements ServletContextListener {
             generateTable(tableName, tableName, new HashMap(), false);
           }
           for (String graphName : availableGraphs.keySet()) {
-            generateGraph(graphName, new HashMap(), false);
+            for (String fileType : availableGraphFileTypes) {
+              generateGraph(graphName, fileType, new HashMap(), false);
+            }
           }
           lastUpdated = System.currentTimeMillis();
         }
@@ -141,8 +148,8 @@ public class RObjectGenerator implements ServletContextListener {
     /* Nothing to do. */
   }
 
-  public RObject generateGraph(String requestedGraph, Map parameterMap,
-      boolean checkCache) {
+  public RObject generateGraph(String requestedGraph, String fileType,
+      Map parameterMap, boolean checkCache) {
     Map<String, String[]> checkedParameters = GraphParameterChecker.
         getInstance().checkParameters(requestedGraph, parameterMap);
     if (checkedParameters == null) {
@@ -172,7 +179,7 @@ public class RObjectGenerator implements ServletContextListener {
             parameterValues.length - 1] + "'), ");
       }
     }
-    imageFilenameBuilder.append(".png");
+    imageFilenameBuilder.append("." + fileType);
     String imageFilename = imageFilenameBuilder.toString();
     rQueryBuilder.append("path = '%s')");
     String rQuery = rQueryBuilder.toString();
diff --git a/web/WEB-INF/fast-exits.jsp b/web/WEB-INF/fast-exits.jsp
index c542a01..d97c8a4 100644
--- a/web/WEB-INF/fast-exits.jsp
+++ b/web/WEB-INF/fast-exits.jsp
@@ -47,6 +47,9 @@ requirements</a></h3>
     </p>
   </div>
 </form>
+<p>Download graph as
+<a href="fast-exits.pdf${fast_exits_url}">PDF</a> or
+<a href="fast-exits.svg${fast_exits_url}">SVG</a>.</p>
 <br>
 
 <a name="almostfastexits"></a>
@@ -76,6 +79,9 @@ fast-exit requirements</a></h3>
     </p>
   </div>
 </form>
+<p>Download graph as
+<a href="almost-fast-exits.pdf${almost_fast_exits_url}">PDF</a> or
+<a href="almost-fast-exits.svg${almost_fast_exits_url}">SVG</a>.</p>
 <br>
 
     </div>
diff --git a/web/WEB-INF/network.jsp b/web/WEB-INF/network.jsp
index d73f672..53ed715 100644
--- a/web/WEB-INF/network.jsp
+++ b/web/WEB-INF/network.jsp
@@ -52,6 +52,9 @@ bridges in the network.</p>
     </p>
   </div>
 </form>
+<p>Download graph as
+<a href="networksize.pdf${networksize_url}">PDF</a> or
+<a href="networksize.svg${networksize_url}">SVG</a>.</p>
 <p><a href="csv/networksize.csv">CSV</a> file containing all data.</p>
 <br>
 
@@ -90,6 +93,9 @@ country.</p>
     </p>
   </div>
 </form>
+<p>Download graph as
+<a href="relaycountries.pdf${relaycountries_url}">PDF</a> or
+<a href="relaycountries.svg${relaycountries_url}">SVG</a>.</p>
 <p><a href="csv/relaycountries.csv">CSV</a> file containing all data.</p>
 <br>
 
@@ -134,6 +140,9 @@ average number of relays with these flags assigned.</p>
     </p>
   </div>
 </form>
+<p>Download graph as
+<a href="relayflags.pdf${relayflags_url}">PDF</a> or
+<a href="relayflags.svg${relayflags_url}">SVG</a>.</p>
 <p><a href="csv/relayflags.csv">CSV</a> file containing all data.</p>
 <br>
 
@@ -170,6 +179,9 @@ The following graph shows the number of relays by version.</p>
     </p>
   </div>
 </form>
+<p>Download graph as
+<a href="versions.pdf${versions_url}">PDF</a> or
+<a href="versions.svg${versions_url}">SVG</a>.</p>
 <p><a href="csv/versions.csv">CSV</a> file containing all data.</p>
 <br>
 
@@ -202,6 +214,9 @@ platform.</p>
     </p>
   </div>
 </form>
+<p>Download graph as
+<a href="platforms.pdf${platforms_url}">PDF</a> or
+<a href="platforms.svg${platforms_url}">SVG</a>.</p>
 <p><a href="csv/platforms.csv">CSV</a> file containing all data.</p>
 <br>
 
@@ -234,6 +249,9 @@ network.</p>
     </p>
   </div>
 </form>
+<p>Download graph as
+<a href="cloudbridges.pdf${cloudbridges_url}">PDF</a> or
+<a href="cloudbridges.svg${cloudbridges_url}">SVG</a>.</p>
 <p><a href="csv/cloudbridges.csv">CSV</a> file containing all data.</p>
 <br>
 
@@ -268,6 +286,9 @@ in the network.</p>
     </p>
   </div>
 </form>
+<p>Download graph as
+<a href="bandwidth.pdf${bandwidth_url}">PDF</a> or
+<a href="bandwidth.svg${bandwidth_url}">SVG</a>.</p>
 <p><a href="csv/bandwidth.csv">CSV</a> file containing all data.</p>
 <br>
 
@@ -300,6 +321,9 @@ Exit and/or Guard flags assigned by the directory authorities.</p>
     </p>
   </div>
 </form>
+<p>Download graph as
+<a href="bwhist-flags.pdf${bwhist_flags_url}">PDF</a> or
+<a href="bwhist-flags.svg${bwhist_flags_url}">SVG</a>.</p>
 <p><a href="csv/bwhist-flags.csv">CSV</a> file containing all data.</p>
 <br>
 
@@ -335,6 +359,9 @@ Guard flag.</p>
     </p>
   </div>
 </form>
+<p>Download graph as
+<a href="bandwidth-flags.pdf${bandwidth_flags_url}">PDF</a> or
+<a href="bandwidth-flags.svg${bandwidth_flags_url}">SVG</a>.</p>
 <p><a href="csv/bandwidth-flags.csv">CSV</a> file containing all data.</p>
 <br>
 
@@ -370,6 +397,9 @@ the number of written and read dir bytes by all relays.</p>
     </p>
   </div>
 </form>
+<p>Download graph as
+<a href="dirbytes.pdf${dirbytes_url}">PDF</a> or
+<a href="dirbytes.svg${dirbytes_url}">SVG</a>.</p>
 <p><a href="csv/dirbytes.csv">CSV</a> file containing all data.</p>
 <br>
     </div>
diff --git a/web/WEB-INF/performance.jsp b/web/WEB-INF/performance.jsp
index 5f25b8a..e6caf8e 100644
--- a/web/WEB-INF/performance.jsp
+++ b/web/WEB-INF/performance.jsp
@@ -59,6 +59,9 @@ graph.</p>
     </p>
   </div>
 </form>
+<p>Download graph as
+<a href="torperf.pdf${torperf_url}">PDF</a> or
+<a href="torperf.svg${torperf_url}">SVG</a>.</p>
 <p><a href="csv/torperf.csv">CSV</a> file containing all data.</p>
 
 <br>
@@ -106,6 +109,9 @@ than 50 KiB (1 MiB, 5 MiB).</p>
     </p>
   </div>
 </form>
+<p>Download graph as
+<a href="torperf-failures.pdf${torperf_failures_url}">PDF</a> or
+<a href="torperf-failures.svg${torperf_failures_url}">SVG</a>.</p>
 <p><a href="csv/torperf-failures.csv">CSV</a> file containing all data.</p>
 
 <br>
@@ -147,6 +153,9 @@ classifying connections, read and write counters are reset for the next
     </p>
   </div>
 </form>
+<p>Download graph as
+<a href="connbidirect.pdf${connbidirect_url}">PDF</a> or
+<a href="connbidirect.svg${connbidirect_url}">SVG</a>.</p>
 <p><a href="csv/connbidirect.csv">CSV</a> file containing all data.</p>
 <br>
 
diff --git a/web/WEB-INF/users.jsp b/web/WEB-INF/users.jsp
index f422123..3ef211b 100644
--- a/web/WEB-INF/users.jsp
+++ b/web/WEB-INF/users.jsp
@@ -64,6 +64,9 @@ based on the requests seen by a few dozen directory mirrors.</p>
     </p>
   </div>
 </form>
+<p>Download graph as
+<a href="direct-users.pdf${direct_users_url}">PDF</a> or
+<a href="direct-users.svg${direct_users_url}">SVG</a>.</p>
 <hr>
 <a name="direct-users-table"></a>
 <p><b>Top-10 countries by directly connecting users:</b></p>
@@ -175,6 +178,9 @@ by a few hundred bridges.</p>
     </p>
   </div>
 </form>
+<p>Download graph as
+<a href="bridge-users.pdf${bridge_users_url}">PDF</a> or
+<a href="bridge-users.svg${bridge_users_url}">SVG</a>.</p>
 <hr>
 <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





More information about the tor-commits mailing list