send the stats page out in chunks (more mem efficient, blah blah blah)
This commit is contained in:
@ -29,183 +29,180 @@ public class StatsGenerator {
|
|||||||
_log = context.logManager().getLog(StatsGenerator.class);
|
_log = context.logManager().getLog(StatsGenerator.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String generateStatsPage() {
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024);
|
|
||||||
try {
|
|
||||||
generateStatsPage(baos);
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
_log.error("Error generating stats", ioe);
|
|
||||||
}
|
|
||||||
return new String(baos.toByteArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void generateStatsPage(OutputStream out) throws IOException {
|
public void generateStatsPage(OutputStream out) throws IOException {
|
||||||
PrintWriter pw = new PrintWriter(out);
|
StringBuffer buf = new StringBuffer(16*1024);
|
||||||
pw.println("<html><head><title>I2P Router Stats</title></head><body>");
|
buf.append("<html><head><title>I2P Router Stats</title></head><body>");
|
||||||
pw.println("<h1>Router statistics</h1>");
|
buf.append("<h1>Router statistics</h1>");
|
||||||
pw.println("<i><a href=\"/routerConsole.html\">console</a> | <a href=\"/routerStats.html\">stats</a></i><hr />");
|
buf.append("<i><a href=\"/routerConsole.html\">console</a> | <a href=\"/routerStats.html\">stats</a></i><hr />");
|
||||||
|
buf.append("<form action=\"/routerStats.html\">");
|
||||||
|
buf.append("<select name=\"go\" onChange='location.href=this.value'>");
|
||||||
|
out.write(buf.toString().getBytes());
|
||||||
|
buf.setLength(0);
|
||||||
|
|
||||||
Map groups = _context.statManager().getStatsByGroup();
|
Map groups = _context.statManager().getStatsByGroup();
|
||||||
|
|
||||||
pw.println("<form action=\"/routerStats.html\">");
|
|
||||||
pw.println("<select name=\"go\" onChange='location.href=this.value'>");
|
|
||||||
for (Iterator iter = groups.keySet().iterator(); iter.hasNext(); ) {
|
for (Iterator iter = groups.keySet().iterator(); iter.hasNext(); ) {
|
||||||
String group = (String)iter.next();
|
String group = (String)iter.next();
|
||||||
Set stats = (Set)groups.get(group);
|
Set stats = (Set)groups.get(group);
|
||||||
pw.print("<option value=\"/routerStats.html#");
|
buf.append("<option value=\"/routerStats.html#").append(group).append("\">");
|
||||||
pw.print(group);
|
buf.append(group).append("</option>\n");
|
||||||
pw.print("\">");
|
|
||||||
pw.print(group);
|
|
||||||
pw.println("</option>\n");
|
|
||||||
for (Iterator statIter = stats.iterator(); statIter.hasNext(); ) {
|
for (Iterator statIter = stats.iterator(); statIter.hasNext(); ) {
|
||||||
String stat = (String)statIter.next();
|
String stat = (String)statIter.next();
|
||||||
pw.print("<option value=\"/routerStats.html#");
|
buf.append("<option value=\"/routerStats.html#");
|
||||||
pw.print(stat);
|
buf.append(stat);
|
||||||
pw.print("\">...");
|
buf.append("\">...");
|
||||||
pw.print(stat);
|
buf.append(stat);
|
||||||
pw.println("</option>\n");
|
buf.append("</option>\n");
|
||||||
}
|
}
|
||||||
|
out.write(buf.toString().getBytes());
|
||||||
|
buf.setLength(0);
|
||||||
}
|
}
|
||||||
pw.println("</select>");
|
buf.append("</select>");
|
||||||
pw.println("</form>");
|
buf.append("</form>");
|
||||||
|
|
||||||
pw.print("Statistics gathered during this router's uptime (");
|
buf.append("Statistics gathered during this router's uptime (");
|
||||||
long uptime = _context.router().getUptime();
|
long uptime = _context.router().getUptime();
|
||||||
pw.print(DataHelper.formatDuration(uptime));
|
buf.append(DataHelper.formatDuration(uptime));
|
||||||
pw.println("). The data gathered is quantized over a 1 minute period, so should just be used as an estimate<p />");
|
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().getBytes());
|
||||||
|
buf.setLength(0);
|
||||||
|
|
||||||
for (Iterator iter = groups.keySet().iterator(); iter.hasNext(); ) {
|
for (Iterator iter = groups.keySet().iterator(); iter.hasNext(); ) {
|
||||||
String group = (String)iter.next();
|
String group = (String)iter.next();
|
||||||
Set stats = (Set)groups.get(group);
|
Set stats = (Set)groups.get(group);
|
||||||
pw.print("<h2><a name=\"");
|
buf.append("<h2><a name=\"");
|
||||||
pw.print(group);
|
buf.append(group);
|
||||||
pw.print("\">");
|
buf.append("\">");
|
||||||
pw.print(group);
|
buf.append(group);
|
||||||
pw.println("</a></h2>");
|
buf.append("</a></h2>");
|
||||||
pw.println("<ul>");
|
buf.append("<ul>");
|
||||||
|
out.write(buf.toString().getBytes());
|
||||||
|
buf.setLength(0);
|
||||||
for (Iterator statIter = stats.iterator(); statIter.hasNext(); ) {
|
for (Iterator statIter = stats.iterator(); statIter.hasNext(); ) {
|
||||||
String stat = (String)statIter.next();
|
String stat = (String)statIter.next();
|
||||||
pw.print("<li><b><a name=\"");
|
buf.append("<li><b><a name=\"");
|
||||||
pw.print(stat);
|
buf.append(stat);
|
||||||
pw.print("\">");
|
buf.append("\">");
|
||||||
pw.print(stat);
|
buf.append(stat);
|
||||||
pw.println("</a></b><br />");
|
buf.append("</a></b><br />");
|
||||||
if (_context.statManager().isFrequency(stat))
|
if (_context.statManager().isFrequency(stat))
|
||||||
renderFrequency(stat, pw);
|
renderFrequency(stat, buf);
|
||||||
else
|
else
|
||||||
renderRate(stat, pw);
|
renderRate(stat, buf);
|
||||||
|
out.write(buf.toString().getBytes());
|
||||||
|
buf.setLength(0);
|
||||||
}
|
}
|
||||||
pw.println("</ul><hr />");
|
out.write("</ul><hr />".getBytes());
|
||||||
}
|
}
|
||||||
pw.println("</body></html>");
|
out.write("</body></html>".getBytes());
|
||||||
pw.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderFrequency(String name, PrintWriter pw) throws IOException {
|
private void renderFrequency(String name, StringBuffer buf) {
|
||||||
FrequencyStat freq = _context.statManager().getFrequency(name);
|
FrequencyStat freq = _context.statManager().getFrequency(name);
|
||||||
pw.print("<i>");
|
buf.append("<i>");
|
||||||
pw.print(freq.getDescription());
|
buf.append(freq.getDescription());
|
||||||
pw.println("</i><br />");
|
buf.append("</i><br />");
|
||||||
long periods[] = freq.getPeriods();
|
long periods[] = freq.getPeriods();
|
||||||
Arrays.sort(periods);
|
Arrays.sort(periods);
|
||||||
for (int i = 0; i < periods.length; i++) {
|
for (int i = 0; i < periods.length; i++) {
|
||||||
renderPeriod(pw, periods[i], "frequency");
|
renderPeriod(buf, periods[i], "frequency");
|
||||||
Frequency curFreq = freq.getFrequency(periods[i]);
|
Frequency curFreq = freq.getFrequency(periods[i]);
|
||||||
pw.print(" <i>avg per period:</i> (");
|
buf.append(" <i>avg per period:</i> (");
|
||||||
pw.print(num(curFreq.getAverageEventsPerPeriod()));
|
buf.append(num(curFreq.getAverageEventsPerPeriod()));
|
||||||
pw.print(", max ");
|
buf.append(", max ");
|
||||||
pw.print(num(curFreq.getMaxAverageEventsPerPeriod()));
|
buf.append(num(curFreq.getMaxAverageEventsPerPeriod()));
|
||||||
if ( (curFreq.getMaxAverageEventsPerPeriod() > 0) && (curFreq.getAverageEventsPerPeriod() > 0) ) {
|
if ( (curFreq.getMaxAverageEventsPerPeriod() > 0) && (curFreq.getAverageEventsPerPeriod() > 0) ) {
|
||||||
pw.print(", current is ");
|
buf.append(", current is ");
|
||||||
pw.print(pct(curFreq.getAverageEventsPerPeriod()/curFreq.getMaxAverageEventsPerPeriod()));
|
buf.append(pct(curFreq.getAverageEventsPerPeriod()/curFreq.getMaxAverageEventsPerPeriod()));
|
||||||
pw.print(" of max");
|
buf.append(" of max");
|
||||||
}
|
}
|
||||||
pw.print(")");
|
buf.append(")");
|
||||||
//buf.append(" <i>avg interval between updates:</i> (").append(num(curFreq.getAverageInterval())).append("ms, min ");
|
//buf.append(" <i>avg interval between updates:</i> (").append(num(curFreq.getAverageInterval())).append("ms, min ");
|
||||||
//buf.append(num(curFreq.getMinAverageInterval())).append("ms)");
|
//buf.append(num(curFreq.getMinAverageInterval())).append("ms)");
|
||||||
pw.print(" <i>strict average per period:</i> ");
|
buf.append(" <i>strict average per period:</i> ");
|
||||||
pw.print(num(curFreq.getStrictAverageEventsPerPeriod()));
|
buf.append(num(curFreq.getStrictAverageEventsPerPeriod()));
|
||||||
pw.print(" events (averaged ");
|
buf.append(" events (averaged ");
|
||||||
pw.print(" using the lifetime of ");
|
buf.append(" using the lifetime of ");
|
||||||
pw.print(num(curFreq.getEventCount()));
|
buf.append(num(curFreq.getEventCount()));
|
||||||
pw.print(" events)");
|
buf.append(" events)");
|
||||||
pw.println("<br />");
|
buf.append("<br />");
|
||||||
}
|
}
|
||||||
pw.println("<br />");
|
buf.append("<br />");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderRate(String name, PrintWriter pw) throws IOException {
|
private void renderRate(String name, StringBuffer buf) {
|
||||||
RateStat rate = _context.statManager().getRate(name);
|
RateStat rate = _context.statManager().getRate(name);
|
||||||
pw.print("<i>");
|
buf.append("<i>");
|
||||||
pw.print(rate.getDescription());
|
buf.append(rate.getDescription());
|
||||||
pw.println("</i><br />");
|
buf.append("</i><br />");
|
||||||
long periods[] = rate.getPeriods();
|
long periods[] = rate.getPeriods();
|
||||||
Arrays.sort(periods);
|
Arrays.sort(periods);
|
||||||
pw.println("<ul>");
|
buf.append("<ul>");
|
||||||
for (int i = 0; i < periods.length; i++) {
|
for (int i = 0; i < periods.length; i++) {
|
||||||
pw.println("<li>");
|
buf.append("<li>");
|
||||||
renderPeriod(pw, periods[i], "rate");
|
renderPeriod(buf, periods[i], "rate");
|
||||||
Rate curRate = rate.getRate(periods[i]);
|
Rate curRate = rate.getRate(periods[i]);
|
||||||
pw.print( "<i>avg value:</i> (");
|
buf.append( "<i>avg value:</i> (");
|
||||||
pw.print(num(curRate.getAverageValue()));
|
buf.append(num(curRate.getAverageValue()));
|
||||||
pw.print(" peak ");
|
buf.append(" peak ");
|
||||||
pw.print(num(curRate.getExtremeAverageValue()));
|
buf.append(num(curRate.getExtremeAverageValue()));
|
||||||
pw.print(", [");
|
buf.append(", [");
|
||||||
pw.print(pct(curRate.getPercentageOfExtremeValue()));
|
buf.append(pct(curRate.getPercentageOfExtremeValue()));
|
||||||
pw.print(" of max");
|
buf.append(" of max");
|
||||||
pw.print(", and ");
|
buf.append(", and ");
|
||||||
pw.print(pct(curRate.getPercentageOfLifetimeValue()));
|
buf.append(pct(curRate.getPercentageOfLifetimeValue()));
|
||||||
pw.print(" of lifetime average]");
|
buf.append(" of lifetime average]");
|
||||||
|
|
||||||
pw.print(")");
|
buf.append(")");
|
||||||
pw.print(" <i>highest total period value:</i> (");
|
buf.append(" <i>highest total period value:</i> (");
|
||||||
pw.print(num(curRate.getExtremeTotalValue()));
|
buf.append(num(curRate.getExtremeTotalValue()));
|
||||||
pw.print(")");
|
buf.append(")");
|
||||||
if (curRate.getLifetimeTotalEventTime() > 0) {
|
if (curRate.getLifetimeTotalEventTime() > 0) {
|
||||||
pw.print(" <i>saturation:</i> (");
|
buf.append(" <i>saturation:</i> (");
|
||||||
pw.print(pct(curRate.getLastEventSaturation()));
|
buf.append(pct(curRate.getLastEventSaturation()));
|
||||||
pw.print(")");
|
buf.append(")");
|
||||||
pw.print(" <i>saturated limit:</i> (");
|
buf.append(" <i>saturated limit:</i> (");
|
||||||
pw.print(num(curRate.getLastSaturationLimit()));
|
buf.append(num(curRate.getLastSaturationLimit()));
|
||||||
pw.print(")");
|
buf.append(")");
|
||||||
pw.print(" <i>peak saturation:</i> (");
|
buf.append(" <i>peak saturation:</i> (");
|
||||||
pw.print(pct(curRate.getExtremeEventSaturation()));
|
buf.append(pct(curRate.getExtremeEventSaturation()));
|
||||||
pw.print(")");
|
buf.append(")");
|
||||||
pw.print(" <i>peak saturated limit:</i> (");
|
buf.append(" <i>peak saturated limit:</i> (");
|
||||||
pw.print(num(curRate.getExtremeSaturationLimit()));
|
buf.append(num(curRate.getExtremeSaturationLimit()));
|
||||||
pw.print(")");
|
buf.append(")");
|
||||||
}
|
}
|
||||||
pw.print(" <i>events per period:</i> ");
|
buf.append(" <i>events per period:</i> ");
|
||||||
pw.print(num(curRate.getLastEventCount()));
|
buf.append(num(curRate.getLastEventCount()));
|
||||||
long numPeriods = curRate.getLifetimePeriods();
|
long numPeriods = curRate.getLifetimePeriods();
|
||||||
if (numPeriods > 0) {
|
if (numPeriods > 0) {
|
||||||
double avgFrequency = curRate.getLifetimeEventCount() / (double)numPeriods;
|
double avgFrequency = curRate.getLifetimeEventCount() / (double)numPeriods;
|
||||||
double peakFrequency = curRate.getExtremeEventCount();
|
double peakFrequency = curRate.getExtremeEventCount();
|
||||||
pw.print(" (lifetime average: ");
|
buf.append(" (lifetime average: ");
|
||||||
pw.print(num(avgFrequency));
|
buf.append(num(avgFrequency));
|
||||||
pw.print(", peak average: ");
|
buf.append(", peak average: ");
|
||||||
pw.print(num(curRate.getExtremeEventCount()));
|
buf.append(num(curRate.getExtremeEventCount()));
|
||||||
pw.println(")");
|
buf.append(")");
|
||||||
}
|
}
|
||||||
pw.print("</li>");
|
buf.append("</li>");
|
||||||
if (i + 1 == periods.length) {
|
if (i + 1 == periods.length) {
|
||||||
// last one, so lets display the strict average
|
// last one, so lets display the strict average
|
||||||
pw.print("<li><b>lifetime average value:</b> ");
|
buf.append("<li><b>lifetime average value:</b> ");
|
||||||
pw.print(num(curRate.getLifetimeAverageValue()));
|
buf.append(num(curRate.getLifetimeAverageValue()));
|
||||||
pw.print(" over ");
|
buf.append(" over ");
|
||||||
pw.print(num(curRate.getLifetimeEventCount()));
|
buf.append(num(curRate.getLifetimeEventCount()));
|
||||||
pw.println(" events<br /></li>");
|
buf.append(" events<br /></li>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pw.print("</ul>");
|
buf.append("</ul>");
|
||||||
pw.println("<br />");
|
buf.append("<br />");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void renderPeriod(PrintWriter pw, long period, String name) throws IOException {
|
private static void renderPeriod(StringBuffer buf, long period, String name) {
|
||||||
pw.print("<b>");
|
buf.append("<b>");
|
||||||
pw.print(DataHelper.formatDuration(period));
|
buf.append(DataHelper.formatDuration(period));
|
||||||
pw.print(" ");
|
buf.append(" ");
|
||||||
pw.print(name);
|
buf.append(name);
|
||||||
pw.print(":</b> ");
|
buf.append(":</b> ");
|
||||||
}
|
}
|
||||||
|
|
||||||
private final static DecimalFormat _fmt = new DecimalFormat("###,##0.00");
|
private final static DecimalFormat _fmt = new DecimalFormat("###,##0.00");
|
||||||
|
Reference in New Issue
Block a user