forked from I2P_Developers/i2p.i2p
222 lines
7.9 KiB
Java
222 lines
7.9 KiB
Java
package net.i2p.router.web;
|
|
|
|
import java.io.IOException;
|
|
import java.io.Writer;
|
|
import java.text.Collator;
|
|
import java.text.DateFormat;
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.Comparator;
|
|
import java.util.Date;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.TimeZone;
|
|
import java.util.TreeMap;
|
|
|
|
import net.i2p.data.DataHelper;
|
|
import net.i2p.router.util.EventLog;
|
|
|
|
/**
|
|
* /events.jsp
|
|
*/
|
|
public class EventLogHelper extends FormHandler {
|
|
protected Writer _out;
|
|
private long _from, _age;
|
|
//private long _to = Long.MAX_VALUE;
|
|
private String _event = ALL;
|
|
// EventLog name to translated display string
|
|
private final Map<String, String> _xevents;
|
|
|
|
private static final String ALL = "all";
|
|
private static final String[] _events = new String[] {
|
|
EventLog.ABORTED, _x("Aborted startup"),
|
|
EventLog.BECAME_FLOODFILL, _x("Enabled floodfill"),
|
|
EventLog.CHANGE_IP, _x("Changed IP"),
|
|
EventLog.CHANGE_PORT, _x("Changed port"),
|
|
EventLog.CLOCK_SHIFT, _x("Clock shifted"),
|
|
EventLog.CRASHED, _x("Crashed"),
|
|
EventLog.CRITICAL, _x("Critical error"),
|
|
EventLog.INSTALLED, _x("Installed new version"),
|
|
EventLog.INSTALL_FAILED, _x("Install failed"),
|
|
EventLog.NETWORK, _x("Network error"),
|
|
EventLog.NEW_IDENT, _x("New router identity"),
|
|
EventLog.NOT_FLOODFILL, _x("Disabled floodfill"),
|
|
EventLog.OOM, _x("Out of memory error"),
|
|
EventLog.REACHABILITY, _x("Reachability change"),
|
|
EventLog.REKEYED, _x("New router identity"),
|
|
EventLog.RESEED, _x("Reseeded router"),
|
|
EventLog.SOFT_RESTART, _x("Soft restart"),
|
|
EventLog.STARTED, _x("Started router"),
|
|
EventLog.STOPPED, _x("Stopped router"),
|
|
EventLog.UPDATED, _x("Updated router"),
|
|
EventLog.WATCHDOG, _x("Watchdog warning")
|
|
};
|
|
private static final long DAY = 24*60*60*1000L;
|
|
private static final long[] _times = { 0, DAY, 7*DAY, 30*DAY, 365*DAY };
|
|
|
|
public EventLogHelper() {
|
|
super();
|
|
_xevents = new HashMap<String, String>(1 + (_events.length / 2));
|
|
}
|
|
|
|
/** set the defaults after we have a context */
|
|
@Override
|
|
public void setContextId(String contextId) {
|
|
super.setContextId(contextId);
|
|
for (int i = 0; i < _events.length; i += 2) {
|
|
_xevents.put(_events[i], _t(_events[i + 1]));
|
|
}
|
|
}
|
|
|
|
public void storeWriter(Writer out) { _out = out; }
|
|
|
|
public void setFrom(String s) {
|
|
try {
|
|
_age = Long.parseLong(s);
|
|
if (_age > 0)
|
|
_from = _context.clock().now() - _age;
|
|
else
|
|
_from = 0;
|
|
} catch (NumberFormatException nfe) {
|
|
_age = 0;
|
|
_from = 0;
|
|
}
|
|
}
|
|
|
|
//public void setTo(String s) {
|
|
// _to = s;
|
|
//}
|
|
|
|
public void setType(String s) {
|
|
_event = s;
|
|
}
|
|
|
|
public String getForm() {
|
|
// too hard to use the standard formhandler.jsi / FormHandler.java session nonces
|
|
// since graphs.jsp needs the refresh value in its <head>.
|
|
// So just use the "shared/console nonce".
|
|
String nonce = CSSHelper.getNonce();
|
|
try {
|
|
_out.write("<br><h3>" + _t("Display Events") + "</h3>");
|
|
_out.write("<form action=\"events\" method=\"POST\">\n" +
|
|
"<input type=\"hidden\" name=\"action\" value=\"save\">\n" +
|
|
"<input type=\"hidden\" name=\"nonce\" value=\"" + nonce + "\" >\n");
|
|
_out.write(_t("Events since") + ": <select name=\"from\">");
|
|
for (int i = 0; i < _times.length; i++) {
|
|
writeOption(_times[i]);
|
|
}
|
|
_out.write("</select><br>");
|
|
_out.write(_t("Event type") + ": <select name=\"type\">");
|
|
// sorted by translated display string
|
|
Map<String, String> events = new TreeMap<String, String>(Collator.getInstance());
|
|
for (int i = 0; i < _events.length; i += 2) {
|
|
events.put(_xevents.get(_events[i]), _events[i]);
|
|
}
|
|
writeOption(_t("All events"), ALL);
|
|
for (Map.Entry<String, String> e : events.entrySet()) {
|
|
writeOption(e.getKey(), e.getValue());
|
|
}
|
|
_out.write("</select>" +
|
|
"<hr><div class=\"formaction\"><input type=\"submit\" class=\"accept\" value=\"" + _t("Filter events") + "\"></div></form>");
|
|
} catch (IOException ioe) {
|
|
ioe.printStackTrace();
|
|
}
|
|
return "";
|
|
}
|
|
|
|
private void writeOption(String key, String val) throws IOException {
|
|
_out.write("<option value=\"");
|
|
_out.write(val);
|
|
_out.write("\"");
|
|
if (val.equals(_event))
|
|
_out.write(" selected=\"selected\"");
|
|
_out.write(">");
|
|
_out.write(key);
|
|
_out.write("</option>\n");
|
|
}
|
|
|
|
private void writeOption(long age) throws IOException {
|
|
_out.write("<option value=\"");
|
|
_out.write(Long.toString(age));
|
|
_out.write("\"");
|
|
if (age == _age)
|
|
_out.write(" selected=\"selected\"");
|
|
_out.write(">");
|
|
if (age == 0)
|
|
_out.write(_t("All events"));
|
|
else
|
|
_out.write(DataHelper.formatDuration2(age));
|
|
_out.write("</option>\n");
|
|
}
|
|
|
|
public String getEvents() {
|
|
EventLog ev = _context.router().eventLog();
|
|
// oldest first
|
|
Map<Long, String> events;
|
|
boolean isAll = ALL.equals(_event);
|
|
if (isAll)
|
|
events = ev.getEvents(_from);
|
|
else
|
|
events = ev.getEvents(_event, _from);
|
|
String xev = _xevents.get(_event);
|
|
if (xev == null)
|
|
xev = _event;
|
|
xev = DataHelper.escapeHTML(xev);
|
|
if (events.isEmpty()) {
|
|
if (isAll) {
|
|
if (_age == 0)
|
|
return _t("No events found");
|
|
return _t("No events found in previous {0}", DataHelper.formatDuration2(_age));
|
|
}
|
|
if (_age == 0)
|
|
return _t("No \"{0}\" events found", xev);
|
|
return _t("No \"{0}\" events found in previous {1}", xev, DataHelper.formatDuration2(_age));
|
|
}
|
|
StringBuilder buf = new StringBuilder(2048);
|
|
buf.append("<table><tr><th>");
|
|
buf.append(_t("Time"));
|
|
buf.append("</th><th>");
|
|
if (isAll) {
|
|
buf.append(_t("Event"));
|
|
buf.append("</th><th>");
|
|
buf.append(_t("Details"));
|
|
} else {
|
|
buf.append(xev);
|
|
}
|
|
buf.append("</th></tr>");
|
|
|
|
SimpleDateFormat fmt = (SimpleDateFormat) DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM);
|
|
// the router sets the JVM time zone to UTC but saves the original here so we can get it
|
|
String systemTimeZone = _context.getProperty("i2p.systemTimeZone");
|
|
if (systemTimeZone != null)
|
|
fmt.setTimeZone(TimeZone.getTimeZone(systemTimeZone));
|
|
|
|
List<Map.Entry<Long, String>> entries = new ArrayList<Map.Entry<Long, String>>(events.entrySet());
|
|
Collections.reverse(entries);
|
|
for (Map.Entry<Long, String> e : entries) {
|
|
long time = e.getKey().longValue();
|
|
String event = e.getValue();
|
|
buf.append("<tr><td>");
|
|
buf.append(fmt.format(new Date(time)));
|
|
buf.append("</td><td>");
|
|
if (isAll) {
|
|
String[] s = DataHelper.split(event, " ", 2);
|
|
String xs = _xevents.get(s[0]);
|
|
if (xs == null)
|
|
xs = s[0];
|
|
buf.append(xs);
|
|
buf.append("</td><td>");
|
|
if (s.length > 1)
|
|
buf.append(s[1]);
|
|
} else {
|
|
buf.append(event);
|
|
}
|
|
buf.append("</td></tr>");
|
|
}
|
|
buf.append("</table>");
|
|
return buf.toString();
|
|
}
|
|
}
|