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