17
17
import ch .qos .logback .classic .Level ;
18
18
import ch .qos .logback .classic .spi .ILoggingEvent ;
19
19
import ch .qos .logback .core .encoder .EncoderBase ;
20
- import ch .qos .logback .core .util .DirectJson ;
20
+ import org .slf4j .Marker ;
21
+ import org .slf4j .event .KeyValuePair ;
21
22
22
- import java .nio .charset .Charset ;
23
+ import java .util .List ;
24
+ import java .util .Map ;
23
25
24
26
import static ch .qos .logback .core .CoreConstants .COLON_CHAR ;
25
27
import static ch .qos .logback .core .CoreConstants .COMMA_CHAR ;
26
28
import static ch .qos .logback .core .CoreConstants .DOUBLE_QUOTE_CHAR ;
27
29
import static ch .qos .logback .core .CoreConstants .UTF_8_CHARSET ;
30
+ import static ch .qos .logback .core .encoder .JsonEscapeUtil .jsonEscapeString ;
28
31
import static ch .qos .logback .core .model .ModelConstants .NULL_STR ;
29
32
30
33
/**
@@ -43,22 +46,35 @@ public class JsonEncoder extends EncoderBase<ILoggingEvent> {
43
46
44
47
public static final String CONTEXT_ATTR_NAME = "context" ;
45
48
public static final String TIMESTAMP_ATTR_NAME = "timestamp" ;
49
+
50
+ public static final String NANOSECONDS_ATTR_NAME = "nanoseconds" ;
51
+
52
+ public static final String SEQUENCE_NUMBER_ATTR_NAME = "sequenceNumbers" ;
53
+
54
+
46
55
public static final String LEVEL_ATTR_NAME = "level" ;
47
56
public static final String MARKERS_ATTR_NAME = "markers" ;
48
57
public static final String THREAD_ATTR_NAME = "thread" ;
49
58
public static final String MDC_ATTR_NAME = "mdc" ;
50
59
public static final String LOGGER_ATTR_NAME = "logger" ;
51
- public static final String MESSAGE_ATTR_NAME = "raw-message" ;
60
+ public static final String MESSAGE_ATTR_NAME = "rawMessage" ;
61
+
62
+ public static final String ARGUMENT_ARRAY_ATTR_NAME = "arguments" ;
63
+ public static final String KEY_VALUE_PAIRS_ATTR_NAME = "keyValuePairs" ;
64
+
52
65
public static final String THROWABLE_ATTR_NAME = "throwable" ;
53
66
54
67
private static final char OPEN_OBJ = '{' ;
55
68
private static final char CLOSE_OBJ = '}' ;
56
- private static final char OPEN_ARR = '[' ;
57
- private static final char CLOSE_ARR = ']' ;
69
+ private static final char OPEN_ARRAY = '[' ;
70
+ private static final char CLOSE_ARRAY = ']' ;
58
71
59
72
private static final char QUOTE = DOUBLE_QUOTE_CHAR ;
60
73
private static final char SP = ' ' ;
61
74
private static final char ENTRY_SEPARATOR = COLON_CHAR ;
75
+
76
+ private static final char COL_SP = COLON_CHAR +SP ;
77
+
62
78
private static final char VALUE_SEPARATOR = COMMA_CHAR ;
63
79
64
80
@@ -72,26 +88,130 @@ public byte[] headerBytes() {
72
88
public byte [] encode (ILoggingEvent event ) {
73
89
final int initialCapacity = event .getThrowableProxy () == null ? DEFAULT_SIZE : DEFAULT_SIZE_WITH_THROWABLE ;
74
90
StringBuilder sb = new StringBuilder (initialCapacity );
91
+ sb .append (OPEN_OBJ );
92
+
93
+
94
+ sb .append (SEQUENCE_NUMBER_ATTR_NAME ).append (COL_SP ).append (event .getSequenceNumber ());
95
+ sb .append (VALUE_SEPARATOR );
96
+
97
+
98
+ sb .append (TIMESTAMP_ATTR_NAME ).append (COL_SP ).append (event .getTimeStamp ());
99
+ sb .append (VALUE_SEPARATOR );
100
+
101
+ sb .append (NANOSECONDS_ATTR_NAME ).append (COL_SP ).append (event .getNanoseconds ());
102
+ sb .append (VALUE_SEPARATOR );
103
+
104
+
105
+ String levelStr = event .getLevel () != null ? event .getLevel ().levelStr : NULL_STR ;
106
+ sb .append (LEVEL_ATTR_NAME ).append (COL_SP ).append (QUOTE ).append (levelStr ).append (QUOTE );
107
+ sb .append (VALUE_SEPARATOR );
108
+
109
+ sb .append (THREAD_ATTR_NAME ).append (COL_SP ).append (QUOTE ).append (jsonSafeStr (event .getThreadName ())).append (QUOTE );
110
+ sb .append (VALUE_SEPARATOR );
75
111
112
+ sb .append (LOGGER_ATTR_NAME ).append (COL_SP ).append (QUOTE ).append (event .getLoggerName ()).append (QUOTE );
113
+ sb .append (VALUE_SEPARATOR );
76
114
115
+ appendMarkers (sb , event );
116
+ appendMDC (sb , event );
117
+ appendKeyValuePairs (sb , event );
77
118
119
+ sb .append (MESSAGE_ATTR_NAME ).append (COL_SP ).append (QUOTE ).append (jsonSafeStr (event .getMessage ())).append (QUOTE );
120
+ sb .append (VALUE_SEPARATOR );
121
+
122
+ appendArgumentArray (sb , event );
123
+
124
+ sb .append (CLOSE_OBJ );
78
125
return sb .toString ().getBytes (UTF_8_CHARSET );
79
126
}
80
127
128
+ private void appendKeyValuePairs (StringBuilder sb , ILoggingEvent event ) {
129
+ List <KeyValuePair > kvpList = event .getKeyValuePairs ();
130
+ if (kvpList == null || kvpList .isEmpty ())
131
+ return ;
132
+
133
+ sb .append (KEY_VALUE_PAIRS_ATTR_NAME ).append (ENTRY_SEPARATOR ).append (SP ).append (OPEN_ARRAY );
134
+ final int len = kvpList .size ();
135
+ for (int i = 0 ; i < len ; i ++) {
136
+ KeyValuePair kvp = kvpList .get (i );
137
+ sb .append (QUOTE ).append (jsonSafeToString (kvp .key )).append (QUOTE );
138
+ sb .append (COL_SP );
139
+ sb .append (QUOTE ).append (jsonSafeToString (kvp .value )).append (QUOTE );
140
+
141
+ if (i != len )
142
+ sb .append (VALUE_SEPARATOR );
143
+ }
144
+ sb .append (CLOSE_ARRAY );
145
+ }
146
+
147
+ private void appendArgumentArray (StringBuilder sb , ILoggingEvent event ) {
148
+ Object [] argumentArray = event .getArgumentArray ();
149
+ if (argumentArray == null )
150
+ return ;
151
+
152
+ sb .append (ARGUMENT_ARRAY_ATTR_NAME ).append (ENTRY_SEPARATOR ).append (SP ).append (OPEN_ARRAY );
153
+ final int len = argumentArray .length ;
154
+ for (int i = 0 ; i < len ; i ++) {
155
+ sb .append (QUOTE ).append (jsonSafeToString (argumentArray [i ])).append (QUOTE );
156
+ if (i != len )
157
+ sb .append (VALUE_SEPARATOR );
158
+ }
159
+ sb .append (CLOSE_ARRAY );
160
+ }
161
+
162
+ private void appendMarkers (StringBuilder sb , ILoggingEvent event ) {
163
+ List <Marker > markerList = event .getMarkerList ();
164
+ if (markerList == null )
165
+ return ;
166
+
167
+ sb .append (MARKERS_ATTR_NAME ).append (ENTRY_SEPARATOR ).append (SP ).append (OPEN_ARRAY );
168
+ final int len = markerList .size ();
169
+ for (int i = 0 ; i < len ; i ++) {
170
+ sb .append (QUOTE ).append (jsonSafeToString (markerList .get (i ))).append (QUOTE );
171
+ if (i != len )
172
+ sb .append (VALUE_SEPARATOR );
173
+ }
174
+ sb .append (CLOSE_ARRAY );
175
+ }
176
+
177
+ private String jsonSafeToString (Object o ) {
178
+ if (o == null )
179
+ return NULL_STR ;
180
+ return jsonEscapeString (o .toString ());
181
+ }
182
+
183
+ private String jsonSafeStr (String s ) {
184
+ if (s == null )
185
+ return NULL_STR ;
186
+ return jsonEscapeString (s );
187
+ }
188
+
189
+
190
+ private void appendMDC (StringBuilder sb , ILoggingEvent event ) {
191
+ Map <String , String > map = event .getMDCPropertyMap ();
192
+
193
+ sb .append (MDC_ATTR_NAME ).append (ENTRY_SEPARATOR ).append (SP ).append (OPEN_OBJ );
194
+ if (isNotEmptyMap (map )) {
195
+ map .entrySet ().stream ().forEach (e -> appendMapEntry (sb , e ));
196
+ }
197
+ sb .append (CLOSE_OBJ );
81
198
82
- public void writeLevel (StringBuilder sb , Level level ) {
83
- String levelString = level != null ? level .toString () : NULL_STR ;
84
- writeStringValue (sb , LEVEL_ATTR_NAME , levelString );
85
199
}
86
200
87
- void writeStringValue (StringBuilder sb , String attrName , String value ) {
88
- sb .append (attrName ).append (ENTRY_SEPARATOR ).append (SP ).append (QUOTE ).append (value );
89
- Character c = ' ' ;
201
+ private void appendMapEntry (StringBuilder sb , Map .Entry <String , String > entry ) {
202
+ if (entry == null )
203
+ return ;
204
+
205
+ sb .append (QUOTE ).append (jsonSafeToString (entry .getKey ())).append (QUOTE ).append (COL_SP ).append (QUOTE )
206
+ .append (jsonSafeToString (entry .getValue ())).append (QUOTE );
90
207
}
91
208
92
- public void writeSep (StringBuilder sb ) {
93
- sb .append (',' );
209
+ boolean isNotEmptyMap (Map map ) {
210
+ if (map == null )
211
+ return false ;
212
+ return !map .isEmpty ();
94
213
}
214
+
95
215
@ Override
96
216
public byte [] footerBytes () {
97
217
return EMPTY_BYTES ;
0 commit comments