View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2011, 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.html.HTMLLayoutBase;
23  import ch.qos.logback.core.html.IThrowableRenderer;
24  import ch.qos.logback.core.pattern.Converter;
25  import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR;
26  
27  /**
28   * 
29   * HTMLLayout outputs events in an HTML table. <p> The content of the table
30   * columns are specified using a conversion pattern. See
31   * {@link ch.qos.logback.classic.PatternLayout} for documentation on the
32   * available patterns. <p> For more information about this layout, please refer
33   * to the online manual at
34   * http://logback.qos.ch/manual/layouts.html#ClassicHTMLLayout
35   * 
36   * @author Ceki G&uuml;lc&uuml;
37   * @author S&eacute;bastien Pennec
38   */
39  public class HTMLLayout extends HTMLLayoutBase<ILoggingEvent> {
40  
41    /**
42     * Default pattern string for log output.
43     */
44    static final String DEFAULT_CONVERSION_PATTERN = "%date%thread%level%logger%mdc%msg";
45  
46    IThrowableRenderer<ILoggingEvent> throwableRenderer;
47  
48    /**
49     * Constructs a PatternLayout using the DEFAULT_LAYOUT_PATTERN.
50     * 
51     * The default pattern just produces the application supplied message.
52     */
53    public HTMLLayout() {
54      pattern = DEFAULT_CONVERSION_PATTERN;
55      throwableRenderer = new DefaultThrowableRenderer();
56      cssBuilder = new DefaultCssBuilder();
57    }
58  
59    @Override
60    public void start() {
61      int errorCount = 0;
62      if (throwableRenderer == null) {
63        addError("ThrowableRender cannot be null.");
64        errorCount++;
65      }
66      if (errorCount == 0) {
67        super.start();
68      }
69    }
70  
71    protected Map<String, String> getDefaultConverterMap() {
72      return PatternLayout.defaultConverterMap;
73    }
74  
75    public String doLayout(ILoggingEvent event) {
76      StringBuilder buf = new StringBuilder();
77      startNewTableIfLimitReached(buf);
78  
79      boolean odd = true;
80      if (((counter++) & 1) == 0) {
81        odd = false;
82      }
83  
84      String level = event.getLevel().toString().toLowerCase();
85  
86      buf.append(LINE_SEPARATOR);
87      buf.append("<tr class=\"");
88      buf.append(level);
89      if (odd) {
90        buf.append(" odd\">");
91      } else {
92        buf.append(" even\">");
93      }
94      buf.append(LINE_SEPARATOR);
95  
96      Converter<ILoggingEvent> c = head;
97      while (c != null) {
98        appendEventToBuffer(buf, c, event);
99        c = c.getNext();
100     }
101     buf.append("</tr>");
102     buf.append(LINE_SEPARATOR);
103 
104     if (event.getThrowableProxy() != null) {
105       throwableRenderer.render(buf, event);
106     }
107     return buf.toString();
108   }
109 
110   private void appendEventToBuffer(StringBuilder buf,
111       Converter<ILoggingEvent> c, ILoggingEvent event) {
112     buf.append("<td class=\"");
113     buf.append(computeConverterName(c));
114     buf.append("\">");
115     c.write(buf, event);
116     buf.append("</td>");
117     buf.append(LINE_SEPARATOR);
118   }
119 
120   public IThrowableRenderer 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 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 }