diff --git a/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java
index 7742ff90fa..5cb93da5f2 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java
@@ -126,6 +126,7 @@ public class GraphHelper extends FormHandler {
/**
* For single stat page
+ * @param "bw.combined" treated specially
* @since 0.9
*/
public void setStat(String stat) {
@@ -151,10 +152,10 @@ public class GraphHelper extends FormHandler {
}
if (hasTx && hasRx && !_showEvents) {
- _out.write("");
String title = _("Combined bandwidth graph");
_out.write(" rates = StatSummarizer.instance().parseSpecs(_stat);
- if (rates.size() != 1) {
- _out.write("Graphs not enabled for " + _stat);
- return "";
+ long period;
+ String name, displayName;
+ if (_stat.equals("bw.combined")) {
+ period = 60000;
+ name = _stat;
+ displayName = _("Bandwidth usage");
+ } else {
+ List
");
- _out.write(_("{0} for {1}", r.getRateStat().getName(), DataHelper.formatDuration2(_periodCount * r.getPeriod())));
+ _out.write(_("{0} for {1}", displayName, DataHelper.formatDuration2(_periodCount * period)));
if (_end > 0)
- _out.write(' ' + _("ending {0} ago", DataHelper.formatDuration2(_end * r.getPeriod())));
+ _out.write(' ' + _("ending {0} ago", DataHelper.formatDuration2(_end * period)));
_out.write("
");
_out.write(link(_stat, !_showEvents, _periodCount, _end, _width, _height));
- _out.write(_showEvents ? _("Plot averages") : _("plot events"));
+ if (!_stat.equals("bw.combined"))
+ _out.write(_showEvents ? _("Plot averages") : _("plot events"));
_out.write("
" + _("All times are UTC.") + "
\n"); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java b/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java index c025fd7e32..75b62819ca 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java @@ -245,7 +245,7 @@ public class StatSummarizer implements Runnable { if (lsnr.getRate().equals(rate)) { lsnr.getData().exportXml(out); out.write(("\n").getBytes()); - out.write(("\n").getBytes()); + out.write(("\n").getBytes()); return true; } } @@ -254,19 +254,21 @@ public class StatSummarizer implements Runnable { /** * This does the two-data bandwidth graph only. - * For all other graphs see SummaryRenderer + * For all other graphs see renderPng() above. * Synchronized to conserve memory. + * + * @param end number of periods before now * @return success */ public boolean renderRatePng(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, - int periodCount, boolean showCredit) throws IOException { + int periodCount, int end, boolean showCredit) throws IOException { try { try { _sem.acquire(); } catch (InterruptedException ie) {} return locked_renderRatePng(out, width, height, hideLegend, hideGrid, hideTitle, showEvents, - periodCount, showCredit); + periodCount, end, showCredit); } finally { _sem.release(); } @@ -274,7 +276,7 @@ public class StatSummarizer implements Runnable { private boolean locked_renderRatePng(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, - int periodCount, boolean showCredit) throws IOException { + int periodCount, int end, boolean showCredit) throws IOException { // go to some trouble to see if we have the data for the combined bw graph SummaryListener txLsnr = null; @@ -289,7 +291,6 @@ public class StatSummarizer implements Runnable { if (txLsnr == null || rxLsnr == null) throw new IOException("no rates for combined graph"); - long end = _context.clock().now() - 75*1000; if (width > GraphHelper.MAX_X) width = GraphHelper.MAX_X; else if (width <= 0) @@ -298,86 +299,9 @@ public class StatSummarizer implements Runnable { height = GraphHelper.MAX_Y; else if (height <= 0) height = GraphHelper.DEFAULT_Y; - if (periodCount <= 0 || periodCount > txLsnr.getRows()) - periodCount = txLsnr.getRows(); - long period = 60*1000; - long start = end - period*periodCount; - //long begin = System.currentTimeMillis(); - ImageOutputStream ios = null; - try { - RrdGraphDef def = new RrdGraphDef(); - def.setTimeSpan(start/1000, end/1000); - def.setMinValue(0d); - def.setBase(1024); - String title = _("Bandwidth usage"); - if (!hideTitle) - def.setTitle(title); - long started = _context.router().getWhenStarted(); - if (started > start && started < end) - def.vrule(started / 1000, SummaryRenderer.RESTART_BAR_COLOR, null, 4.0f); // no room for legend - String sendName = SummaryListener.createName(_context, "bw.sendRate.60000"); - String recvName = SummaryListener.createName(_context, "bw.recvRate.60000"); - def.datasource(sendName, txLsnr.getData().getPath(), sendName, SummaryListener.CF, txLsnr.getBackendName()); - def.datasource(recvName, rxLsnr.getData().getPath(), recvName, SummaryListener.CF, rxLsnr.getBackendName()); - def.area(sendName, Color.BLUE, _("Outbound Bytes/sec")); - //def.line(sendName, Color.BLUE, "Outbound bytes/sec", 3); - def.line(recvName, Color.RED, _("Inbound Bytes/sec") + "\\r", 3); - //def.area(recvName, Color.RED, "Inbound bytes/sec@r"); - if (!hideLegend) { - def.gprint(sendName, SummaryListener.CF, _("Out average") + ": %.2f %s" + _("Bps")); - def.gprint(sendName, "MAX", ' ' + _("max") + ": %.2f %S" + _("Bps") + "\\r"); - def.gprint(recvName, SummaryListener.CF, _("In average") + ": %.2f %S" + _("Bps")); - def.gprint(recvName, "MAX", ' ' + _("max") + ": %.2f %S" + _("Bps") + "\\r"); - // '07-Jul 21:09 UTC' with month name in the system locale - SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM HH:mm"); - def.comment(sdf.format(new Date(start)) + " -- " + sdf.format(new Date(end)) + " UTC\\r"); - } - if (!showCredit) - def.setShowSignature(false); - if (hideLegend) - def.setNoLegend(true); - if (hideGrid) { - def.setDrawXGrid(false); - def.setDrawYGrid(false); - } - //System.out.println("rendering: path=" + path + " dsNames[0]=" + dsNames[0] + " dsNames[1]=" + dsNames[1] + " lsnr.getName=" + _listener.getName()); - def.setAntiAliasing(false); - //System.out.println("Rendering: \n" + def.exportXmlTemplate()); - //System.out.println("*****************\nData: \n" + _listener.getData().dump()); - def.setWidth(width); - def.setHeight(height); - def.setImageFormat("PNG"); - def.setLazy(true); - - RrdGraph graph = new RrdGraph(def); - //System.out.println("Graph created"); - int totalWidth = graph.getRrdGraphInfo().getWidth(); - int totalHeight = graph.getRrdGraphInfo().getHeight(); - BufferedImage img = new BufferedImage(totalWidth, totalHeight, BufferedImage.TYPE_USHORT_565_RGB); - Graphics gfx = img.getGraphics(); - graph.render(gfx); - ios = new MemoryCacheImageOutputStream(out); - ImageIO.write(img, "png", ios); - - //File t = File.createTempFile("jrobinData", ".xml"); - //_listener.getData().dumpXml(new FileOutputStream(t)); - //System.out.println("plotted: " + (data != null ? data.length : 0) + " bytes in " + timeToPlot - // ); // + ", data written to " + t.getAbsolutePath()); - return true; - } catch (RrdException re) { - _log.error("Error rendering", re); - throw new IOException("Error plotting: " + re.getMessage()); - } catch (IOException ioe) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Error rendering", ioe); - throw ioe; - } catch (OutOfMemoryError oom) { - _log.error("Error rendering", oom); - throw new IOException("Error plotting: " + oom.getMessage()); - } finally { - // this does not close the underlying stream - if (ios != null) try {ios.close();} catch (IOException ioe) {} - } + txLsnr.renderPng(out, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, + end, showCredit, rxLsnr, _("Bandwidth usage")); + return true; } /** diff --git a/apps/routerconsole/java/src/net/i2p/router/web/SummaryListener.java b/apps/routerconsole/java/src/net/i2p/router/web/SummaryListener.java index f971e66cb9..b4572e53b1 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryListener.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryListener.java @@ -187,14 +187,31 @@ class SummaryListener implements RateSummaryListener { } /** + * Single graph. + * * @param end number of periods before now */ public void renderPng(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, int end, boolean showCredit) throws IOException { + renderPng(out, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, + end, showCredit, null, null); + } + + /** + * Single or two-data-source graph. + * + * @param lsnr2 2nd data source to plot on same graph, or null. Not recommended for events. + * @param titleOverride If non-null, overrides the title + * @since 0.9.6 + */ + public void renderPng(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, + boolean hideTitle, boolean showEvents, int periodCount, + int end, boolean showCredit, SummaryListener lsnr2, String titleOverride) throws IOException { if (_renderer == null || _db == null) throw new IOException("No RRD, check logs for previous errors"); - _renderer.render(out, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, end, showCredit); + _renderer.render(out, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, + end, showCredit, lsnr2, titleOverride); } public void renderPng(OutputStream out) throws IOException { diff --git a/apps/routerconsole/java/src/net/i2p/router/web/SummaryRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/SummaryRenderer.java index bea95b7978..e35e772d09 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryRenderer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryRenderer.java @@ -27,8 +27,7 @@ import org.jrobin.graph.RrdGraphDefTemplate; /** * Generate the RRD graph png images, - * except for the combined rate graph, which is - * generated in StatSummarizer. + * including the combined rate graph. * * @since 0.6.1.13 */ @@ -36,7 +35,7 @@ class SummaryRenderer { private final Log _log; private final SummaryListener _listener; private final I2PAppContext _context; - static final Color RESTART_BAR_COLOR = new Color(255, 144, 0, 224); + private static final Color RESTART_BAR_COLOR = new Color(255, 144, 0, 224); public SummaryRenderer(I2PAppContext ctx, SummaryListener lsnr) { _log = ctx.logManager().getLog(SummaryRenderer.class); @@ -51,8 +50,11 @@ class SummaryRenderer { * specify who can get it from where, etc. * * @deprecated unsed + * @throws UnsupportedOperationException always */ public static synchronized void render(I2PAppContext ctx, OutputStream out, String filename) throws IOException { + throw new UnsupportedOperationException(); +/***** long end = ctx.clock().now() - 60*1000; long start = end - 60*1000*SummaryListener.PERIODS; try { @@ -80,17 +82,34 @@ class SummaryRenderer { //_log.error("Error rendering " + filename, ioe); throw ioe; } +*****/ } public void render(OutputStream out) throws IOException { render(out, GraphHelper.DEFAULT_X, GraphHelper.DEFAULT_Y, false, false, false, false, -1, 0, false); } /** + * Single graph. + * * @param endp number of periods before now */ public void render(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, int endp, boolean showCredit) throws IOException { + render(out, width, height, hideLegend, hideGrid, hideTitle, + showEvents, periodCount, endp, showCredit, null, null); + } + + /** + * Single or two-data-source graph. + * + * @param lsnr2 2nd data source to plot on same graph, or null. Not recommended for events. + * @param titleOverride If non-null, overrides the title + * @since 0.9.6 consolidated from StatSummarizer for bw.combined + */ + public void render(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, + boolean hideTitle, boolean showEvents, int periodCount, + int endp, boolean showCredit, SummaryListener lsnr2, String titleOverride) throws IOException { long end = _listener.now() - 75*1000; long period = _listener.getRate().getPeriod(); if (endp > 0) @@ -109,7 +128,9 @@ class SummaryRenderer { if ((name.startsWith("bw.") || name.indexOf("Size") >= 0 || name.indexOf("Bps") >= 0 || name.indexOf("memory") >= 0) && !showEvents) def.setBase(1024); - if (!hideTitle) { + if (titleOverride != null) { + def.setTitle(titleOverride); + } else if (!hideTitle) { String title; String p; // we want the formatting and translation of formatDuration2(), except not zh, and not the @@ -146,14 +167,31 @@ class SummaryRenderer { // def.vrule(started / 1000, RESTART_BAR_COLOR, _("Restart"), 4.0f); def.datasource(plotName, path, plotName, SummaryListener.CF, _listener.getBackendName()); - if (descr.length() > 0) + if (descr.length() > 0) { def.area(plotName, Color.BLUE, descr + "\\r"); - else + } else { def.area(plotName, Color.BLUE); + } if (!hideLegend) { def.gprint(plotName, SummaryListener.CF, _("avg") + ": %.2f %s"); def.gprint(plotName, "MAX", ' ' + _("max") + ": %.2f %S"); def.gprint(plotName, "LAST", ' ' + _("now") + ": %.2f %S\\r"); + } + String plotName2 = null; + if (lsnr2 != null) { + String dsNames2[] = lsnr2.getData().getDsNames(); + plotName2 = dsNames2[0]; + String path2 = lsnr2.getData().getPath(); + String descr2 = _(lsnr2.getRate().getRateStat().getDescription()); + def.datasource(plotName2, path2, plotName2, SummaryListener.CF, lsnr2.getBackendName()); + def.line(plotName2, Color.RED, descr2 + "\\r", 3); + if (!hideLegend) { + def.gprint(plotName2, SummaryListener.CF, _("avg") + ": %.2f %s"); + def.gprint(plotName2, "MAX", ' ' + _("max") + ": %.2f %S"); + def.gprint(plotName2, "LAST", ' ' + _("now") + ": %.2f %S\\r"); + } + } + if (!hideLegend) { // '07-Jul 21:09 UTC' with month name in the system locale SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM HH:mm"); Map