Skip to content

Commit 22da156

Browse files
committed
ongoing work on JsonEscapeUtil
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
1 parent b8e0936 commit 22da156

File tree

8 files changed

+327
-146
lines changed

8 files changed

+327
-146
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,140 +1,2 @@
1-
package ch.qos.logback.classic.encoder;
2-
3-
import ch.qos.logback.classic.spi.ILoggingEvent;
4-
import ch.qos.logback.core.encoder.JsonEncoderBase;
5-
import ch.qos.logback.core.util.DirectJson;
6-
7-
import java.util.ArrayList;
8-
import java.util.List;
9-
10-
/**
11-
* This is a concrete JsonEncoder for {@link ILoggingEvent} that emits fields according to object's configuration.
12-
* It is partially imported from <a href="https://github.com/hkupty/penna">penna</a>, but adapted to logback's structure.
13-
*
14-
* @author Henry John Kupty
15-
*/
16-
public class JsonEncoder extends JsonEncoderBase<ILoggingEvent> {
17-
18-
19-
// Excerpt below imported from
20-
// ch.qos.logback.contrib.json.classic.JsonLayout
21-
public static final String TIMESTAMP_ATTR_NAME = "timestamp";
22-
public static final String LEVEL_ATTR_NAME = "level";
23-
public static final String MARKERS_ATTR_NAME = "tags";
24-
public static final String THREAD_ATTR_NAME = "thread";
25-
public static final String MDC_ATTR_NAME = "mdc";
26-
public static final String LOGGER_ATTR_NAME = "logger";
27-
public static final String FORMATTED_MESSAGE_ATTR_NAME = "message";
28-
public static final String MESSAGE_ATTR_NAME = "raw-message";
29-
public static final String EXCEPTION_ATTR_NAME = "exception";
30-
public static final String CONTEXT_ATTR_NAME = "context";
31-
32-
protected boolean includeLevel;
33-
protected boolean includeThreadName;
34-
protected boolean includeMDC;
35-
protected boolean includeLoggerName;
36-
protected boolean includeFormattedMessage;
37-
protected boolean includeMessage;
38-
protected boolean includeException;
39-
protected boolean includeContextName;
40-
41-
private final List<Emitter<ILoggingEvent>> emitters;
42-
43-
44-
public JsonEncoder() {
45-
super();
46-
47-
emitters = new ArrayList<>();
48-
this.includeLevel = true;
49-
this.includeThreadName = true;
50-
this.includeMDC = true;
51-
this.includeLoggerName = true;
52-
this.includeFormattedMessage = true;
53-
this.includeException = true;
54-
this.includeContextName = true;
55-
}
56-
57-
//protected = new DirectJson();
58-
59-
60-
public void writeMessage(DirectJson jsonWriter, ILoggingEvent event) {
61-
jsonWriter.writeStringValue(MESSAGE_ATTR_NAME, event.getMessage());
62-
}
63-
64-
public void writeFormattedMessage(DirectJson jsonWriter, ILoggingEvent event) {
65-
jsonWriter.writeStringValue(FORMATTED_MESSAGE_ATTR_NAME, event.getFormattedMessage());
66-
}
67-
68-
public void writeLogger(DirectJson jsonWriter, ILoggingEvent event) {
69-
jsonWriter.writeStringValue(LOGGER_ATTR_NAME, event.getLoggerName());
70-
}
71-
72-
public void writeThreadName(DirectJson jsonWriter, ILoggingEvent event) {
73-
jsonWriter.writeStringValue(THREAD_ATTR_NAME, event.getThreadName());
74-
}
75-
76-
public void writeLevel(DirectJson jsonWriter, ILoggingEvent event) {
77-
jsonWriter.writeStringValue(LEVEL_ATTR_NAME, event.getLevel().levelStr);
78-
}
79-
80-
81-
public void writeMarkers(DirectJson jsonWriter, ILoggingEvent event) {
82-
var markers = event.getMarkerList();
83-
if (!markers.isEmpty()) {
84-
jsonWriter.openArray(MARKERS_ATTR_NAME);
85-
for (var marker : markers) {
86-
jsonWriter.writeString(marker.getName());
87-
jsonWriter.writeSep();
88-
}
89-
// Close array will overwrite the last "," in the buffer, so we are OK
90-
jsonWriter.closeArray();
91-
jsonWriter.writeSep();
92-
}
93-
}
94-
95-
public void writeMdc(DirectJson jsonWriter, ILoggingEvent event) {
96-
var mdc = event.getMDCPropertyMap();
97-
if (!mdc.isEmpty()) {
98-
jsonWriter.openObject(MDC_ATTR_NAME);
99-
for (var entry : mdc.entrySet()) {
100-
jsonWriter.writeStringValue(entry.getKey(), entry.getValue());
101-
}
102-
jsonWriter.closeObject();
103-
jsonWriter.writeSep();
104-
}
105-
}
106-
107-
private void buildEmitterList() {
108-
// This method should be re-entrant and allow for reconfiguring the emitters if something change;
109-
emitters.clear();
110-
111-
// TODO figure out order
112-
if (includeLevel) emitters.add(this::writeLevel);
113-
if (includeMDC) emitters.add(this::writeMdc);
114-
if (includeMessage) emitters.add(this::writeMessage);
115-
if (includeFormattedMessage) emitters.add(this::writeFormattedMessage);
116-
if (includeThreadName) emitters.add(this::writeThreadName);
117-
if (includeLoggerName) emitters.add(this::writeLogger);
118-
// TODO add fields missing:
119-
// context
120-
// exception
121-
// custom data
122-
// marker
123-
}
124-
125-
@Override
126-
public byte[] encode(ILoggingEvent event) {
127-
if (emitters.isEmpty()) {
128-
buildEmitterList();
129-
}
130-
DirectJson jsonWriter = new DirectJson();
131-
jsonWriter.openObject();
132-
133-
for (var emitter: emitters) {
134-
emitter.write(jsonWriter, event);
135-
}
136-
137-
jsonWriter.closeObject();
138-
return jsonWriter.flush();
139-
}
1+
package ch.qos.logback.classic.encoder;public class JsonEncoder {
1402
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package ch.qos.logback.classic.encoder;
2+
3+
import ch.qos.logback.classic.spi.ILoggingEvent;
4+
import ch.qos.logback.core.encoder.JsonEncoderBase;
5+
import ch.qos.logback.core.util.DirectJson;
6+
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
10+
/**
11+
* This is a concrete JsonEncoder for {@link ILoggingEvent} that emits fields according to object's configuration.
12+
* It is partially imported from <a href="https://github.com/hkupty/penna">penna</a>, but adapted to logback's structure.
13+
*
14+
* @author Henry John Kupty
15+
*/
16+
public class JsonEncoder extends JsonEncoderBase<ILoggingEvent> {
17+
18+
19+
// Excerpt below imported from
20+
// ch.qos.logback.contrib.json.classic.JsonLayout
21+
public static final String TIMESTAMP_ATTR_NAME = "timestamp";
22+
public static final String LEVEL_ATTR_NAME = "level";
23+
public static final String MARKERS_ATTR_NAME = "tags";
24+
public static final String THREAD_ATTR_NAME = "thread";
25+
public static final String MDC_ATTR_NAME = "mdc";
26+
public static final String LOGGER_ATTR_NAME = "logger";
27+
public static final String FORMATTED_MESSAGE_ATTR_NAME = "message";
28+
public static final String MESSAGE_ATTR_NAME = "raw-message";
29+
public static final String EXCEPTION_ATTR_NAME = "exception";
30+
public static final String CONTEXT_ATTR_NAME = "context";
31+
32+
protected boolean includeLevel;
33+
protected boolean includeThreadName;
34+
protected boolean includeMDC;
35+
protected boolean includeLoggerName;
36+
protected boolean includeFormattedMessage;
37+
protected boolean includeMessage;
38+
protected boolean includeException;
39+
protected boolean includeContextName;
40+
41+
private final List<Emitter<ILoggingEvent>> emitters;
42+
43+
44+
public JsonEncoder() {
45+
super();
46+
47+
emitters = new ArrayList<>();
48+
this.includeLevel = true;
49+
this.includeThreadName = true;
50+
this.includeMDC = true;
51+
this.includeLoggerName = true;
52+
this.includeFormattedMessage = true;
53+
this.includeException = true;
54+
this.includeContextName = true;
55+
}
56+
57+
//protected = new DirectJson();
58+
59+
60+
public void writeMessage(DirectJson jsonWriter, ILoggingEvent event) {
61+
jsonWriter.writeStringValue(MESSAGE_ATTR_NAME, event.getMessage());
62+
}
63+
64+
public void writeFormattedMessage(DirectJson jsonWriter, ILoggingEvent event) {
65+
jsonWriter.writeStringValue(FORMATTED_MESSAGE_ATTR_NAME, event.getFormattedMessage());
66+
}
67+
68+
public void writeLogger(DirectJson jsonWriter, ILoggingEvent event) {
69+
jsonWriter.writeStringValue(LOGGER_ATTR_NAME, event.getLoggerName());
70+
}
71+
72+
public void writeThreadName(DirectJson jsonWriter, ILoggingEvent event) {
73+
jsonWriter.writeStringValue(THREAD_ATTR_NAME, event.getThreadName());
74+
}
75+
76+
public void writeLevel(DirectJson jsonWriter, ILoggingEvent event) {
77+
jsonWriter.writeStringValue(LEVEL_ATTR_NAME, event.getLevel().levelStr);
78+
}
79+
80+
81+
public void writeMarkers(DirectJson jsonWriter, ILoggingEvent event) {
82+
var markers = event.getMarkerList();
83+
if (!markers.isEmpty()) {
84+
jsonWriter.openArray(MARKERS_ATTR_NAME);
85+
for (var marker : markers) {
86+
jsonWriter.writeString(marker.getName());
87+
jsonWriter.writeSep();
88+
}
89+
// Close array will overwrite the last "," in the buffer, so we are OK
90+
jsonWriter.closeArray();
91+
jsonWriter.writeSep();
92+
}
93+
}
94+
95+
public void writeMdc(DirectJson jsonWriter, ILoggingEvent event) {
96+
var mdc = event.getMDCPropertyMap();
97+
if (!mdc.isEmpty()) {
98+
jsonWriter.openObject(MDC_ATTR_NAME);
99+
for (var entry : mdc.entrySet()) {
100+
jsonWriter.writeStringValue(entry.getKey(), entry.getValue());
101+
}
102+
jsonWriter.closeObject();
103+
jsonWriter.writeSep();
104+
}
105+
}
106+
107+
private void buildEmitterList() {
108+
// This method should be re-entrant and allow for reconfiguring the emitters if something change;
109+
emitters.clear();
110+
111+
// TODO figure out order
112+
if (includeLevel) emitters.add(this::writeLevel);
113+
if (includeMDC) emitters.add(this::writeMdc);
114+
if (includeMessage) emitters.add(this::writeMessage);
115+
if (includeFormattedMessage) emitters.add(this::writeFormattedMessage);
116+
if (includeThreadName) emitters.add(this::writeThreadName);
117+
if (includeLoggerName) emitters.add(this::writeLogger);
118+
// TODO add fields missing:
119+
// context
120+
// exception
121+
// custom data
122+
// marker
123+
}
124+
125+
@Override
126+
public byte[] encode(ILoggingEvent event) {
127+
if (emitters.isEmpty()) {
128+
buildEmitterList();
129+
}
130+
DirectJson jsonWriter = new DirectJson();
131+
jsonWriter.openObject();
132+
133+
for (var emitter: emitters) {
134+
emitter.write(jsonWriter, event);
135+
}
136+
137+
jsonWriter.closeObject();
138+
return jsonWriter.flush();
139+
}
140+
}

logback-classic/src/test/java/ch/qos/logback/classic/encoder/JsonEncoderTest.java renamed to logback-classic/src/test/java/ch/qos/logback/classic/encoder/JsonEncoder2Test.java

+26-6
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,8 @@
2929

3030
import static org.junit.jupiter.api.Assertions.assertEquals;
3131

32-
33-
34-
@Disabled
3532
public class JsonEncoderTest {
3633

37-
38-
3934
LoggerContext context = new LoggerContext();
4035
ByteArrayOutputStream baos = new ByteArrayOutputStream();
4136
Logger logger = context.getLogger(PatternLayoutEncoderTest.class);
@@ -54,7 +49,32 @@ public void smoke() throws IOException {
5449
ILoggingEvent event = makeLoggingEvent(msg);
5550
byte[] eventBytes = je.encode(event);
5651
baos.write(eventBytes);
57-
assertEquals(msg, baos.toString());
52+
String witnessPattern = makeWitness(event);
53+
assertEquals(witnessPattern, baos.toString());
54+
}
55+
56+
@Test
57+
public void twoEvents() throws IOException {
58+
59+
ILoggingEvent event0 = makeLoggingEvent("hello");
60+
ILoggingEvent event1 = makeLoggingEvent("world");
61+
62+
byte[] eventBytes0 = je.encode(event0);
63+
byte[] eventBytes1 = je.encode(event1);
64+
65+
baos.write(eventBytes0);
66+
baos.write(eventBytes1);
67+
68+
String witnessPattern0 = makeWitness(event0);
69+
String witnessPattern1 = makeWitness(event1);
70+
71+
assertEquals(witnessPattern0+witnessPattern1, baos.toString());
72+
}
73+
74+
75+
private static String makeWitness(ILoggingEvent event) {
76+
return "{\"level\":\"" + event.getLevel() + "\",\"message\":\"" + event.getMessage() + "\",\"thread\":\""
77+
+ event.getThreadName() + "\",\"logger\":\"" + event.getLoggerName() + "\"}";
5878
}
5979

6080
ILoggingEvent makeLoggingEvent(String message) {

logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java

+6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
*/
1414
package ch.qos.logback.core;
1515

16+
import java.nio.charset.Charset;
17+
import java.nio.charset.StandardCharsets;
18+
1619
public class CoreConstants {
1720

1821
final public static String DISABLE_SERVLET_CONTAINER_INITIALIZER_KEY = "logbackDisableServletContainerInitializer";
@@ -107,6 +110,8 @@ public class CoreConstants {
107110
*/
108111
public static final String[] EMPTY_STRING_ARRAY = new String[] {};
109112

113+
public static final Charset UTF_8_CHARSET = StandardCharsets.UTF_8;
114+
110115
/**
111116
* An empty Class array.
112117
*/
@@ -129,6 +134,7 @@ public class CoreConstants {
129134
public static final char DASH_CHAR = '-';
130135
public static final String DEFAULT_VALUE_SEPARATOR = ":-";
131136

137+
public static final String NULL_STR = "null";
132138
/**
133139
* Number of rows before in an HTML table before, we close the table and create
134140
* a new one

0 commit comments

Comments
 (0)