0
# Appenders
1
2
Core appender classes and interfaces for writing log events to various destinations. Appenders are the components responsible for outputting log events to different targets like console, files, networks, or custom destinations.
3
4
## Capabilities
5
6
### Appender Interface
7
8
The foundational interface that all appenders must implement, providing the core contract for log event processing.
9
10
```java { .api }
11
/**
12
* Core interface for all log event appenders.
13
* Appenders are responsible for writing log events to their destination.
14
*/
15
public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachable<E> {
16
/**
17
* Get the appender name.
18
* @return appender name
19
*/
20
String getName();
21
22
/**
23
* Process a log event. This is the main method called by the logging framework.
24
* @param event the log event to process
25
*/
26
void doAppend(E event);
27
28
/**
29
* Set the appender name.
30
* @param name the name to assign to this appender
31
*/
32
void setName(String name);
33
}
34
```
35
36
### AppenderBase
37
38
Base implementation providing synchronized event processing, filter support, and lifecycle management. Most custom appenders should extend this class.
39
40
```java { .api }
41
/**
42
* Base appender implementation with filtering and synchronization.
43
* Provides thread-safe doAppend() method and filter chain support.
44
*/
45
public abstract class AppenderBase<E> extends ContextAwareBase implements Appender<E> {
46
/**
47
* Thread-safe template method that applies filters before calling append().
48
* @param eventObject the event to append
49
* @throws LogbackException if appending fails
50
*/
51
public synchronized void doAppend(E eventObject) throws LogbackException;
52
53
/**
54
* Subclasses must implement this method to handle the actual appending.
55
* Called by doAppend() after filter processing.
56
* @param eventObject the event to append
57
*/
58
protected abstract void append(E eventObject);
59
60
/**
61
* Start the appender. Subclasses should override to perform initialization.
62
*/
63
public void start();
64
65
/**
66
* Stop the appender. Subclasses should override to perform cleanup.
67
*/
68
public void stop();
69
70
/**
71
* Check if the appender is started.
72
* @return true if started, false otherwise
73
*/
74
public boolean isStarted();
75
76
// Filter management methods inherited from FilterAttachable
77
public void addFilter(Filter<E> newFilter);
78
public void clearAllFilters();
79
public List<Filter<E>> getCopyOfAttachedFiltersList();
80
public FilterReply getFilterChainDecision(E event);
81
}
82
```
83
84
### UnsynchronizedAppenderBase
85
86
Base class for appenders that handle their own synchronization or don't require it.
87
88
```java { .api }
89
/**
90
* Base appender without synchronized doAppend() method.
91
* Use when the appender handles synchronization internally or when synchronization is not needed.
92
*/
93
public abstract class UnsynchronizedAppenderBase<E> extends ContextAwareBase
94
implements Appender<E> {
95
/**
96
* Non-synchronized template method for event processing.
97
* @param eventObject the event to append
98
*/
99
public void doAppend(E eventObject);
100
101
/**
102
* Subclasses implement this to handle actual appending.
103
* @param eventObject the event to append
104
*/
105
protected abstract void append(E eventObject);
106
}
107
```
108
109
### OutputStreamAppender
110
111
Base class for appenders that output to an OutputStream, providing encoding support and immediate flush control.
112
113
```java { .api }
114
/**
115
* Appender that writes to an OutputStream with encoder support.
116
* Base class for console and file appenders.
117
*/
118
public class OutputStreamAppender<E> extends UnsynchronizedAppenderBase<E> {
119
/**
120
* Set the target output stream.
121
* @param outputStream the stream to write to
122
*/
123
public void setOutputStream(OutputStream outputStream);
124
125
/**
126
* Get the current output stream.
127
* @return the current output stream
128
*/
129
public OutputStream getOutputStream();
130
131
/**
132
* Set the encoder for formatting events.
133
* @param encoder the encoder to use
134
*/
135
public void setEncoder(Encoder<E> encoder);
136
137
/**
138
* Get the current encoder.
139
* @return the current encoder
140
*/
141
public Encoder<E> getEncoder();
142
143
/**
144
* Control whether to flush immediately after each event.
145
* @param immediateFlush true to flush immediately, false to buffer
146
*/
147
public void setImmediateFlush(boolean immediateFlush);
148
149
/**
150
* Check if immediate flush is enabled.
151
* @return true if immediate flush is enabled
152
*/
153
public boolean isImmediateFlush();
154
155
/**
156
* Set a layout (deprecated - use encoder instead).
157
* @param layout the layout to wrap in an encoder
158
* @deprecated Use setEncoder() instead
159
*/
160
@Deprecated
161
public void setLayout(Layout<E> layout);
162
}
163
```
164
165
### ConsoleAppender
166
167
Appender for writing to console (stdout or stderr).
168
169
```java { .api }
170
/**
171
* Console appender with configurable target (stdout/stderr).
172
*/
173
public class ConsoleAppender<E> extends OutputStreamAppender<E> {
174
/**
175
* Set the console target.
176
* @param value "System.out" or "System.err"
177
*/
178
public void setTarget(String value);
179
180
/**
181
* Get the current console target.
182
* @return "System.out" or "System.err"
183
*/
184
public String getTarget();
185
}
186
```
187
188
### FileAppender
189
190
File-based appender with support for append mode, prudent mode (multi-JVM safety), and buffer configuration.
191
192
```java { .api }
193
/**
194
* File appender with collision detection and multi-JVM safety features.
195
*/
196
public class FileAppender<E> extends OutputStreamAppender<E> {
197
/**
198
* Set the target file path.
199
* @param file path to the log file
200
*/
201
public void setFile(String file);
202
203
/**
204
* Get the current file path.
205
* @return path to the log file
206
*/
207
public String getFile();
208
209
/**
210
* Set append mode.
211
* @param append true to append to existing file, false to truncate
212
*/
213
public void setAppend(boolean append);
214
215
/**
216
* Check if append mode is enabled.
217
* @return true if appending, false if truncating
218
*/
219
public boolean isAppend();
220
221
/**
222
* Enable prudent mode for multi-JVM safety.
223
* @param prudent true to enable prudent mode
224
*/
225
public void setPrudent(boolean prudent);
226
227
/**
228
* Check if prudent mode is enabled.
229
* @return true if prudent mode is enabled
230
*/
231
public boolean isPrudent();
232
233
/**
234
* Set the buffer size for file operations.
235
* @param bufferSize buffer size in bytes
236
*/
237
public void setBufferSize(FileSize bufferSize);
238
239
/**
240
* Get the current buffer size.
241
* @return buffer size
242
*/
243
public FileSize getBufferSize();
244
245
/**
246
* Open a file for writing.
247
* @param fileName path to the file to open
248
* @throws IOException if file cannot be opened
249
*/
250
public void openFile(String fileName) throws IOException;
251
}
252
```
253
254
### AsyncAppenderBase
255
256
Base class for asynchronous appenders that use a worker thread and queue for non-blocking log processing.
257
258
```java { .api }
259
/**
260
* Asynchronous appender base with configurable queue and worker thread.
261
*/
262
public abstract class AsyncAppenderBase<E> extends UnsynchronizedAppenderBase<E>
263
implements AppenderAttachable<E> {
264
/**
265
* Set the queue size for buffering events.
266
* @param queueSize maximum number of events to buffer
267
*/
268
public void setQueueSize(int queueSize);
269
270
/**
271
* Get the current queue size.
272
* @return queue size
273
*/
274
public int getQueueSize();
275
276
/**
277
* Set the threshold for discarding events when queue is full.
278
* @param discardingThreshold threshold for discarding events
279
*/
280
public void setDiscardingThreshold(int discardingThreshold);
281
282
/**
283
* Get the discarding threshold.
284
* @return discarding threshold
285
*/
286
public int getDiscardingThreshold();
287
288
/**
289
* Set the maximum time to wait for queue flush on shutdown.
290
* @param maxFlushTime maximum flush time in milliseconds
291
*/
292
public void setMaxFlushTime(int maxFlushTime);
293
294
/**
295
* Get the maximum flush time.
296
* @return maximum flush time in milliseconds
297
*/
298
public int getMaxFlushTime();
299
300
/**
301
* Enable never-block mode to prevent blocking when queue is full.
302
* @param neverBlock true to enable never-block mode
303
*/
304
public void setNeverBlock(boolean neverBlock);
305
306
/**
307
* Check if never-block mode is enabled.
308
* @return true if never-block mode is enabled
309
*/
310
public boolean isNeverBlock();
311
312
/**
313
* Add an appender to receive events from the async queue.
314
* @param newAppender appender to add
315
*/
316
public void addAppender(Appender<E> newAppender);
317
318
/**
319
* Get the number of events in the queue.
320
* @return queue depth
321
*/
322
public int getQueueSize();
323
324
/**
325
* Get the number of elements remaining in the queue.
326
* @return remaining queue capacity
327
*/
328
public int getRemainingCapacity();
329
}
330
```
331
332
## Usage Examples
333
334
### Basic Console Appender
335
336
```java
337
import ch.qos.logback.core.ConsoleAppender;
338
import ch.qos.logback.core.encoder.LayoutWrappingEncoder;
339
340
// Create and configure console appender
341
ConsoleAppender<Object> appender = new ConsoleAppender<>();
342
appender.setContext(context);
343
appender.setTarget("System.out");
344
345
// Configure encoder
346
LayoutWrappingEncoder<Object> encoder = new LayoutWrappingEncoder<>();
347
encoder.setContext(context);
348
// encoder.setLayout(layout); // Set your layout here
349
encoder.start();
350
351
appender.setEncoder(encoder);
352
appender.start();
353
354
// Use the appender
355
appender.doAppend(someEvent);
356
```
357
358
### File Appender with Prudent Mode
359
360
```java
361
import ch.qos.logback.core.FileAppender;
362
import ch.qos.logback.core.util.FileSize;
363
364
// Create file appender with multi-JVM safety
365
FileAppender<Object> fileAppender = new FileAppender<>();
366
fileAppender.setContext(context);
367
fileAppender.setFile("/path/to/application.log");
368
fileAppender.setAppend(true);
369
fileAppender.setPrudent(true); // Enable multi-JVM safety
370
fileAppender.setBufferSize(new FileSize(8192)); // 8KB buffer
371
372
fileAppender.setEncoder(encoder);
373
fileAppender.start();
374
```
375
376
### Custom Appender Implementation
377
378
```java
379
import ch.qos.logback.core.AppenderBase;
380
381
public class CustomAppender<E> extends AppenderBase<E> {
382
private String customProperty;
383
384
@Override
385
protected void append(E eventObject) {
386
// Custom appending logic here
387
System.out.println("Custom: " + eventObject.toString());
388
}
389
390
public void setCustomProperty(String customProperty) {
391
this.customProperty = customProperty;
392
}
393
394
public String getCustomProperty() {
395
return customProperty;
396
}
397
398
@Override
399
public void start() {
400
if (customProperty == null) {
401
addError("CustomProperty is not set");
402
return;
403
}
404
super.start();
405
}
406
}
407
```
408
409
## Appender Attachment
410
411
```java { .api }
412
/**
413
* Interface for components that can attach multiple appenders.
414
*/
415
public interface AppenderAttachable<E> {
416
/**
417
* Add an appender.
418
* @param newAppender appender to add
419
*/
420
void addAppender(Appender<E> newAppender);
421
422
/**
423
* Iterate over attached appenders.
424
* @return iterator for appenders
425
*/
426
Iterator<Appender<E>> iteratorForAppenders();
427
428
/**
429
* Get an appender by name.
430
* @param name appender name
431
* @return appender with the given name, or null
432
*/
433
Appender<E> getAppender(String name);
434
435
/**
436
* Check if an appender is attached.
437
* @param appender appender to check
438
* @return true if attached
439
*/
440
boolean isAttached(Appender<E> appender);
441
442
/**
443
* Detach and stop all appenders.
444
*/
445
void detachAndStopAllAppenders();
446
447
/**
448
* Detach a specific appender.
449
* @param appender appender to detach
450
* @return true if appender was attached and detached
451
*/
452
boolean detachAppender(Appender<E> appender);
453
454
/**
455
* Append an event to all attached appenders.
456
* @param event event to append
457
* @return number of appenders that received the event
458
*/
459
int appendLoopOnAppenders(E event);
460
}
461
```
462
463
## Lifecycle Management
464
465
All appenders implement the `LifeCycle` interface and follow a consistent start/stop pattern:
466
467
1. **Configuration Phase**: Set properties and dependencies
468
2. **Start Phase**: Call `start()` to initialize resources and validate configuration
469
3. **Active Phase**: Process events through `doAppend()`
470
4. **Stop Phase**: Call `stop()` to cleanup resources and flush buffers
471
472
Appenders should always be started before use and stopped when no longer needed to ensure proper resource management.