Skip to content

Commit c7c25e3

Browse files
committed
Refactor throwable serialization into implementation of interface
1 parent d729141 commit c7c25e3

File tree

4 files changed

+284
-128
lines changed

4 files changed

+284
-128
lines changed
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/*-
2+
* #%L
3+
* Java ECS logging
4+
* %%
5+
* Copyright (C) 2019 - 2020 Elastic and contributors
6+
* %%
7+
* Licensed to Elasticsearch B.V. under one or more contributor
8+
* license agreements. See the NOTICE file distributed with
9+
* this work for additional information regarding copyright
10+
* ownership. Elasticsearch B.V. licenses this file to you under
11+
* the Apache License, Version 2.0 (the "License"); you may
12+
* not use this file except in compliance with the License.
13+
* You may obtain a copy of the License at
14+
*
15+
* http://www.apache.org/licenses/LICENSE-2.0
16+
*
17+
* Unless required by applicable law or agreed to in writing,
18+
* software distributed under the License is distributed on an
19+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20+
* KIND, either express or implied. See the License for the
21+
* specific language governing permissions and limitations
22+
* under the License.
23+
* #L%
24+
*/
25+
package co.elastic.logging;
26+
27+
import java.io.PrintWriter;
28+
import java.util.regex.Pattern;
29+
30+
import static co.elastic.logging.EcsJsonSerializer.getMessageStringBuilder;
31+
32+
public class DefaultThrowableSerializer implements ThrowableSerializer {
33+
static final String NEW_LINE = System.getProperty("line.separator");
34+
static final Pattern NEW_LINE_PATTERN = Pattern.compile("\\n");
35+
36+
private static final ThrowableSerializer instance = new DefaultThrowableSerializer();
37+
38+
public static ThrowableSerializer getInstance() {
39+
return instance;
40+
}
41+
42+
@Override
43+
public void serialize(StringBuilder builder, Throwable thrown, boolean stackTraceAsArray) {
44+
serializeErrorType(builder, thrown);
45+
serializeErrorMessage(builder, thrown);
46+
serializeStackTrace(builder, thrown, stackTraceAsArray);
47+
}
48+
49+
@Override
50+
public void serialize(StringBuilder builder, String exceptionClassName, String exceptionMessage, String stackTrace, boolean stackTraceAsArray) {
51+
serializeErrorType(builder, exceptionClassName);
52+
serializeErrorMessage(builder, exceptionMessage);
53+
serializeStackTrace(builder, stackTrace, stackTraceAsArray);
54+
}
55+
56+
protected void serializeErrorType(StringBuilder builder, Throwable thrown) {
57+
serializeErrorType(builder, formatErrorType(thrown));
58+
}
59+
60+
protected String formatErrorType(Throwable thrown) {
61+
return thrown.getClass().getName();
62+
}
63+
64+
protected void serializeErrorType(StringBuilder builder, String errorType) {
65+
builder.append("\"error.type\":\"");
66+
JsonUtils.quoteAsString(errorType, builder);
67+
builder.append("\",");
68+
}
69+
70+
protected void serializeErrorMessage(StringBuilder builder, Throwable thrown) {
71+
serializeErrorMessage(builder, formatErrorMessage(thrown));
72+
}
73+
74+
protected String formatErrorMessage(Throwable thrown) {
75+
return thrown.getMessage();
76+
}
77+
78+
protected void serializeErrorMessage(StringBuilder builder, String message) {
79+
if (message != null) {
80+
builder.append("\"error.message\":\"");
81+
JsonUtils.quoteAsString(message, builder);
82+
builder.append("\",");
83+
}
84+
}
85+
86+
protected void serializeStackTrace(StringBuilder builder, Throwable thrown, boolean stackTraceAsArray) {
87+
builder.append("\"error.stack_trace\":");
88+
if (stackTraceAsArray) {
89+
serializeStackTraceAsArray(builder, thrown);
90+
} else {
91+
serializeStackTraceAsString(builder, thrown);
92+
}
93+
}
94+
95+
protected void serializeStackTraceAsArray(final StringBuilder builder, Throwable thrown) {
96+
builder.append('[');
97+
final StringBuilder buffer = getMessageStringBuilder();
98+
final PrintWriter pw = new PrintWriter(new StringBuilderWriter(buffer), true) {
99+
boolean firstElement = true;
100+
@Override
101+
public void println() {
102+
flush();
103+
if (firstElement) {
104+
firstElement = false;
105+
} else {
106+
builder.append(',');
107+
}
108+
builder.append('\"');
109+
JsonUtils.quoteAsString(buffer, builder);
110+
builder.append('\"');
111+
buffer.setLength(0);
112+
}
113+
};
114+
thrown.printStackTrace(pw);
115+
builder.append(']');
116+
}
117+
118+
protected void serializeStackTraceAsString(StringBuilder builder, Throwable thrown) {
119+
builder.append('\"');
120+
JsonUtils.quoteAsString(formatStackTrace(thrown), builder);
121+
builder.append('\"');
122+
}
123+
124+
protected CharSequence formatStackTrace(Throwable thrown) {
125+
StringBuilder buffer = getMessageStringBuilder();
126+
final PrintWriter pw = new PrintWriter(new StringBuilderWriter(buffer));
127+
thrown.printStackTrace(pw);
128+
pw.flush();
129+
return buffer;
130+
}
131+
132+
protected void serializeStackTrace(StringBuilder builder, String stackTrace, boolean stackTraceAsArray) {
133+
builder.append("\"error.stack_trace\":");
134+
if (stackTraceAsArray) {
135+
serializeStackTraceAsArray(builder, stackTrace);
136+
} else {
137+
serializeStackTraceAsString(builder, stackTrace);
138+
}
139+
}
140+
141+
protected void serializeStackTraceAsString(StringBuilder builder, String stackTrace) {
142+
builder.append('\"');
143+
JsonUtils.quoteAsString(stackTrace, builder);
144+
builder.append('\"');
145+
}
146+
147+
protected void serializeStackTraceAsArray(StringBuilder builder, String stackTrace) {
148+
builder.append('[');
149+
boolean firstElement = true;
150+
for (String line : NEW_LINE_PATTERN.split(stackTrace)) {
151+
if (firstElement) {
152+
firstElement = false;
153+
} else {
154+
builder.append(',');
155+
}
156+
builder.append('\"');
157+
JsonUtils.quoteAsString(line, builder);
158+
builder.append('\"');
159+
}
160+
builder.append(']');
161+
}
162+
}

ecs-logging-core/src/main/java/co/elastic/logging/EcsJsonSerializer.java

Lines changed: 8 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,12 @@
2424
*/
2525
package co.elastic.logging;
2626

27-
import java.io.PrintWriter;
28-
import java.io.Writer;
2927
import java.util.Map;
30-
import java.util.regex.Pattern;
3128

3229
public class EcsJsonSerializer {
3330

3431
private static final TimestampSerializer TIMESTAMP_SERIALIZER = new TimestampSerializer();
3532
private static final ThreadLocal<StringBuilder> messageStringBuilder = new ThreadLocal<StringBuilder>();
36-
private static final String NEW_LINE = System.getProperty("line.separator");
37-
private static final Pattern NEW_LINE_PATTERN = Pattern.compile("\\n");
3833

3934
public static CharSequence toNullSafeString(final CharSequence s) {
4035
return s == null ? "" : s;
@@ -166,79 +161,21 @@ public static void serializeMDC(StringBuilder builder, Map<String, ?> properties
166161
}
167162

168163
public static void serializeException(StringBuilder builder, Throwable thrown, boolean stackTraceAsArray) {
169-
if (thrown != null) {
170-
builder.append("\"error.type\":\"");
171-
JsonUtils.quoteAsString(thrown.getClass().getName(), builder);
172-
builder.append("\",");
173-
174-
String message = thrown.getMessage();
175-
if (message != null) {
176-
builder.append("\"error.message\":\"");
177-
JsonUtils.quoteAsString(message, builder);
178-
builder.append("\",");
179-
}
180-
if (stackTraceAsArray) {
181-
builder.append("\"error.stack_trace\":[").append(NEW_LINE);
182-
formatThrowableAsArray(builder, thrown);
183-
builder.append("]");
184-
} else {
185-
builder.append("\"error.stack_trace\":\"");
186-
JsonUtils.quoteAsString(formatThrowable(thrown), builder);
187-
builder.append("\"");
188-
}
189-
}
164+
serializeException(builder, thrown, stackTraceAsArray, DefaultThrowableSerializer.getInstance());
190165
}
191166

192-
public static void serializeException(StringBuilder builder, String exceptionClassName, String exceptionMessage, String stackTrace, boolean stackTraceAsArray) {
193-
builder.append("\"error.type\":\"");
194-
JsonUtils.quoteAsString(exceptionClassName, builder);
195-
builder.append("\",");
196-
builder.append("\"error.message\":\"");
197-
JsonUtils.quoteAsString(exceptionMessage, builder);
198-
builder.append("\",");
199-
if (stackTraceAsArray) {
200-
builder.append("\"error.stack_trace\":[").append(NEW_LINE);
201-
for (String line : NEW_LINE_PATTERN.split(stackTrace)) {
202-
appendQuoted(builder, line);
203-
}
204-
builder.append("]");
205-
} else {
206-
builder.append("\"error.stack_trace\":\"");
207-
JsonUtils.quoteAsString(stackTrace, builder);
208-
builder.append("\"");
167+
public static void serializeException(StringBuilder builder, Throwable thrown, boolean stackTraceAsArray, ThrowableSerializer throwableSerializer) {
168+
if (thrown != null) {
169+
throwableSerializer.serialize(builder, thrown, stackTraceAsArray);
209170
}
210171
}
211172

212-
private static void appendQuoted(StringBuilder builder, CharSequence content) {
213-
builder.append('"');
214-
JsonUtils.quoteAsString(content, builder);
215-
builder.append('"');
216-
}
217-
218-
private static CharSequence formatThrowable(final Throwable throwable) {
219-
StringBuilder buffer = getMessageStringBuilder();
220-
final PrintWriter pw = new PrintWriter(new StringBuilderWriter(buffer));
221-
throwable.printStackTrace(pw);
222-
pw.flush();
223-
return buffer;
173+
public static void serializeException(StringBuilder builder, String exceptionClassName, String exceptionMessage, String stackTrace, boolean stackTraceAsArray) {
174+
serializeException(builder, exceptionClassName, exceptionMessage, stackTrace, stackTraceAsArray, DefaultThrowableSerializer.getInstance());
224175
}
225176

226-
private static void formatThrowableAsArray(final StringBuilder jsonBuilder, final Throwable throwable) {
227-
final StringBuilder buffer = getMessageStringBuilder();
228-
final PrintWriter pw = new PrintWriter(new StringBuilderWriter(buffer), true) {
229-
@Override
230-
public void println() {
231-
flush();
232-
jsonBuilder.append("\t\"");
233-
JsonUtils.quoteAsString(buffer, jsonBuilder);
234-
jsonBuilder.append("\",");
235-
jsonBuilder.append(NEW_LINE);
236-
buffer.setLength(0);
237-
}
238-
};
239-
throwable.printStackTrace(pw);
240-
removeIfEndsWith(jsonBuilder, NEW_LINE);
241-
removeIfEndsWith(jsonBuilder, ",");
177+
public static void serializeException(StringBuilder builder, String exceptionClassName, String exceptionMessage, String stackTrace, boolean stackTraceAsArray, ThrowableSerializer throwableSerializer) {
178+
throwableSerializer.serialize(builder, exceptionClassName, exceptionMessage, stackTrace, stackTraceAsArray);
242179
}
243180

244181
public static void removeIfEndsWith(StringBuilder sb, String ending) {
@@ -277,61 +214,4 @@ public static String computeEventDataset(String eventDataset, String serviceName
277214
}
278215
return eventDataset;
279216
}
280-
281-
private static class StringBuilderWriter extends Writer {
282-
283-
private final StringBuilder buffer;
284-
285-
StringBuilderWriter(StringBuilder buffer) {
286-
this.buffer = buffer;
287-
}
288-
289-
@Override
290-
public Writer append(CharSequence csq) {
291-
buffer.append(csq);
292-
return this;
293-
}
294-
295-
@Override
296-
public void write(String str) {
297-
buffer.append(str);
298-
}
299-
300-
@Override
301-
public void write(String str, int off, int len) {
302-
buffer.append(str, off, len);
303-
}
304-
305-
@Override
306-
public Writer append(CharSequence csq, int start, int end) {
307-
buffer.append(csq, start, end);
308-
return this;
309-
}
310-
311-
@Override
312-
public Writer append(char c) {
313-
buffer.append(c);
314-
return this;
315-
}
316-
317-
@Override
318-
public void write(int c) {
319-
buffer.append((char) c);
320-
}
321-
322-
@Override
323-
public void write(char[] cbuf, int off, int len) {
324-
buffer.append(cbuf, off, len);
325-
}
326-
327-
@Override
328-
public void flush() {
329-
330-
}
331-
332-
@Override
333-
public void close() {
334-
335-
}
336-
}
337217
}

0 commit comments

Comments
 (0)