View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.classic.html;
15  
16  import java.util.Map;
17  
18  import ch.qos.logback.classic.PatternLayout;
19  import ch.qos.logback.classic.pattern.MDCConverter;
20  import ch.qos.logback.classic.spi.ILoggingEvent;
21  import ch.qos.logback.classic.html.DefaultCssBuilder;
22  import ch.qos.logback.core.helpers.Transform;
23  import ch.qos.logback.core.html.HTMLLayoutBase;
24  import ch.qos.logback.core.html.IThrowableRenderer;
25  import ch.qos.logback.core.pattern.Converter;
26  import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR;
27  
28  /**
29   * 
30   * HTMLLayout outputs events in an HTML table. <p> The content of the table
31   * columns are specified using a conversion pattern. See
32   * {@link ch.qos.logback.classic.PatternLayout} for documentation on the
33   * available patterns. <p> For more information about this layout, please refer
34   * to the online manual at
35   * http://logback.qos.ch/manual/layouts.html#ClassicHTMLLayout
36   * 
37   * @author Ceki G&uuml;lc&uuml;
38   * @author S&eacute;bastien Pennec
39   */
40  public class HTMLLayout extends HTMLLayoutBase<ILoggingEvent> {
41  
42      /**
43       * Default pattern string for log output.
44       */
45      static final String DEFAULT_CONVERSION_PATTERN = "%date%thread%level%logger%mdc%msg";
46  
47      IThrowableRenderer<ILoggingEvent> throwableRenderer;
48  
49      /**
50       * Constructs a PatternLayout using the DEFAULT_LAYOUT_PATTERN.
51       * 
52       * The default pattern just produces the application supplied message.
53       */
54      public HTMLLayout() {
55          pattern = DEFAULT_CONVERSION_PATTERN;
56          throwableRenderer = new DefaultThrowableRenderer();
57          cssBuilder = new DefaultCssBuilder();
58      }
59  
60      @Override
61      public void start() {
62          int errorCount = 0;
63          if (throwableRenderer == null) {
64              addError("ThrowableRender cannot be null.");
65              errorCount++;
66          }
67          if (errorCount == 0) {
68              super.start();
69          }
70      }
71  
72      protected Map<String, String> getDefaultConverterMap() {
73          return PatternLayout.defaultConverterMap;
74      }
75  
76      public String doLayout(ILoggingEvent event) {
77          StringBuilder buf = new StringBuilder();
78          startNewTableIfLimitReached(buf);
79  
80          boolean odd = true;
81          if (((counter++) & 1) == 0) {
82              odd = false;
83          }
84  
85          String level = event.getLevel().toString().toLowerCase();
86  
87          buf.append(LINE_SEPARATOR);
88          buf.append("<tr class=\"");
89          buf.append(level);
90          if (odd) {
91              buf.append(" odd\">");
92          } else {
93              buf.append(" even\">");
94          }
95          buf.append(LINE_SEPARATOR);
96  
97          Converter<ILoggingEvent> c = head;
98          while (c != null) {
99              appendEventToBuffer(buf, c, event);
100             c = c.getNext();
101         }
102         buf.append("</tr>");
103         buf.append(LINE_SEPARATOR);
104 
105         if (event.getThrowableProxy() != null) {
106             throwableRenderer.render(buf, event);
107         }
108         return buf.toString();
109     }
110 
111     private void appendEventToBuffer(StringBuilder buf, Converter<ILoggingEvent> c, ILoggingEvent event) {
112         buf.append("<td class=\"");
113         buf.append(computeConverterName(c));
114         buf.append("\">");
115         buf.append(Transform.escapeTags(c.convert(event)));
116         buf.append("</td>");
117         buf.append(LINE_SEPARATOR);
118     }
119 
120     public IThrowableRenderer<ILoggingEvent> getThrowableRenderer() {
121         return throwableRenderer;
122     }
123 
124     public void setThrowableRenderer(IThrowableRenderer<ILoggingEvent> throwableRenderer) {
125         this.throwableRenderer = throwableRenderer;
126     }
127 
128     @Override
129     protected String computeConverterName(Converter<ILoggingEvent> c) {
130         if (c instanceof MDCConverter) {
131             MDCConverter mc = (MDCConverter) c;
132             String key = mc.getFirstOption();
133             if (key != null) {
134                 return key;
135             } else {
136                 return "MDC";
137             }
138         } else {
139             return super.computeConverterName(c);
140         }
141     }
142 }