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 7ee8b069d4852dfff4d98fc2f6524354ef516c47..7f39f04f8aa2f315bb10b1454bb81ead2b53b959 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java @@ -264,9 +264,8 @@ public class StatSummarizer implements Runnable { height = GraphHelper.MAX_Y; else if (height <= 0) height = GraphHelper.DEFAULT_Y; - if (periodCount <= 0) periodCount = SummaryListener.PERIODS; - if (periodCount > SummaryListener.PERIODS) - periodCount = SummaryListener.PERIODS; + if (periodCount <= 0 || periodCount > txLsnr.getRows()) + periodCount = txLsnr.getRows(); long period = 60*1000; long start = end - period*periodCount; //long begin = System.currentTimeMillis(); @@ -284,16 +283,16 @@ public class StatSummarizer implements Runnable { def.vrule(started / 1000, Color.BLACK, 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, "AVERAGE", txLsnr.getBackendName()); - def.datasource(recvName, rxLsnr.getData().getPath(), recvName, "AVERAGE", rxLsnr.getBackendName()); + 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, "AVERAGE", _("Out average") + ": %.2f %s" + _("Bps")); + def.gprint(sendName, SummaryListener.CF, _("Out average") + ": %.2f %s" + _("Bps")); def.gprint(sendName, "MAX", ' ' + _("max") + ": %.2f %S" + _("Bps") + "\\r"); - def.gprint(recvName, "AVERAGE", _("In average") + ": %.2f %S" + _("Bps")); + def.gprint(recvName, SummaryListener.CF, _("In average") + ": %.2f %S" + _("Bps")); def.gprint(recvName, "MAX", ' ' + _("max") + ": %.2f %S" + _("Bps") + "\\r"); } if (!showCredit) 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 f338e684811d51997fb563bb1fd5c8c6f160a059..c66c2fbccfdafcad11bc8e9c7b08ab664fa33b98 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryListener.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryListener.java @@ -13,6 +13,7 @@ import net.i2p.util.Log; import net.i2p.util.SecureFile; import net.i2p.util.SecureFileOutputStream; +import org.jrobin.core.Archive; import org.jrobin.core.RrdBackendFactory; import org.jrobin.core.RrdDb; import org.jrobin.core.RrdDef; @@ -36,6 +37,9 @@ class SummaryListener implements RateSummaryListener { private static final String RRD_DIR = "rrd"; private static final String RRD_PREFIX = "rrd-"; private static final String RRD_SUFFIX = ".jrb"; + static final String CF = "AVERAGE"; + private static final double XFF = 0.9d; + private static final int STEPS = 1; private final I2PAppContext _context; private final Log _log; @@ -47,8 +51,12 @@ class SummaryListener implements RateSummaryListener { private Sample _sample; private RrdMemoryBackendFactory _factory; private SummaryRenderer _renderer; + private int _rows; - static final int PERIODS = 1440; + static final int PERIODS = 60 * 24; // 1440 + private static final int MIN_ROWS = PERIODS; + private static final int MAX_ROWS = 91 * MIN_ROWS; + private static final long THREE_MONTHS = 91l * 24 * 60 * 60 * 1000; public SummaryListener(Rate r) { _context = I2PAppContext.getGlobalContext(); @@ -112,8 +120,12 @@ class SummaryListener implements RateSummaryListener { rrdDefName = rrdFile.getAbsolutePath(); if (rrdFile.exists()) { _db = new RrdDb(rrdDefName, factory); + Archive arch = _db.getArchive(CF, STEPS); + if (arch == null) + throw new IOException("No average CF in " + rrdDefName); + _rows = arch.getRows(); if (_log.shouldLog(Log.INFO)) - _log.info("Existing RRD " + baseName + " (" + rrdDefName + ") consuming " + _db.getRrdBackend().getLength() + " bytes"); + _log.info("Existing RRD " + baseName + " (" + rrdDefName + ") with " + _rows + " rows consuming " + _db.getRrdBackend().getLength() + " bytes"); } else { rrdDir.mkdir(); } @@ -128,15 +140,18 @@ class SummaryListener implements RateSummaryListener { long heartbeat = period*10/1000; def.addDatasource(_name, "GAUGE", heartbeat, Double.NaN, Double.NaN); def.addDatasource(_eventName, "GAUGE", heartbeat, 0, Double.NaN); - double xff = 0.9; int steps = 1; - int rows = PERIODS; - def.addArchive("AVERAGE", xff, steps, rows); + if (_isPersistent) { + _rows = (int) Math.max(MIN_ROWS, Math.min(MAX_ROWS, THREE_MONTHS / period)); + } else { + _rows = MIN_ROWS; + } + def.addArchive(CF, XFF, STEPS, _rows); _db = new RrdDb(def, factory); if (_isPersistent) SecureFileOutputStream.setPerms(new File(rrdDefName)); if (_log.shouldLog(Log.INFO)) - _log.info("New RRD " + baseName + " (" + rrdDefName + ") consuming " + _db.getRrdBackend().getLength() + " bytes"); + _log.info("New RRD " + baseName + " (" + rrdDefName + ") with " + _rows + " rows consuming " + _db.getRrdBackend().getLength() + " bytes"); } _sample = _db.createSample(); _renderer = new SummaryRenderer(_context, this); @@ -184,6 +199,11 @@ class SummaryListener implements RateSummaryListener { return _isPersistent ? RrdNioBackendFactory.NAME : RrdMemoryBackendFactory.NAME; } + /** @since 0.8.6 */ + int getRows() { + return _rows; + } + @Override public boolean equals(Object obj) { return ((obj instanceof SummaryListener) && ((SummaryListener)obj)._rate.equals(_rate)); 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 37d41719e936f25a3ffb96503d905f3df61b6cf9..46bd66292030081a2759cfcecebc1c1c3d7a18b6 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryRenderer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryRenderer.java @@ -85,9 +85,8 @@ class SummaryRenderer { public void render(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, boolean showCredit) throws IOException { long end = _listener.now() - 60*1000; - if (periodCount <= 0) periodCount = SummaryListener.PERIODS; - if (periodCount > SummaryListener.PERIODS) - periodCount = SummaryListener.PERIODS; + if (periodCount <= 0 || periodCount > _listener.getRows()) + periodCount = _listener.getRows(); long start = end - _listener.getRate().getPeriod()*periodCount; //long begin = System.currentTimeMillis(); try { @@ -134,10 +133,10 @@ class SummaryRenderer { long started = ((RouterContext)_context).router().getWhenStarted(); if (started > start && started < end) def.vrule(started / 1000, Color.BLACK, _("Restart"), 4.0f); - def.datasource(plotName, path, plotName, "AVERAGE", _listener.getBackendName()); + def.datasource(plotName, path, plotName, SummaryListener.CF, _listener.getBackendName()); def.area(plotName, Color.BLUE, descr + "\\r"); if (!hideLegend) { - def.gprint(plotName, "AVERAGE", _("avg") + ": %.2f %s"); + def.gprint(plotName, SummaryListener.CF, _("avg") + ": %.2f %s"); def.gprint(plotName, "MAX", ' ' + _("max") + ": %.2f %S"); def.gprint(plotName, "LAST", ' ' + _("now") + ": %.2f %S\\r"); }