Files
i2p.i2p/router/java/src/net/i2p/router/admin/StatsGenerator.java
T
zzz 0bde8a24e4 * Reachability:
- Restrict peers requiring introducers from inbound tunnels,
        since it's slow and unreliable... and many of them advertise
        NTCP, which seems unlikely to work
      - Provide warning on summary bar if firewalled with inbound NTCP enabled
    * Stats: Remove the bw.[send,recv]Bps[1,15]s stats unless
      log level net.i2p.router.transport.FIFOBandwidthLimiter >= WARN
      at startup (you didn't get any data unless you set the log level anyway)
    * oldstats.jsp: Don't put 2 decimal places on integer event counts
    * Remove the Internals link from the menu bar
    * i2psnark: Extend startup delay from 1 to 3 minutes
2008-05-07 16:23:54 +00:00

221 lines
9.5 KiB
Java

package net.i2p.router.admin;
import java.io.IOException;
import java.io.Writer;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import net.i2p.data.DataHelper;
import net.i2p.router.RouterContext;
import net.i2p.stat.Frequency;
import net.i2p.stat.FrequencyStat;
import net.i2p.stat.Rate;
import net.i2p.stat.RateStat;
import net.i2p.util.Log;
/**
* Dump the stats to the web admin interface
*/
public class StatsGenerator {
private Log _log;
private RouterContext _context;
public StatsGenerator(RouterContext context) {
_context = context;
_log = context.logManager().getLog(StatsGenerator.class);
}
public void generateStatsPage(Writer out) throws IOException {
StringBuffer buf = new StringBuffer(16*1024);
buf.append("<h1>Router statistics</h1><hr />");
buf.append("<form action=\"/oldstats.jsp\">");
buf.append("<select name=\"go\" onChange='location.href=this.value'>");
out.write(buf.toString());
buf.setLength(0);
Map groups = _context.statManager().getStatsByGroup();
for (Iterator iter = groups.keySet().iterator(); iter.hasNext(); ) {
String group = (String)iter.next();
Set stats = (Set)groups.get(group);
buf.append("<option value=\"/oldstats.jsp#").append(group).append("\">");
buf.append(group).append("</option>\n");
for (Iterator statIter = stats.iterator(); statIter.hasNext(); ) {
String stat = (String)statIter.next();
buf.append("<option value=\"/oldstats.jsp#");
buf.append(stat);
buf.append("\">...");
buf.append(stat);
buf.append("</option>\n");
}
out.write(buf.toString());
buf.setLength(0);
}
buf.append("</select> <input type=\"submit\" value=\"GO\" />");
buf.append("</form>");
buf.append("Statistics gathered during this router's uptime (");
long uptime = _context.router().getUptime();
buf.append(DataHelper.formatDuration(uptime));
buf.append("). The data gathered is quantized over a 1 minute period, so should just be used as an estimate<p />");
out.write(buf.toString());
buf.setLength(0);
for (Iterator iter = groups.keySet().iterator(); iter.hasNext(); ) {
String group = (String)iter.next();
Set stats = (Set)groups.get(group);
buf.append("<h2><a name=\"");
buf.append(group);
buf.append("\">");
buf.append(group);
buf.append("</a></h2>");
buf.append("<ul>");
out.write(buf.toString());
buf.setLength(0);
for (Iterator statIter = stats.iterator(); statIter.hasNext(); ) {
String stat = (String)statIter.next();
buf.append("<li><b><a name=\"");
buf.append(stat);
buf.append("\">");
buf.append(stat);
buf.append("</a></b><br />");
if (_context.statManager().isFrequency(stat))
renderFrequency(stat, buf);
else
renderRate(stat, buf);
out.write(buf.toString());
buf.setLength(0);
}
out.write("</ul><hr />");
}
out.flush();
}
private void renderFrequency(String name, StringBuffer buf) {
FrequencyStat freq = _context.statManager().getFrequency(name);
buf.append("<i>");
buf.append(freq.getDescription());
buf.append("</i><br />");
long periods[] = freq.getPeriods();
Arrays.sort(periods);
for (int i = 0; i < periods.length; i++) {
renderPeriod(buf, periods[i], "frequency");
Frequency curFreq = freq.getFrequency(periods[i]);
buf.append(" <i>avg per period:</i> (");
buf.append(num(curFreq.getAverageEventsPerPeriod()));
buf.append(", max ");
buf.append(num(curFreq.getMaxAverageEventsPerPeriod()));
if ( (curFreq.getMaxAverageEventsPerPeriod() > 0) && (curFreq.getAverageEventsPerPeriod() > 0) ) {
buf.append(", current is ");
buf.append(pct(curFreq.getAverageEventsPerPeriod()/curFreq.getMaxAverageEventsPerPeriod()));
buf.append(" of max");
}
buf.append(")");
//buf.append(" <i>avg interval between updates:</i> (").append(num(curFreq.getAverageInterval())).append("ms, min ");
//buf.append(num(curFreq.getMinAverageInterval())).append("ms)");
buf.append(" <i>strict average per period:</i> ");
buf.append(num(curFreq.getStrictAverageEventsPerPeriod()));
buf.append(" events (averaged ");
buf.append(" using the lifetime of ");
buf.append(curFreq.getEventCount());
buf.append(" events)");
buf.append("<br />");
}
buf.append("<br />");
}
private void renderRate(String name, StringBuffer buf) {
RateStat rate = _context.statManager().getRate(name);
buf.append("<i>");
buf.append(rate.getDescription());
buf.append("</i><br />");
long periods[] = rate.getPeriods();
Arrays.sort(periods);
buf.append("<ul>");
for (int i = 0; i < periods.length; i++) {
buf.append("<li>");
renderPeriod(buf, periods[i], "rate");
Rate curRate = rate.getRate(periods[i]);
buf.append( "<i>avg value:</i> (");
buf.append(num(curRate.getAverageValue()));
buf.append(" peak ");
buf.append(num(curRate.getExtremeAverageValue()));
buf.append(", [");
buf.append(pct(curRate.getPercentageOfExtremeValue()));
buf.append(" of max");
buf.append(", and ");
buf.append(pct(curRate.getPercentageOfLifetimeValue()));
buf.append(" of lifetime average]");
buf.append(")");
buf.append(" <i>highest total period value:</i> (");
buf.append(num(curRate.getExtremeTotalValue()));
buf.append(")");
if (curRate.getLifetimeTotalEventTime() > 0) {
buf.append(" <i>saturation:</i> (");
buf.append(pct(curRate.getLastEventSaturation()));
buf.append(")");
buf.append(" <i>saturated limit:</i> (");
buf.append(num(curRate.getLastSaturationLimit()));
buf.append(")");
buf.append(" <i>peak saturation:</i> (");
buf.append(pct(curRate.getExtremeEventSaturation()));
buf.append(")");
buf.append(" <i>peak saturated limit:</i> (");
buf.append(num(curRate.getExtremeSaturationLimit()));
buf.append(")");
}
buf.append(" <i>events per period:</i> ");
buf.append(curRate.getLastEventCount());
long numPeriods = curRate.getLifetimePeriods();
if (numPeriods > 0) {
double avgFrequency = curRate.getLifetimeEventCount() / (double)numPeriods;
double peakFrequency = curRate.getExtremeEventCount();
buf.append(" (lifetime average: ");
buf.append(num(avgFrequency));
buf.append(", peak average: ");
buf.append(curRate.getExtremeEventCount());
buf.append(")");
}
if (curRate.getSummaryListener() != null) {
buf.append(" <a href=\"viewstat.jsp?stat=").append(name);
buf.append("&amp;period=").append(periods[i]);
buf.append("\" title=\"Render summarized data\">render</a>");
buf.append(" <a href=\"viewstat.jsp?stat=").append(name);
buf.append("&amp;period=").append(periods[i]).append("&amp;showEvents=true\" title=\"Render summarized event counts\">events</a>");
buf.append(" (as <a href=\"viewstat.jsp?stat=").append(name);
buf.append("&amp;period=").append(periods[i]);
buf.append("&amp;format=xml\" title=\"Dump stat history as XML\">XML</a>");
buf.append(" in a format <a href=\"http://people.ee.ethz.ch/~oetiker/webtools/rrdtool\">RRDTool</a> understands)");
}
buf.append("</li>");
if (i + 1 == periods.length) {
// last one, so lets display the strict average
buf.append("<li><b>lifetime average value:</b> ");
buf.append(num(curRate.getLifetimeAverageValue()));
buf.append(" over ");
buf.append(curRate.getLifetimeEventCount());
buf.append(" events<br /></li>");
}
}
buf.append("</ul>");
buf.append("<br />");
}
private static void renderPeriod(StringBuffer buf, long period, String name) {
buf.append("<b>");
buf.append(DataHelper.formatDuration(period));
buf.append(" ");
buf.append(name);
buf.append(":</b> ");
}
private final static DecimalFormat _fmt = new DecimalFormat("###,##0.00");
private final static String num(double num) { synchronized (_fmt) { return _fmt.format(num); } }
private final static DecimalFormat _pct = new DecimalFormat("#0.00%");
private final static String pct(double num) { synchronized (_pct) { return _pct.format(num); } }
}