1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.layout;
18
19 import java.io.IOException;
20 import java.io.Writer;
21 import java.nio.charset.Charset;
22 import java.nio.charset.StandardCharsets;
23 import java.util.HashMap;
24 import java.util.Map;
25
26 import org.apache.logging.log4j.core.Layout;
27 import org.apache.logging.log4j.core.LogEvent;
28 import org.apache.logging.log4j.core.config.Configuration;
29 import org.apache.logging.log4j.core.config.DefaultConfiguration;
30 import org.apache.logging.log4j.core.config.Node;
31 import org.apache.logging.log4j.core.config.plugins.Plugin;
32 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
33 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 @Plugin(name = "JsonLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
61 public final class JsonLayout extends AbstractJacksonLayout {
62
63 private static final String DEFAULT_FOOTER = "]";
64
65 private static final String DEFAULT_HEADER = "[";
66
67 static final String CONTENT_TYPE = "application/json";
68
69 public static class Builder<B extends Builder<B>> extends AbstractJacksonLayout.Builder<B>
70 implements org.apache.logging.log4j.core.util.Builder<JsonLayout> {
71
72 @PluginBuilderAttribute
73 private boolean propertiesAsList;
74
75 public Builder() {
76 super();
77 setCharset(StandardCharsets.UTF_8);
78 }
79
80 @Override
81 public JsonLayout build() {
82 final boolean encodeThreadContextAsList = isProperties() && propertiesAsList;
83 final String headerPattern = toStringOrNull(getHeader());
84 final String footerPattern = toStringOrNull(getFooter());
85 return new JsonLayout(getConfiguration(), isLocationInfo(), isProperties(), encodeThreadContextAsList,
86 isComplete(), isCompact(), getEventEol(), headerPattern, footerPattern, getCharset(),
87 isIncludeStacktrace(), isStacktraceAsString(), isIncludeNullDelimiter());
88 }
89
90 public boolean isPropertiesAsList() {
91 return propertiesAsList;
92 }
93
94 public B setPropertiesAsList(final boolean propertiesAsList) {
95 this.propertiesAsList = propertiesAsList;
96 return asBuilder();
97 }
98 }
99
100
101
102
103 @Deprecated
104 protected JsonLayout(final Configuration config, final boolean locationInfo, final boolean properties,
105 final boolean encodeThreadContextAsList,
106 final boolean complete, final boolean compact, final boolean eventEol, final String headerPattern,
107 final String footerPattern, final Charset charset, final boolean includeStacktrace) {
108 super(config, new JacksonFactory.JSON(encodeThreadContextAsList, includeStacktrace, false).newWriter(
109 locationInfo, properties, compact),
110 charset, compact, complete, eventEol,
111 PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(),
112 PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build(),
113 false);
114 }
115
116 private JsonLayout(final Configuration config, final boolean locationInfo, final boolean properties,
117 final boolean encodeThreadContextAsList,
118 final boolean complete, final boolean compact, final boolean eventEol,
119 final String headerPattern,final String footerPattern, final Charset charset,
120 final boolean includeStacktrace,final boolean stacktraceAsString,
121 final boolean includeNullDelimiter) {
122 super(config, new JacksonFactory.JSON(encodeThreadContextAsList, includeStacktrace, stacktraceAsString).newWriter(
123 locationInfo, properties, compact),
124 charset, compact, complete, eventEol,
125 PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(),
126 PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build(),
127 includeNullDelimiter);
128 }
129
130
131
132
133
134
135 @Override
136 public byte[] getHeader() {
137 if (!this.complete) {
138 return null;
139 }
140 final StringBuilder buf = new StringBuilder();
141 final String str = serializeToString(getHeaderSerializer());
142 if (str != null) {
143 buf.append(str);
144 }
145 buf.append(this.eol);
146 return getBytes(buf.toString());
147 }
148
149
150
151
152
153
154 @Override
155 public byte[] getFooter() {
156 if (!this.complete) {
157 return null;
158 }
159 final StringBuilder buf = new StringBuilder();
160 buf.append(this.eol);
161 final String str = serializeToString(getFooterSerializer());
162 if (str != null) {
163 buf.append(str);
164 }
165 buf.append(this.eol);
166 return getBytes(buf.toString());
167 }
168
169 @Override
170 public Map<String, String> getContentFormat() {
171 final Map<String, String> result = new HashMap<>();
172 result.put("version", "2.0");
173 return result;
174 }
175
176
177
178
179 @Override
180 public String getContentType() {
181 return CONTENT_TYPE + "; charset=" + this.getCharset();
182 }
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216 @Deprecated
217 public static JsonLayout createLayout(
218 final Configuration config,
219 final boolean locationInfo,
220 final boolean properties,
221 final boolean propertiesAsList,
222 final boolean complete,
223 final boolean compact,
224 final boolean eventEol,
225 final String headerPattern,
226 final String footerPattern,
227 final Charset charset,
228 final boolean includeStacktrace) {
229 final boolean encodeThreadContextAsList = properties && propertiesAsList;
230 return new JsonLayout(config, locationInfo, properties, encodeThreadContextAsList, complete, compact, eventEol,
231 headerPattern, footerPattern, charset, includeStacktrace, false, false);
232 }
233
234 @PluginBuilderFactory
235 public static <B extends Builder<B>> B newBuilder() {
236 return new Builder<B>().asBuilder();
237 }
238
239
240
241
242
243
244 public static JsonLayout createDefaultLayout() {
245 return new JsonLayout(new DefaultConfiguration(), false, false, false, false, false, false,
246 DEFAULT_HEADER, DEFAULT_FOOTER, StandardCharsets.UTF_8, true, false, false);
247 }
248
249 @Override
250 public void toSerializable(final LogEvent event, final Writer writer) throws IOException {
251 if (complete && eventCount > 0) {
252 writer.append(", ");
253 }
254 super.toSerializable(event, writer);
255 }
256 }