Compare commits

...

2 Commits

Author SHA1 Message Date
zzz
d4e89d1e20 color the filter buttons 2025-04-18 08:25:38 -04:00
zzz
7e35aee6fe Console: /logs page improvements
- Add filter for console log types
- Show recent event logs on /logs page
- Don't translate log types inside loop
2025-04-11 12:22:22 -04:00
4 changed files with 167 additions and 35 deletions

View File

@@ -22,6 +22,8 @@ import net.i2p.util.SystemVersion;
*/ */
public class EventLogHelper extends FormHandler { public class EventLogHelper extends FormHandler {
private long _from, _age; private long _from, _age;
private int _max;
private boolean _reverse = true;
//private long _to = Long.MAX_VALUE; //private long _to = Long.MAX_VALUE;
private String _event = ALL; private String _event = ALL;
// EventLog name to translated display string // EventLog name to translated display string
@@ -82,7 +84,23 @@ public class EventLogHelper extends FormHandler {
} catch (NumberFormatException nfe) { } catch (NumberFormatException nfe) {
_age = 0; _age = 0;
_from = 0; _from = 0;
} }
}
/**
* @since 0.9.66 for /logs
*/
public void setMax(String s) {
try {
_max = Integer.parseInt(s);
} catch (NumberFormatException nfe) {}
}
/**
* @since 0.9.66 for /logs
*/
public void setReverse(String s) {
_reverse = Boolean.parseBoolean(s);
} }
//public void setTo(String s) { //public void setTo(String s) {
@@ -191,7 +209,11 @@ public class EventLogHelper extends FormHandler {
buf.append("</th></tr>"); buf.append("</th></tr>");
List<Map.Entry<Long, String>> entries = new ArrayList<Map.Entry<Long, String>>(events.entrySet()); List<Map.Entry<Long, String>> entries = new ArrayList<Map.Entry<Long, String>>(events.entrySet());
Collections.reverse(entries); int sz = entries.size();
if (_max > 0 && sz > _max)
entries = entries.subList(sz - _max, sz);
if (_reverse)
Collections.reverse(entries);
for (Map.Entry<Long, String> e : entries) { for (Map.Entry<Long, String> e : entries) {
long time = e.getKey().longValue(); long time = e.getKey().longValue();
String event = e.getValue(); String event = e.getValue();
@@ -210,7 +232,7 @@ public class EventLogHelper extends FormHandler {
} else { } else {
buf.append(event); buf.append(event);
} }
buf.append("</td></tr>"); buf.append("</td></tr>\n");
} }
buf.append("</table>"); buf.append("</table>");
return buf.toString(); return buf.toString();

View File

@@ -32,7 +32,14 @@ public class LogsHelper extends HelperBase {
private static final int MAX_WRAPPER_LINES = 250; private static final int MAX_WRAPPER_LINES = 250;
private static final String PROP_LAST_WRAPPER = "routerconsole.lastWrapperLogEntry"; private static final String PROP_LAST_WRAPPER = "routerconsole.lastWrapperLogEntry";
// Homeland Security Advisory System
// http://www.dhs.gov/xinfoshare/programs/Copy_of_press_release_0046.shtm
// but pink instead of yellow for WARN
private static final String COLOR_CRIT = "#cc0000";
private static final String COLOR_ERROR = "#ff3300";
private static final String COLOR_WARN = "#bf00df";
private static final String COLOR_INFO = "#333399";
private static final String COLOR_DEBUG = "#006600";
/** @since 0.8.12 */ /** @since 0.8.12 */
public String getJettyVersion() { public String getJettyVersion() {
@@ -81,7 +88,17 @@ public class LogsHelper extends HelperBase {
* Does not call logManager.flush(); call getCriticalLogs() first to flush * Does not call logManager.flush(); call getCriticalLogs() first to flush
*/ */
public String getLogs() { public String getLogs() {
String str = formatMessages(_context.logManager().getBuffer().getMostRecentMessages()); return getLogs(null);
}
/**
* Does not call logManager.flush(); call getCriticalLogs() first to flush
*
* @param filter log type or null
* @since 0.9.66
*/
public String getLogs(String filter) {
String str = formatMessages(_context.logManager().getBuffer().getMostRecentMessages(), filter);
return "<p>" + _t("File location") + ": <a href=\"/router.log\" target=\"_blank\">" + return "<p>" + _t("File location") + ": <a href=\"/router.log\" target=\"_blank\">" +
DataHelper.escapeHTML(_context.logManager().currentFile()) + "</a></p>" + str; DataHelper.escapeHTML(_context.logManager().currentFile()) + "</a></p>" + str;
} }
@@ -96,7 +113,7 @@ public class LogsHelper extends HelperBase {
if (cmgr != null) if (cmgr != null)
cmgr.setBubble(PortMapper.SVC_LOGS, 0, null); cmgr.setBubble(PortMapper.SVC_LOGS, 0, null);
} }
return formatMessages(msgs); return formatMessages(msgs, null);
} }
/** /**
@@ -260,12 +277,89 @@ public class LogsHelper extends HelperBase {
private final static String NL = System.getProperty("line.separator"); private final static String NL = System.getProperty("line.separator");
/** formats in forward order */ /** formats in forward order */
private String formatMessages(List<String> msgs) { private String formatMessages(List<String> msgs, String filter) {
if (msgs.isEmpty()) if (msgs.isEmpty())
return "</td></tr><tr><td><p><i>" + _t("No log messages") + "</i></p>"; return "</td></tr><tr><td><p><i>" + _t("No log messages") + "</i></p>";
boolean colorize = _context.getBooleanPropertyDefaultTrue("routerconsole.logs.color"); boolean colorize = _context.getBooleanPropertyDefaultTrue("routerconsole.logs.color");
StringBuilder buf = new StringBuilder(16*1024); StringBuilder buf = new StringBuilder(16*1024);
buf.append("</td></tr><tr><td><ul>"); buf.append("</td></tr><tr><td>");
// translate once, out of the loops
String tCRIT = _c("CRIT");
String tERROR = _c("ERROR");
String tWARN = _c("WARN");
String tINFO = _c("INFO");
String tDEBUG = _c("DEBUG");
// filter buttons
int crits = 0, errors = 0, warns = 0, infos = 0, debugs = 0, types = 0;
for (String msg : msgs) {
if (msg.contains(tCRIT)) {
if (crits == 0) types++;
crits++;
} else if (msg.contains(tERROR)) {
if (errors == 0) types++;
errors++;
} else if (msg.contains(tWARN)) {
if (warns == 0) types++;
warns++;
} else if (msg.contains(tINFO)) {
if (infos == 0) types++;
infos++;
} else if (msg.contains(tDEBUG)) {
if (debugs == 0) types++;
debugs++;
}
}
if (types > 1) {
buf.append("<p>").append(_t("Filter")).append(": ");
buf.append("&nbsp;&nbsp;&nbsp;&nbsp;\n");
if (crits > 0) {
if ("crit".equals(filter))
buf.append("<span class=\"tab2\">" + tCRIT + " (" + crits + ")</span>");
else
buf.append("<span class=\"tab\"><a href=\"/logs?f=crit#routerlogs\"><font color=\"" + COLOR_CRIT + "\">" + tCRIT + "</font> (" + crits + ")</a></span>");
buf.append(" &nbsp;&nbsp;&nbsp;&nbsp;\n");
}
if (errors > 0) {
if ("error".equals(filter))
buf.append("<span class=\"tab2\">" + tERROR + " (" + errors + ")</span>");
else
buf.append("<span class=\"tab\"><a href=\"/logs?f=error#routerlogs\"><font color=\"" + COLOR_ERROR + "\">" + tERROR + "</font> (" + errors + ")</a></span>");
buf.append("&nbsp;&nbsp;&nbsp;&nbsp;\n");
}
if (warns > 0) {
if ("warn".equals(filter))
buf.append("<span class=\"tab2\">" + tWARN + " (" + warns + ")</span>");
else
buf.append("<span class=\"tab\"><a href=\"/logs?f=warn#routerlogs\"><font color=\"" + COLOR_WARN + "\">" + tWARN + "</font> (" + warns + ")</a></span>");
buf.append("&nbsp;&nbsp;&nbsp;&nbsp;\n");
}
if (infos > 0) {
if ("info".equals(filter))
buf.append("<span class=\"tab2\">" + tINFO + "< (" + infos + ")</span>");
else
buf.append("<span class=\"tab\"><a href=\"/logs?f=info#routerlogs\"><font color=\"" + COLOR_INFO + "\">" + tINFO + "</font> (" + infos + ")</a></span>");
buf.append("&nbsp;&nbsp;&nbsp;&nbsp;\n");
}
if (debugs > 0) {
if ("debug".equals(filter))
buf.append("<span class=\"tab2\">" + tDEBUG + " (" + debugs + ")</span>");
else
buf.append("<span class=\"tab\"><a href=\"/logs?f=debug#routerlogs\"><font color=\"" + COLOR_DEBUG + "\">" + tDEBUG + "</font> (" + debugs + ")</a></span>");
buf.append("&nbsp;&nbsp;&nbsp;&nbsp;\n");
}
if (filter != null) {
buf.append("<a href=\"/logs#routerlogs\"><img src=\"/themes/console/images/buttons/delete.png\" title=\"")
.append(_t("Remove"))
.append("\" alt=\"")
.append(_t("Remove"))
.append("\"></a>\n");
}
buf.append("</p>\n");
}
buf.append("<br><ul>");
// newest first // newest first
// for (int i = msgs.size() - 1; i >= 0; i--) { // for (int i = msgs.size() - 1; i >= 0; i--) {
// oldest first // oldest first
@@ -287,33 +381,42 @@ public class LogsHelper extends HelperBase {
// replace \n so that exception stack traces will format correctly and will paste nicely into pastebin // replace \n so that exception stack traces will format correctly and will paste nicely into pastebin
msg = msg.replace("\n", "<br>&nbsp;&nbsp;&nbsp;&nbsp;\n"); msg = msg.replace("\n", "<br>&nbsp;&nbsp;&nbsp;&nbsp;\n");
msg = msg.replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;"); msg = msg.replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
buf.append("<li>");
if (colorize) { if (colorize) {
// TODO this would be a lot easier if LogConsoleBuffer stored LogRecords instead of formatted strings // TODO this would be a lot easier if LogConsoleBuffer stored LogRecords instead of formatted strings
String color; String color;
// Homeland Security Advisory System if (msg.contains(tCRIT)) {
// http://www.dhs.gov/xinfoshare/programs/Copy_of_press_release_0046.shtm if (filter != null && !filter.equals("crit"))
// but pink instead of yellow for WARN continue;
if (msg.contains(_c("CRIT"))) color = COLOR_CRIT;
color = "#cc0000"; } else if (msg.contains(tERROR)) {
else if (msg.contains(_c("ERROR"))) if (filter != null && !filter.equals("error"))
color = "#ff3300"; continue;
else if (msg.contains(_c("WARN"))) color = COLOR_ERROR;
// color = "#ff00cc"; poor legibility on light backgrounds } else if (msg.contains(tWARN)) {
color = "#bf00df"; if (filter != null && !filter.equals("warn"))
else if (msg.contains(_c("INFO"))) continue;
color = "#333399"; color = COLOR_WARN;
else } else if (msg.contains(tINFO)) {
color = "#006600"; if (filter != null && !filter.equals("info"))
buf.append("<font color=\"").append(color).append("\">"); continue;
color = COLOR_INFO;
} else {
// skip the "similar messages" lines when filtering
if (filter != null && (!filter.equals("debug") || msg.contains("&uarr;&uarr;&uarr;")))
continue;
color = COLOR_DEBUG;
}
buf.append("<li><font color=\"").append(color).append("\">");
buf.append(msg); buf.append(msg);
buf.append("</font>"); buf.append("</font>");
} else { } else {
// don't bother filtering, colorize is the default
buf.append("<li>");
buf.append(msg); buf.append(msg);
} }
buf.append("</li>\n"); buf.append("</li>\n");
} }
buf.append("</ul>\n"); buf.append("</ul><br>\n");
return buf.toString(); return buf.toString();
} }

View File

@@ -101,7 +101,13 @@
</h3> </h3>
<table id="routerlogs" class="logtable"><tbody> <table id="routerlogs" class="logtable"><tbody>
<tr><td> <tr><td>
<jsp:getProperty name="logsHelper" property="logs" /> <%
String filter = request.getParameter("f");
if (filter != null)
out.write(logsHelper.getLogs(filter));
else
out.write(logsHelper.getLogs());
%>
</td></tr> </td></tr>
</tbody></table> </tbody></table>
@@ -111,6 +117,12 @@
<!-- 90 days --><p><a href="events?from=7776000"><%=intl._t("View event logs")%></a></p> <!-- 90 days --><p><a href="events?from=7776000"><%=intl._t("View event logs")%></a></p>
</td></tr> </td></tr>
</tbody></table> </tbody></table>
<jsp:useBean class="net.i2p.router.web.helpers.EventLogHelper" id="eventHelper" scope="request" />
<jsp:setProperty name="eventHelper" property="contextId" value="<%=i2pcontextId%>" />
<jsp:setProperty name="eventHelper" property="from" value="2592000" />
<jsp:setProperty name="eventHelper" property="max" value="10" />
<jsp:setProperty name="eventHelper" property="reverse" value="false" />
<jsp:getProperty name="eventHelper" property="events" />
<h3 class="tabletitle" id="servicelogs"><%=intl._t("Service (Wrapper) Logs")%><% <h3 class="tabletitle" id="servicelogs"><%=intl._t("Service (Wrapper) Logs")%><%
StringBuilder buf = new StringBuilder(24*1024); StringBuilder buf = new StringBuilder(24*1024);

View File

@@ -1905,10 +1905,6 @@ p {
line-height: 160%; line-height: 160%;
} }
p img:first-child {
display: none !important;
}
p:empty { p:empty {
/* kills empty paragraphs that are likely erroneous eg. see top of /profiles?f=1, /profiles */ /* kills empty paragraphs that are likely erroneous eg. see top of /profiles?f=1, /profiles */
display: none; display: none;
@@ -2781,7 +2777,6 @@ li.noevents {
/* /eventlogs */ /* /eventlogs */
table#eventlog { table#eventlog {
margin-top: -21px;
margin-bottom: 10px; margin-bottom: 10px;
} }
@@ -3901,7 +3896,7 @@ form[action="events"]>.formaction {
margin-left: -21px; margin-left: -21px;
} }
.eventspanel th { #eventlog th {
text-align: left; text-align: left;
padding-left: 10px; padding-left: 10px;
font-size: 10pt; font-size: 10pt;
@@ -3909,15 +3904,15 @@ form[action="events"]>.formaction {
word-spacing: 0.1em; word-spacing: 0.1em;
} }
.eventspanel table { #eventlog table {
font-size: 9pt; font-size: 9pt;
} }
.eventspanel table tr:hover { #eventlog table tr:hover {
background: #002000; background: #002000;
} }
.eventspanel table td { #eventlog table td {
padding: 5px 10px; padding: 5px 10px;
} }