0
# Encoders and Layouts
1
2
Message formatting and encoding for different output formats and protocols. Encoders are responsible for converting log events into byte arrays, while layouts format events into strings.
3
4
## Capabilities
5
6
### Core Encoder Interface
7
8
Base interfaces and classes for event encoding.
9
10
```java { .api }
11
/**
12
* Interface for encoding log events to byte arrays
13
*/
14
public interface Encoder<E> extends ContextAware, LifeCycle {
15
/**
16
* Encode a single event
17
*/
18
byte[] encode(E event);
19
20
/**
21
* Get header bytes (written once at start)
22
*/
23
byte[] headerBytes();
24
25
/**
26
* Get footer bytes (written once at end)
27
*/
28
byte[] footerBytes();
29
}
30
31
/**
32
* Base implementation for encoders
33
*/
34
public abstract class EncoderBase<E> extends ContextAwareBase implements Encoder<E> {
35
protected boolean started;
36
37
public boolean isStarted();
38
public void start();
39
public void stop();
40
41
// Default implementations
42
public byte[] headerBytes();
43
public byte[] footerBytes();
44
}
45
46
/**
47
* Interface for layout-based encoders
48
*/
49
public interface LayoutWrappingEncoder<E> extends Encoder<E> {
50
Layout<E> getLayout();
51
void setLayout(Layout<E> layout);
52
53
String getCharset();
54
void setCharset(Charset charset);
55
56
boolean isImmediateFlush();
57
void setImmediateFlush(boolean immediateFlush);
58
}
59
```
60
61
### Pattern Layout Encoder
62
63
Most commonly used encoder that formats events using pattern strings.
64
65
```java { .api }
66
/**
67
* Encoder that uses PatternLayout for formatting
68
*/
69
public class PatternLayoutEncoder extends LayoutWrappingEncoder<ILoggingEvent> {
70
/**
71
* Set the pattern string for formatting
72
*/
73
public void setPattern(String pattern);
74
public String getPattern();
75
76
/**
77
* Set the output pattern (alias for setPattern)
78
*/
79
public void setOutputPatternAsHeader(boolean outputPatternAsHeader);
80
public boolean isOutputPatternAsHeader();
81
}
82
```
83
84
**Usage Examples:**
85
86
```java
87
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
88
89
// Create pattern encoder
90
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
91
encoder.setContext(loggerContext);
92
93
// Set formatting pattern
94
encoder.setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n");
95
96
// Optional: output pattern as header
97
encoder.setOutputPatternAsHeader(true);
98
99
// Set charset if needed
100
encoder.setCharset(StandardCharsets.UTF_8);
101
102
encoder.start();
103
```
104
105
### JSON Encoder
106
107
Structured logging encoder that outputs events in JSON format.
108
109
```java { .api }
110
/**
111
* JSON-based encoder for structured logging
112
*/
113
public class JsonEncoder extends EncoderBase<ILoggingEvent> {
114
private boolean includeContext = true;
115
private boolean includeMdc = true;
116
117
/**
118
* Include logger context information in JSON
119
*/
120
public void setIncludeContext(boolean includeContext);
121
public boolean isIncludeContext();
122
123
/**
124
* Include MDC properties in JSON
125
*/
126
public void setIncludeMdc(boolean includeMdc);
127
public boolean isIncludeMdc();
128
}
129
```
130
131
**Usage Examples:**
132
133
```java
134
import ch.qos.logback.classic.encoder.JsonEncoder;
135
136
// Create JSON encoder
137
JsonEncoder jsonEncoder = new JsonEncoder();
138
jsonEncoder.setContext(loggerContext);
139
jsonEncoder.setIncludeContext(true);
140
jsonEncoder.setIncludeMdc(true);
141
jsonEncoder.start();
142
143
// Results in JSON output like:
144
// {"timestamp":"2023-01-01T12:00:00.000Z","level":"INFO","logger":"com.example.App","message":"User logged in","mdc":{"userId":"123"}}
145
```
146
147
### Layout Interface
148
149
Core layout interface for string-based event formatting.
150
151
```java { .api }
152
/**
153
* Interface for formatting log events as strings
154
*/
155
public interface Layout<E> extends ContextAware, LifeCycle {
156
/**
157
* Format a single event as string
158
*/
159
String doLayout(E event);
160
161
/**
162
* Get file header string
163
*/
164
String getFileHeader();
165
166
/**
167
* Get presentation header string
168
*/
169
String getPresentationHeader();
170
171
/**
172
* Get presentation footer string
173
*/
174
String getPresentationFooter();
175
176
/**
177
* Get file footer string
178
*/
179
String getFileFooter();
180
181
/**
182
* Get content type for HTTP responses
183
*/
184
String getContentType();
185
}
186
187
/**
188
* Base implementation for layouts
189
*/
190
public abstract class LayoutBase<E> extends ContextAwareBase implements Layout<E> {
191
protected boolean started;
192
193
String fileHeader;
194
String presentationHeader;
195
String presentationFooter;
196
String fileFooter;
197
198
public boolean isStarted();
199
public void start();
200
public void stop();
201
202
public void setFileHeader(String header);
203
public String getFileHeader();
204
public void setPresentationHeader(String header);
205
public String getPresentationHeader();
206
public void setPresentationFooter(String footer);
207
public String getPresentationFooter();
208
public void setFileFooter(String footer);
209
public String getFileFooter();
210
public String getContentType();
211
}
212
```
213
214
### Pattern Layout
215
216
Flexible layout using pattern strings with conversion specifiers.
217
218
```java { .api }
219
/**
220
* Layout that formats events using pattern strings
221
*/
222
public class PatternLayout extends PatternLayoutBase<ILoggingEvent> {
223
public static final Map<String, String> DEFAULT_CONVERTER_MAP = new HashMap<String, String>();
224
public static final String HEADER_PREFIX = "#logback.classic pattern: ";
225
226
static {
227
// Default pattern converters
228
DEFAULT_CONVERTER_MAP.putAll(Parser.DEFAULT_COMPOSITE_CONVERTER_MAP);
229
DEFAULT_CONVERTER_MAP.put("d", DateConverter.class.getName());
230
DEFAULT_CONVERTER_MAP.put("date", DateConverter.class.getName());
231
DEFAULT_CONVERTER_MAP.put("r", RelativeTimeConverter.class.getName());
232
DEFAULT_CONVERTER_MAP.put("relative", RelativeTimeConverter.class.getName());
233
DEFAULT_CONVERTER_MAP.put("level", LevelConverter.class.getName());
234
DEFAULT_CONVERTER_MAP.put("le", LevelConverter.class.getName());
235
DEFAULT_CONVERTER_MAP.put("p", LevelConverter.class.getName());
236
DEFAULT_CONVERTER_MAP.put("t", ThreadConverter.class.getName());
237
DEFAULT_CONVERTER_MAP.put("thread", ThreadConverter.class.getName());
238
DEFAULT_CONVERTER_MAP.put("lo", LoggerConverter.class.getName());
239
DEFAULT_CONVERTER_MAP.put("logger", LoggerConverter.class.getName());
240
DEFAULT_CONVERTER_MAP.put("c", LoggerConverter.class.getName());
241
DEFAULT_CONVERTER_MAP.put("m", MessageConverter.class.getName());
242
DEFAULT_CONVERTER_MAP.put("msg", MessageConverter.class.getName());
243
DEFAULT_CONVERTER_MAP.put("message", MessageConverter.class.getName());
244
DEFAULT_CONVERTER_MAP.put("C", ClassOfCallerConverter.class.getName());
245
DEFAULT_CONVERTER_MAP.put("class", ClassOfCallerConverter.class.getName());
246
DEFAULT_CONVERTER_MAP.put("M", MethodOfCallerConverter.class.getName());
247
DEFAULT_CONVERTER_MAP.put("method", MethodOfCallerConverter.class.getName());
248
DEFAULT_CONVERTER_MAP.put("L", LineOfCallerConverter.class.getName());
249
DEFAULT_CONVERTER_MAP.put("line", LineOfCallerConverter.class.getName());
250
DEFAULT_CONVERTER_MAP.put("F", FileOfCallerConverter.class.getName());
251
DEFAULT_CONVERTER_MAP.put("file", FileOfCallerConverter.class.getName());
252
DEFAULT_CONVERTER_MAP.put("X", MDCConverter.class.getName());
253
DEFAULT_CONVERTER_MAP.put("mdc", MDCConverter.class.getName());
254
DEFAULT_CONVERTER_MAP.put("ex", ThrowableProxyConverter.class.getName());
255
DEFAULT_CONVERTER_MAP.put("exception", ThrowableProxyConverter.class.getName());
256
DEFAULT_CONVERTER_MAP.put("rEx", RootCauseFirstThrowableProxyConverter.class.getName());
257
DEFAULT_CONVERTER_MAP.put("rootException", RootCauseFirstThrowableProxyConverter.class.getName());
258
DEFAULT_CONVERTER_MAP.put("throwable", ThrowableProxyConverter.class.getName());
259
DEFAULT_CONVERTER_MAP.put("xEx", ExtendedThrowableProxyConverter.class.getName());
260
DEFAULT_CONVERTER_MAP.put("xException", ExtendedThrowableProxyConverter.class.getName());
261
DEFAULT_CONVERTER_MAP.put("xThrowable", ExtendedThrowableProxyConverter.class.getName());
262
DEFAULT_CONVERTER_MAP.put("nopex", NopThrowableInformationConverter.class.getName());
263
DEFAULT_CONVERTER_MAP.put("nopexception", NopThrowableInformationConverter.class.getName());
264
DEFAULT_CONVERTER_MAP.put("cn", ContextNameConverter.class.getName());
265
DEFAULT_CONVERTER_MAP.put("contextName", ContextNameConverter.class.getName());
266
DEFAULT_CONVERTER_MAP.put("caller", CallerDataConverter.class.getName());
267
DEFAULT_CONVERTER_MAP.put("marker", MarkerConverter.class.getName());
268
DEFAULT_CONVERTER_MAP.put("property", PropertyConverter.class.getName());
269
DEFAULT_CONVERTER_MAP.put("n", LineSeparatorConverter.class.getName());
270
DEFAULT_CONVERTER_MAP.put("black", BlackCompositeConverter.class.getName());
271
DEFAULT_CONVERTER_MAP.put("red", RedCompositeConverter.class.getName());
272
DEFAULT_CONVERTER_MAP.put("green", GreenCompositeConverter.class.getName());
273
DEFAULT_CONVERTER_MAP.put("yellow", YellowCompositeConverter.class.getName());
274
DEFAULT_CONVERTER_MAP.put("blue", BlueCompositeConverter.class.getName());
275
DEFAULT_CONVERTER_MAP.put("magenta", MagentaCompositeConverter.class.getName());
276
DEFAULT_CONVERTER_MAP.put("cyan", CyanCompositeConverter.class.getName());
277
DEFAULT_CONVERTER_MAP.put("white", WhiteCompositeConverter.class.getName());
278
DEFAULT_CONVERTER_MAP.put("gray", GrayCompositeConverter.class.getName());
279
DEFAULT_CONVERTER_MAP.put("boldRed", BoldRedCompositeConverter.class.getName());
280
DEFAULT_CONVERTER_MAP.put("boldGreen", BoldGreenCompositeConverter.class.getName());
281
DEFAULT_CONVERTER_MAP.put("boldYellow", BoldYellowCompositeConverter.class.getName());
282
DEFAULT_CONVERTER_MAP.put("boldBlue", BoldBlueCompositeConverter.class.getName());
283
DEFAULT_CONVERTER_MAP.put("boldMagenta", BoldMagentaCompositeConverter.class.getName());
284
DEFAULT_CONVERTER_MAP.put("boldCyan", BoldCyanCompositeConverter.class.getName());
285
DEFAULT_CONVERTER_MAP.put("boldWhite", BoldWhiteCompositeConverter.class.getName());
286
DEFAULT_CONVERTER_MAP.put("highlight", HighlightingCompositeConverter.class.getName());
287
}
288
}
289
290
/**
291
* Base class for pattern-based layouts
292
*/
293
public abstract class PatternLayoutBase<E> extends LayoutBase<E> {
294
Node head;
295
String pattern;
296
protected PostCompileProcessor<E> postCompileProcessor;
297
298
/**
299
* Set the conversion pattern
300
*/
301
public void setPattern(String pattern);
302
public String getPattern();
303
304
/**
305
* Get the effective converter map
306
*/
307
public Map<String, String> getEffectiveConverterMap();
308
public Map<String, String> getDefaultConverterMap();
309
}
310
```
311
312
### Specialized Layouts
313
314
Additional layout implementations for specific use cases.
315
316
```java { .api }
317
/**
318
* Simple layout showing Time, Thread, Level, Logger (TTLL)
319
*/
320
public class TTLLLayout extends LayoutBase<ILoggingEvent> {
321
DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
322
323
public String doLayout(ILoggingEvent event);
324
}
325
326
/**
327
* HTML-based layout for web display
328
*/
329
public class HTMLLayout extends LayoutBase<ILoggingEvent> {
330
protected String title = "Logback Log Messages";
331
protected CssBuilder cssBuilder;
332
333
public void setTitle(String title);
334
public String getTitle();
335
336
/**
337
* Set custom CSS builder for styling
338
*/
339
public CssBuilder getCssBuilder();
340
public void setCssBuilder(CssBuilder cssBuilder);
341
342
public String getFileHeader();
343
public String getPresentationHeader();
344
public String doLayout(ILoggingEvent event);
345
public String getPresentationFooter();
346
public String getFileFooter();
347
public String getContentType();
348
}
349
```
350
351
## Pattern Conversion Specifiers
352
353
Common pattern conversion specifiers for PatternLayout:
354
355
| Specifier | Description | Example |
356
|-----------|-------------|---------|
357
| `%d{pattern}` | Date/time | `%d{yyyy-MM-dd HH:mm:ss.SSS}` |
358
| `%thread` | Thread name | `%thread` or `%t` |
359
| `%level` | Log level | `%-5level` (left-aligned, 5 chars) |
360
| `%logger{length}` | Logger name | `%logger{36}` (abbreviated to 36 chars) |
361
| `%msg` | Log message | `%msg` or `%message` |
362
| `%n` | Line separator | `%n` |
363
| `%ex` | Exception | `%ex` (full stack trace) |
364
| `%mdc` | MDC properties | `%mdc` or `%X{key}` |
365
| `%marker` | SLF4J marker | `%marker` |
366
| `%property{key}` | Context property | `%property{user.home}` |
367
| `%caller{depth}` | Caller information | `%caller{2}` |
368
| `%class` | Caller class | `%C{1}` (simple name) |
369
| `%method` | Caller method | `%M` |
370
| `%line` | Line number | `%L` |
371
| `%file` | File name | `%F` |
372
373
## Usage Examples
374
375
### Custom Pattern Layout
376
377
```java
378
// Create custom pattern layout
379
PatternLayout layout = new PatternLayout();
380
layout.setContext(loggerContext);
381
layout.setPattern("%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n");
382
layout.start();
383
384
// Use with WriterAppender
385
WriterAppender<ILoggingEvent> appender = new WriterAppender<>();
386
appender.setLayout(layout);
387
```
388
389
### Conditional Patterns
390
391
```java
392
// Pattern with conditional MDC
393
String pattern = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}%X{userId:+ userId=%X{userId}} - %msg%n";
394
395
// Pattern with color highlighting
396
String colorPattern = "%red(%d{HH:mm:ss.SSS}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %msg%n";
397
```
398
399
### JSON Structured Logging
400
401
```java
402
// Custom JSON encoder configuration
403
JsonEncoder jsonEncoder = new JsonEncoder();
404
jsonEncoder.setContext(loggerContext);
405
jsonEncoder.setIncludeContext(true);
406
jsonEncoder.setIncludeMdc(true);
407
408
// Example JSON output:
409
// {
410
// "timestamp": "2023-12-01T10:30:00.123Z",
411
// "level": "INFO",
412
// "thread": "main",
413
// "logger": "com.example.UserService",
414
// "message": "User created successfully",
415
// "mdc": {
416
// "userId": "12345",
417
// "requestId": "req-abc-123"
418
// },
419
// "context": {
420
// "name": "default"
421
// }
422
// }
423
```