
Author: seb Date: Wed Sep 13 15:51:24 2006 New Revision: 574 Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/ThrowableRenderer.java Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/HTMLLayout.java logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableHandlingConverter.java logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java Log: - added ThrowableRenderer class to manage the output of exceptions - updated HTMLLayout to use the new class - updated tests - removed the unnecessary method onNewLine from ThrowableHandlingConverter Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/HTMLLayout.java ============================================================================== --- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/HTMLLayout.java (original) +++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/HTMLLayout.java Wed Sep 13 15:51:24 2006 @@ -13,10 +13,7 @@ import ch.qos.logback.classic.ClassicLayout; import ch.qos.logback.classic.PatternLayout; import ch.qos.logback.classic.helpers.CssBuilder; -import ch.qos.logback.classic.helpers.Transform; -import ch.qos.logback.classic.pattern.ThrowableHandlingConverter; import ch.qos.logback.classic.spi.LoggingEvent; -import ch.qos.logback.classic.spi.ThrowableInformation; import ch.qos.logback.core.LayoutBase; import ch.qos.logback.core.pattern.Converter; import ch.qos.logback.core.pattern.DynamicConverter; @@ -42,25 +39,23 @@ */ static final String DEFAULT_CONVERSION_PATTERN = "%date%thread%level%logger%mdc%msg"; - static final String TRACE_PREFIX = "<br /> "; protected final int BUF_SIZE = 256; protected final int MAX_CAPACITY = 1024; - + private String pattern; - + private Converter head; - - //private String timezone; + + // private String timezone; private String title = "Logback Log Messages"; private CssBuilder cssBuilder; - // Does our PatternConverter chain handle throwable on its own? - private boolean chainHandlesThrowable; + ThrowableRenderer throwableRenderer = new ThrowableRenderer(); // counter keeping track of the rows output private long counter = 0; - //max number of rows before we close the table and create a new one + // max number of rows before we close the table and create a new one private static final int ROW_LIMIT = 10000; /** @@ -87,11 +82,11 @@ public String getPattern() { return pattern; } - + public CssBuilder getCssBuilder() { return cssBuilder; } - + public void setCssBuilder(CssBuilder cssBuilder) { this.cssBuilder = cssBuilder; } @@ -107,25 +102,13 @@ } Node t = p.parse(); this.head = p.compile(t, PatternLayout.defaultConverterMap); - postCompileProcessing(head); DynamicConverter.startConverters(this.head); - } catch (ScanException ex) { + } catch (ScanException ex) { addError("Incorrect pattern found", ex); } - + started = true; } - - private void postCompileProcessing(Converter c) { - while (c != null) { - if (c instanceof ThrowableHandlingConverter) { - chainHandlesThrowable = true; - return; - } - c = c.getNext(); - } - chainHandlesThrowable = false; - } /** * The <b>Title </b> option takes a String value. This option sets the @@ -153,30 +136,15 @@ return "text/html"; } - void appendThrowableAsHTML(final String[] s, final StringBuffer sbuf) { - if (s != null) { - int len = s.length; - if (len == 0) { - return; - } - sbuf.append(Transform.escapeTags(s[0])); - sbuf.append(LINE_SEP); - for (int i = 1; i < len; i++) { - sbuf.append(TRACE_PREFIX); - sbuf.append(Transform.escapeTags(s[i])); - sbuf.append(LINE_SEP); - } - } - } - /** * Returns appropriate HTML headers. */ public String getHeader() { StringBuffer sbuf = new StringBuffer(); - + // PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + // SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" sbuf.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\""); - sbuf.append(" SYSTEM \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"); + sbuf.append(" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"); sbuf.append(LINE_SEP); sbuf.append("<html>"); sbuf.append(LINE_SEP); @@ -208,7 +176,7 @@ sbuf.append(LINE_SEP); sbuf.append("<table cellspacing=\"0\">"); sbuf.append(LINE_SEP); - + createTableHeader(sbuf); return sbuf.toString(); @@ -220,10 +188,10 @@ sbuf.append("<tr class=\"header\">"); sbuf.append(LINE_SEP); while (c != null) { - if (c instanceof ThrowableHandlingConverter) { - c = c.getNext(); - continue; - } + // if (c instanceof ThrowableHandlingConverter) { + // c = c.getNext(); + // continue; + // } name = computeConverterName(c); if (name == null) { c = c.getNext(); @@ -234,14 +202,12 @@ sbuf.append("\">"); sbuf.append(computeConverterName(c)); sbuf.append("</td>"); - sbuf.append(LINE_SEP); + sbuf.append(LINE_SEP); c = c.getNext(); } sbuf.append("</tr>"); sbuf.append(LINE_SEP); } - - /** * Returns the appropriate HTML footers. @@ -263,7 +229,7 @@ public String doLayout(LoggingEvent event) { StringBuffer buf = new StringBuffer(); handleTableClosing(buf); - + boolean odd = true; if (((counter++) & 1) == 0) { odd = false; @@ -271,7 +237,6 @@ String level = event.getLevel().toString().toLowerCase(); - buf.append(LINE_SEP); buf.append("<tr class=\""); buf.append(level); @@ -284,44 +249,20 @@ Converter c = head; while (c != null) { - if (c instanceof ThrowableHandlingConverter) { - ThrowableHandlingConverter converter = (ThrowableHandlingConverter)c; - if (converter.onNewLine(event)) { - buf.append("</tr>"); - buf.append("<tr colspan=\"6\">"); - appendThrowableAsHTML(event.getThrowableInformation().getThrowableStrRep(), buf); - //appendEventToBuffer(buf, c, event); - if (c.getNext() != null) { - //here we assume that when we exist the while loop, - //a </tr> tag is added. - buf.append("</tr>"); - buf.append("<tr>"); - } - } - } else { - appendEventToBuffer(buf, c, event); - } + appendEventToBuffer(buf, c, event); c = c.getNext(); } buf.append("</tr>"); buf.append(LINE_SEP); - // if the pattern chain handles throwables then no need to do it again here. - if (!chainHandlesThrowable) { - ThrowableInformation ti = event.getThrowableInformation(); - if (ti != null) { - String[] s = ti.getThrowableStrRep(); - if (s != null) { - buf.append("<tr><td class=\"Exception\" colspan=\"6\">"); - appendThrowableAsHTML(s, buf); - buf.append("</td></tr>"); - buf.append(LINE_SEP); - } - } + if (throwableRenderer.newLineRequired(event)) { + buf.append("<tr><td class=\"Exception\" colspan=\"6\">"); + throwableRenderer.render(buf, event); + buf.append("</td></tr>"); } return buf.toString(); } - + private void handleTableClosing(StringBuffer sbuf) { if (this.counter >= ROW_LIMIT) { counter = 0; @@ -333,64 +274,18 @@ createTableHeader(sbuf); } } - - private void appendEventToBuffer(StringBuffer buf, Converter c, LoggingEvent event) { + + private void appendEventToBuffer(StringBuffer buf, Converter c, + LoggingEvent event) { buf.append("<td class=\""); buf.append(computeConverterName(c)); buf.append("\">"); buf.append(c.convert(event)); buf.append("</td>"); - buf.append(LINE_SEP); - } - - /** - * Generate an internal CSS file. - * - * @param buf The StringBuffer where the CSS file will be placed. - */ - void getInternalCSS(StringBuffer buf) { - - buf.append("<STYLE type=\"text/css\">"); - buf.append(LINE_SEP); - buf.append("table { margin-left: 2em; margin-right: 2em; border-left: 2px solid #AAA; }"); - buf.append(LINE_SEP); - - buf.append("TR.even { background: #FFFFFF; }"); - buf.append(LINE_SEP); - - buf.append("TR.odd { background: #DADADA; }"); - buf.append(LINE_SEP); - - buf.append("TR.warn TD.level, TR.error TD.level, TR.fatal TD.level {font-weight: bold; color: #FF4040 }"); - buf.append(LINE_SEP); - - buf.append("TD { padding-right: 1ex; padding-left: 1ex; border-right: 2px solid #AAA; }"); - buf.append(LINE_SEP); - - buf.append("TD.Time, TD.Date { text-align: right; font-family: courier, monospace; font-size: smaller; }"); buf.append(LINE_SEP); - - buf.append("TD.Thread { text-align: left; }"); - buf.append(LINE_SEP); - - buf.append("TD.Level { text-align: right; }"); - buf.append(LINE_SEP); - - buf.append("TD.Logger { text-align: left; }"); - buf.append(LINE_SEP); - - buf.append("TR.header { background: #9090FF; color: #FFF; font-weight: bold; font-size: larger; }"); - buf.append(LINE_SEP); - - buf.append("TD.Exception { background: #C0C0F0; font-family: courier, monospace;}"); - buf.append(LINE_SEP); - - buf.append("</STYLE>"); - buf.append(LINE_SEP); - } - - private String computeConverterName(Converter c) { + + private String computeConverterName(Converter c) { String className = c.getClass().getSimpleName(); int index = className.indexOf("Converter"); if (index == -1) { Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/ThrowableRenderer.java ============================================================================== --- (empty file) +++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/ThrowableRenderer.java Wed Sep 13 15:51:24 2006 @@ -0,0 +1,44 @@ +package ch.qos.logback.classic.html; + +import static ch.qos.logback.core.Layout.LINE_SEP; +import ch.qos.logback.classic.helpers.Transform; +import ch.qos.logback.classic.spi.LoggingEvent; + +public class ThrowableRenderer { + + static final String TRACE_PREFIX = "<br /> "; + + Throwable throwable; + + public ThrowableRenderer() { + + } + + public void setThrowable(Throwable t) { + this.throwable = t; + } + + public boolean newLineRequired(LoggingEvent event) { + return event.getThrowableInformation() != null; + } + + public void render(StringBuffer sbuf, String[] s) { + if (s != null) { + int len = s.length; + if (len == 0) { + return; + } + sbuf.append(Transform.escapeTags(s[0])); + sbuf.append(LINE_SEP); + for (int i = 1; i < len; i++) { + sbuf.append(TRACE_PREFIX); + sbuf.append(Transform.escapeTags(s[i])); + sbuf.append(LINE_SEP); + } + } + } + + public void render(StringBuffer sbuf, LoggingEvent event) { + render(sbuf, event.getThrowableInformation().getThrowableStrRep()); + } +} Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableHandlingConverter.java ============================================================================== --- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableHandlingConverter.java (original) +++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableHandlingConverter.java Wed Sep 13 15:51:24 2006 @@ -1,7 +1,5 @@ package ch.qos.logback.classic.pattern; -import ch.qos.logback.classic.pattern.ClassicConverter; -import ch.qos.logback.classic.spi.LoggingEvent; /** @@ -13,9 +11,4 @@ boolean handlesThrowable() { return true; } - - // tentatively... - public boolean onNewLine(LoggingEvent le) { - return le.getThrowableInformation() != null; - } } Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java ============================================================================== --- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java (original) +++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java Wed Sep 13 15:51:24 2006 @@ -31,7 +31,7 @@ appender.setContext(lc); layout = new HTMLLayout(); layout.setContext(lc); - layout.setPattern("%level %thread %msg"); + layout.setPattern("%level%thread%msg"); layout.start(); appender.setLayout(layout); logger = lc.getLogger(LoggerContext.ROOT_NAME); @@ -58,20 +58,18 @@ Element trElement = tableElement.element("tr"); List<Element> elementList = trElement.elements(); assertEquals("Level", elementList.get(0).getText()); - assertEquals("Literal", elementList.get(1).getText()); - assertEquals("Thread", elementList.get(2).getText()); - assertEquals("Literal", elementList.get(3).getText()); - assertEquals("Message", elementList.get(4).getText()); + assertEquals("Thread", elementList.get(1).getText()); + assertEquals("Message", elementList.get(2).getText()); } public void testAppendThrowable() throws Exception { StringBuffer buf = new StringBuffer(); String[] strArray = { "test1", "test2" }; - layout.appendThrowableAsHTML(strArray, buf); + layout.throwableRenderer.render(buf, strArray); // System.out.println(buf.toString()); String[] result = buf.toString().split(HTMLLayout.LINE_SEP); assertEquals("test1", result[0]); - assertEquals(HTMLLayout.TRACE_PREFIX + "test2", result[1]); + assertEquals(ThrowableRenderer.TRACE_PREFIX + "test2", result[1]); } public void testDoLayout() throws Exception { @@ -79,25 +77,17 @@ String result = layout.doLayout(le); Document doc = parseOutput(result); Element trElement = doc.getRootElement(); - assertEquals(5, trElement.elements().size()); + assertEquals(3, trElement.elements().size()); { Element tdElement = (Element) trElement.elements().get(0); assertEquals("DEBUG", tdElement.getText()); } { Element tdElement = (Element) trElement.elements().get(1); - assertEquals(" ", tdElement.getText()); - } - { - Element tdElement = (Element) trElement.elements().get(2); assertEquals("main", tdElement.getText()); } { - Element tdElement = (Element) trElement.elements().get(3); - assertEquals(" ", tdElement.getText()); - } - { - Element tdElement = (Element) trElement.elements().get(4); + Element tdElement = (Element) trElement.elements().get(2); assertEquals("test message", tdElement.getText()); } // System.out.println(result); @@ -130,8 +120,12 @@ } // public void testLog() { -// for (int i = 1; i <= 1000; i++) { -// logger.debug("test message" + i); +// for (int i = 1; i <= 10; i++) { +// if (i == 5 || i == 8) { +// logger.debug("test", new Exception("test exception")); +// } else { +// logger.debug("test message" + i); +// } // } // }