
Author: ceki Date: Tue Dec 30 19:40:15 2008 New Revision: 2119 Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/ViewStatusMessageServlet.java logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/Transform.java - copied, changed from r2086, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/helpers/Transform.java logback/trunk/logback-core/src/main/java/ch/qos/logback/core/status/ViewStatusMessagesServletBase.java Removed: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/helpers/Transform.java Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/ClassicGlobal.java logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultThrowableRenderer.java logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassNameOnlyAbbreviator.java logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/TargetLengthBasedClassNameAbbreviator.java logback/trunk/logback-core/pom.xml logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java logback/trunk/logback-core/src/main/java/ch/qos/logback/core/html/IThrowableRenderer.java Log: - Added a servlet for viewing status messages. This begins to address LBCORE-81 Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/ClassicGlobal.java ============================================================================== --- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/ClassicGlobal.java (original) +++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/ClassicGlobal.java Tue Dec 30 19:40:15 2008 @@ -1,17 +1,16 @@ -/** - * LOGBack: the reliable, fast and flexible logging library for Java. - * - * Copyright (C) 1999-2005, QOS.ch, LOGBack.com - * - * This library is free software, you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation. +/** + * Logback: the generic, reliable, fast and flexible logging framework. + * + * Copyright (C) 2000-2008, QOS.ch + * + * This library is free software, you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation. */ package ch.qos.logback.classic; public class ClassicGlobal { static public final char LOGGER_SEPARATOR = '.'; - static public final char DOT = '.'; static public final String USER_MDC_KEY = "user"; public static final String LOGBACK_CONTEXT_SELECTOR = "logback.ContextSelector"; Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/ViewStatusMessageServlet.java ============================================================================== --- (empty file) +++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/ViewStatusMessageServlet.java Tue Dec 30 19:40:15 2008 @@ -0,0 +1,36 @@ +/** + * Logback: the generic, reliable, fast and flexible logging framework. + * + * Copyright (C) 2000-2008, QOS.ch + * + * This library is free software, you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation. + */ +package ch.qos.logback.classic; + +import org.slf4j.LoggerFactory; + +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.status.ViewStatusMessagesServletBase; + +public class ViewStatusMessageServlet extends ViewStatusMessagesServletBase { + + private static final long serialVersionUID = 443878494348593337L; + + // + + @Override + protected StatusManager getStatusManager() { + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + return lc.getStatusManager(); + } + + @Override + protected String getPageTitle() { + LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); + return "<h2>Status messages for LoggerContext named [" + + lc.getName() + "]</h2>\r\n"; + } + +} Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultThrowableRenderer.java ============================================================================== --- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultThrowableRenderer.java (original) +++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultThrowableRenderer.java Tue Dec 30 19:40:15 2008 @@ -1,10 +1,19 @@ +/** + * Logback: the generic, reliable, fast and flexible logging framework. + * + * Copyright (C) 2000-2008, QOS.ch + * + * This library is free software, you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation. + */ package ch.qos.logback.classic.html; import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR; -import ch.qos.logback.classic.helpers.Transform; import ch.qos.logback.classic.spi.LoggingEvent; import ch.qos.logback.classic.spi.ThrowableDataPoint; import ch.qos.logback.classic.spi.ThrowableProxy; +import ch.qos.logback.core.helpers.Transform; import ch.qos.logback.core.html.IThrowableRenderer; public class DefaultThrowableRenderer implements IThrowableRenderer { Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassNameOnlyAbbreviator.java ============================================================================== --- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassNameOnlyAbbreviator.java (original) +++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassNameOnlyAbbreviator.java Tue Dec 30 19:40:15 2008 @@ -9,7 +9,7 @@ */ package ch.qos.logback.classic.pattern; -import ch.qos.logback.classic.ClassicGlobal; +import ch.qos.logback.core.CoreConstants; /** * This abbreviator returns the class name from a fully qualified class name, @@ -20,7 +20,7 @@ public class ClassNameOnlyAbbreviator implements Abbreviator { public String abbreviate(String fqClassName) { - int lastIndex = fqClassName.lastIndexOf(ClassicGlobal.DOT); + int lastIndex = fqClassName.lastIndexOf(CoreConstants.DOT); if (lastIndex != -1) { return fqClassName.substring(lastIndex + 1, fqClassName.length()); } else { Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/TargetLengthBasedClassNameAbbreviator.java ============================================================================== --- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/TargetLengthBasedClassNameAbbreviator.java (original) +++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/TargetLengthBasedClassNameAbbreviator.java Tue Dec 30 19:40:15 2008 @@ -9,7 +9,7 @@ */ package ch.qos.logback.classic.pattern; -import ch.qos.logback.classic.ClassicGlobal; +import ch.qos.logback.core.CoreConstants; public class TargetLengthBasedClassNameAbbreviator implements Abbreviator { @@ -71,7 +71,7 @@ int dotCount = 0; int k = 0; while (true) { - k = className.indexOf(ClassicGlobal.DOT, k); + k = className.indexOf(CoreConstants.DOT, k); if (k != -1 && dotCount < MAX_DOTS) { dotArray[dotCount] = k; dotCount++; Modified: logback/trunk/logback-core/pom.xml ============================================================================== --- logback/trunk/logback-core/pom.xml (original) +++ logback/trunk/logback-core/pom.xml Tue Dec 30 19:40:15 2008 @@ -59,6 +59,12 @@ <scope>test</scope> </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>servlet-api</artifactId> + <scope>compile</scope> + <optional>true</optional> + </dependency> </dependencies> Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java ============================================================================== --- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java (original) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java Tue Dec 30 19:40:15 2008 @@ -78,5 +78,6 @@ * Ceki's machine (Orion) */ public static long REFERENCE_BIPS = 9000; + static public final char DOT = '.'; } Copied: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/Transform.java (from r2086, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/helpers/Transform.java) ============================================================================== --- /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/helpers/Transform.java (original) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/Transform.java Tue Dec 30 19:40:15 2008 @@ -7,7 +7,7 @@ * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation. */ -package ch.qos.logback.classic.helpers; +package ch.qos.logback.core.helpers; /** * Utility class for transforming strings. @@ -40,6 +40,18 @@ } StringBuffer buf = new StringBuffer(input); + return escapeTags(buf); + } + + + /** + * This method takes a StringBuilder which may contain HTML tags (ie, <b>, + * <table>, etc) and replaces any '<' and '>' characters with + * respective predefined entity references. + * @param buf + * @return + */ + public static String escapeTags(final StringBuffer buf) { for (int i = 0; i < buf.length(); i++) { char ch = buf.charAt(i); if (ch == '<') { @@ -50,10 +62,7 @@ } return buf.toString(); } - - // public static void appendEscapingCDATA(StringBuffer buf, String str) { - // - // } + /** * Ensures that embeded CDEnd strings (]]>) are handled properly within Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/html/IThrowableRenderer.java ============================================================================== --- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/html/IThrowableRenderer.java (original) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/html/IThrowableRenderer.java Tue Dec 30 19:40:15 2008 @@ -1,3 +1,12 @@ +/** + * Logback: the generic, reliable, fast and flexible logging framework. + * + * Copyright (C) 2000-2008, QOS.ch + * + * This library is free software, you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation. + */ package ch.qos.logback.core.html; Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/status/ViewStatusMessagesServletBase.java ============================================================================== --- (empty file) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/status/ViewStatusMessagesServletBase.java Tue Dec 30 19:40:15 2008 @@ -0,0 +1,173 @@ +/** + * Logback: the generic, reliable, fast and flexible logging framework. + * + * Copyright (C) 2000-2008, QOS.ch + * + * This library is free software, you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation. + */ +package ch.qos.logback.core.status; + +import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.text.SimpleDateFormat; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.helpers.Transform; + +abstract public class ViewStatusMessagesServletBase extends HttpServlet { + + private static final long serialVersionUID = -3551928133801157219L; + private static SimpleDateFormat SDF = new SimpleDateFormat( + "yyyy-MM-dd HH:mm:ss"); + + protected abstract StatusManager getStatusManager(); + + protected abstract String getPageTitle(); + + int count; + + protected void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + + count = 0; + StatusManager sm = getStatusManager(); + + resp.setContentType("text/html"); + PrintWriter output = resp.getWriter(); + + output.append("<html>\r\n"); + output.append("<head>\r\n"); + printCSS(req.getContextPath(), output); + output.append("</head>\r\n"); + output.append("<body>\r\n"); + output.append(getPageTitle()); + + output.append("<table>"); + StringBuilder buf = new StringBuilder(); + printList(buf, sm); + output.append(buf); + output.append("</table>"); + output.append("</body>\r\n"); + output.append("</html>\r\n"); + output.flush(); + output.close(); + } + + public void printCSS(String localRef, PrintWriter output) { + output.append(" <STYLE TYPE=\"text/css\">\r\n"); + output.append(" .warn { font-weight: bold; color: #FF6600;} \r\n"); // orange + output.append(" .error { font-weight: bold; color: #CC0000;} \r\n"); + output + .append(" table { margin-left: 2em; margin-right: 2em; border-left: 2px solid #AAA; }\r\n"); + output.append(" tr.even { background: #FFFFFF; }\r\n"); + output.append(" tr.odd { background: #EAEAEA; }\r\n"); + output + .append(" td { padding-right: 1ex; padding-left: 1ex; border-right: 2px solid #AAA; }\r\n"); + output + .append(" td.date { text-align: right; font-family: courier, monospace; font-size: smaller; }"); + output.append(LINE_SEPARATOR); + + output.append(" td.level { text-align: right; }"); + output.append(LINE_SEPARATOR); + output + .append(" tr.header { background: #596ED5; color: #FFF; font-weight: bold; font-size: larger; }"); + output.append(CoreConstants.LINE_SEPARATOR); + + output + .append(" td.exception { background: #A2AEE8; white-space: pre; font-family: courier, monospace;}"); + output.append(LINE_SEPARATOR); + + output.append(" </STYLE>\r\n"); + + } + + public void printList(StringBuilder buf, StatusManager sm) { + buf.append("<table>\r\n"); + printHeader(buf); + List<Status> statusList = sm.getCopyOfStatusList(); + for (Status s : statusList) { + count++; + printStatus(buf, s); + } + buf.append("</table>\r\n"); + } + + public void printHeader(StringBuilder buf) { + buf.append(" <tr class=\"header\">\r\n"); + buf.append(" <th>Date </th>\r\n"); + buf.append(" <th>Level</th>\r\n"); + buf.append(" <th>Origin</th>\r\n"); + buf.append(" <th>Message</th>\r\n"); + buf.append(" </tr>\r\n"); + + } + + String statusLevelAsString(Status s) { + switch (s.getEffectiveLevel()) { + case Status.INFO: + return "INFO"; + case Status.WARN: + return "<span class=\"warn\">WARN</span>"; + case Status.ERROR: + return "<span class=\"error\">ERROR</span>"; + } + return null; + } + + String abbreviatedOrigin(Status s) { + Object o = s.getOrigin(); + if (o == null) { + return null; + } + String fqClassName = o.getClass().getName(); + int lastIndex = fqClassName.lastIndexOf(CoreConstants.DOT); + if (lastIndex != -1) { + return fqClassName.substring(lastIndex + 1, fqClassName.length()); + } else { + return fqClassName; + } + } + + private void printStatus(StringBuilder buf, Status s) { + String trClass; + if (count % 2 == 0) { + trClass = "even"; + } else { + trClass = "odd"; + } + buf.append(" <tr class=\"").append(trClass).append("\">\r\n"); + String dateStr = SDF.format(s.getDate()); + buf.append(" <td class=\"date\">").append(dateStr).append("</td>\r\n"); + buf.append(" <td class=\"level\">").append(statusLevelAsString(s)) + .append("</td>\r\n"); + buf.append(" <td>").append(abbreviatedOrigin(s)).append("</td>\r\n"); + buf.append(" <td>").append(s.getMessage()).append("</td>\r\n"); + buf.append(" </tr>\r\n"); + if (s.getThrowable() != null) { + printThrowable(buf, s.getThrowable()); + } + } + + private void printThrowable(StringBuilder buf, Throwable t) { + buf.append(" <tr>\r\n"); + buf.append(" <td colspan=\"4\" class=\"exception\">"); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + t.printStackTrace(pw); + buf.append(Transform.escapeTags(sw.getBuffer())); + buf.append(" </td>\r\n"); + buf.append(" </tr>\r\n"); + + } +}