1
2
3
4
5
6
7
8
9
10
11
12
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.core.helpers.Transform;
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
30
31
32
33
34
35
36
37
38
39
40
41 public class HTMLLayout extends HTMLLayoutBase<ILoggingEvent> {
42
43
44
45
46 static final String DEFAULT_CONVERSION_PATTERN = "%date%thread%level%logger%mdc%msg";
47
48 IThrowableRenderer<ILoggingEvent> throwableRenderer;
49
50
51
52
53
54
55 public HTMLLayout() {
56 pattern = DEFAULT_CONVERSION_PATTERN;
57 throwableRenderer = new DefaultThrowableRenderer();
58 cssBuilder = new DefaultCssBuilder();
59 }
60
61 @Override
62 public void start() {
63 int errorCount = 0;
64 if (throwableRenderer == null) {
65 addError("ThrowableRender cannot be null.");
66 errorCount++;
67 }
68 if (errorCount == 0) {
69 super.start();
70 }
71 }
72
73 protected Map<String, String> getDefaultConverterMap() {
74 return PatternLayout.DEFAULT_CONVERTER_MAP;
75 }
76
77 public String doLayout(ILoggingEvent event) {
78 StringBuilder buf = new StringBuilder();
79 startNewTableIfLimitReached(buf);
80
81 boolean odd = true;
82 if (((counter++) & 1) == 0) {
83 odd = false;
84 }
85
86 String level = event.getLevel().toString().toLowerCase();
87
88 buf.append(LINE_SEPARATOR);
89 buf.append("<tr class=\"");
90 buf.append(level);
91 if (odd) {
92 buf.append(" odd\">");
93 } else {
94 buf.append(" even\">");
95 }
96 buf.append(LINE_SEPARATOR);
97
98 Converter<ILoggingEvent> c = head;
99 while (c != null) {
100 appendEventToBuffer(buf, c, event);
101 c = c.getNext();
102 }
103 buf.append("</tr>");
104 buf.append(LINE_SEPARATOR);
105
106 if (event.getThrowableProxy() != null) {
107 throwableRenderer.render(buf, event);
108 }
109 return buf.toString();
110 }
111
112 private void appendEventToBuffer(StringBuilder buf, Converter<ILoggingEvent> c, ILoggingEvent event) {
113 buf.append("<td class=\"");
114 buf.append(computeConverterName(c));
115 buf.append("\">");
116 buf.append(Transform.escapeTags(c.convert(event)));
117 buf.append("</td>");
118 buf.append(LINE_SEPARATOR);
119 }
120
121 public IThrowableRenderer<ILoggingEvent> getThrowableRenderer() {
122 return throwableRenderer;
123 }
124
125 public void setThrowableRenderer(IThrowableRenderer<ILoggingEvent> throwableRenderer) {
126 this.throwableRenderer = throwableRenderer;
127 }
128
129 @Override
130 protected String computeConverterName(Converter<ILoggingEvent> c) {
131 if (c instanceof MDCConverter) {
132 MDCConverter mc = (MDCConverter) c;
133 String key = mc.getFirstOption();
134 if (key != null) {
135 return key;
136 } else {
137 return "MDC";
138 }
139 } else {
140 return super.computeConverterName(c);
141 }
142 }
143 }