0
# Filters
1
2
Event filtering mechanisms for controlling which log events are processed at various levels of the logging pipeline. Filters provide fine-grained control over log processing with minimal performance impact.
3
4
## Capabilities
5
6
### Core Filter Interface
7
8
Base interface and functionality for all filters.
9
10
```java { .api }
11
/**
12
* Core filter interface for controlling log event processing
13
*/
14
public abstract class Filter<E> extends ContextAwareBase implements LifeCycle {
15
private String name;
16
17
/**
18
* Decide whether to accept, deny, or remain neutral about an event
19
*/
20
public abstract FilterReply decide(E event);
21
22
public String getName();
23
public void setName(String name);
24
25
// LifeCycle methods
26
public void start();
27
public void stop();
28
public boolean isStarted();
29
}
30
31
/**
32
* Filter decision enumeration
33
*/
34
public enum FilterReply {
35
DENY, // Reject the event immediately
36
NEUTRAL, // Let other filters decide
37
ACCEPT // Accept the event immediately
38
}
39
40
/**
41
* Interface for components that can have filters attached
42
*/
43
public interface FilterAttachable<E> {
44
void addFilter(Filter<E> newFilter);
45
void clearAllFilters();
46
List<Filter<E>> getCopyOfAttachedFiltersList();
47
FilterReply getFilterChainDecision(E event);
48
}
49
```
50
51
### Level Filters
52
53
Filters based on logging levels.
54
55
```java { .api }
56
/**
57
* Filter that accepts or denies events based on exact level match
58
*/
59
public class LevelFilter extends Filter<ILoggingEvent> {
60
Level level;
61
FilterReply onMatch = FilterReply.NEUTRAL;
62
FilterReply onMismatch = FilterReply.NEUTRAL;
63
64
/**
65
* Set the level to match against
66
*/
67
public void setLevel(Level level);
68
public Level getLevel();
69
70
/**
71
* Set action when level matches
72
*/
73
public void setOnMatch(FilterReply reply);
74
public FilterReply getOnMatch();
75
76
/**
77
* Set action when level doesn't match
78
*/
79
public void setOnMismatch(FilterReply reply);
80
public FilterReply getOnMismatch();
81
82
@Override
83
public FilterReply decide(ILoggingEvent event);
84
}
85
86
/**
87
* Filter that denies events below a threshold level
88
*/
89
public class ThresholdFilter extends Filter<ILoggingEvent> {
90
Level level;
91
92
/**
93
* Set the minimum level threshold
94
*/
95
public void setLevel(Level level);
96
public Level getLevel();
97
98
@Override
99
public FilterReply decide(ILoggingEvent event);
100
}
101
```
102
103
**Usage Examples:**
104
105
```java
106
import ch.qos.logback.classic.filter.LevelFilter;
107
import ch.qos.logback.classic.filter.ThresholdFilter;
108
109
// Level filter - only accept INFO events
110
LevelFilter levelFilter = new LevelFilter();
111
levelFilter.setContext(loggerContext);
112
levelFilter.setLevel(Level.INFO);
113
levelFilter.setOnMatch(FilterReply.ACCEPT);
114
levelFilter.setOnMismatch(FilterReply.DENY);
115
levelFilter.start();
116
117
// Threshold filter - accept WARN and above
118
ThresholdFilter thresholdFilter = new ThresholdFilter();
119
thresholdFilter.setContext(loggerContext);
120
thresholdFilter.setLevel(Level.WARN);
121
thresholdFilter.start();
122
123
// Add to appender
124
appender.addFilter(levelFilter);
125
```
126
127
### Turbo Filters
128
129
High-performance filters that operate before LoggingEvent creation.
130
131
```java { .api }
132
/**
133
* High-performance filter base class that operates before event creation
134
*/
135
public abstract class TurboFilter extends ContextAwareBase implements LifeCycle {
136
private String name;
137
138
/**
139
* Decide on logging event before LoggingEvent is created
140
* @param marker the marker (can be null)
141
* @param logger the logger
142
* @param level the level
143
* @param format the message format
144
* @param params message parameters
145
* @param t throwable (can be null)
146
*/
147
public abstract FilterReply decide(Marker marker, Logger logger, Level level,
148
String format, Object[] params, Throwable t);
149
150
public String getName();
151
public void setName(String name);
152
153
public void start();
154
public void stop();
155
public boolean isStarted();
156
}
157
158
/**
159
* Container for turbo filters with evaluation logic
160
*/
161
public final class TurboFilterList extends ArrayList<TurboFilter> {
162
/**
163
* Evaluate all turbo filters for an event
164
*/
165
public FilterReply getTurboFilterChainDecision(Marker marker, Logger logger, Level level,
166
String format, Object[] params, Throwable t);
167
}
168
```
169
170
### Specialized Turbo Filters
171
172
Commonly used turbo filter implementations.
173
174
```java { .api }
175
/**
176
* Filter duplicate messages to reduce log noise
177
*/
178
public class DuplicateMessageFilter extends TurboFilter {
179
public static final int DEFAULT_CACHE_SIZE = 100;
180
public static final int DEFAULT_ALLOWED_REPETITIONS = 5;
181
182
private int allowedRepetitions = DEFAULT_ALLOWED_REPETITIONS;
183
private int cacheSize = DEFAULT_CACHE_SIZE;
184
private LRUMessageCache msgCache;
185
186
/**
187
* Set number of allowed repetitions before filtering
188
*/
189
public int getAllowedRepetitions();
190
public void setAllowedRepetitions(int allowedRepetitions);
191
192
/**
193
* Set cache size for tracking messages
194
*/
195
public int getCacheSize();
196
public void setCacheSize(int cacheSize);
197
198
@Override
199
public FilterReply decide(Marker marker, Logger logger, Level level,
200
String format, Object[] params, Throwable t);
201
}
202
203
/**
204
* Filter based on MDC values
205
*/
206
public class MDCFilter extends TurboFilter {
207
String MDCKey;
208
String value;
209
FilterReply onMatch = FilterReply.NEUTRAL;
210
FilterReply onMismatch = FilterReply.NEUTRAL;
211
212
/**
213
* Set the MDC key to check
214
*/
215
public void setMDCKey(String MDCKey);
216
public String getMDCKey();
217
218
/**
219
* Set the value to match against
220
*/
221
public void setValue(String value);
222
public String getValue();
223
224
/**
225
* Set actions for match/mismatch
226
*/
227
public void setOnMatch(FilterReply reply);
228
public FilterReply getOnMatch();
229
public void setOnMismatch(FilterReply reply);
230
public FilterReply getOnMismatch();
231
232
@Override
233
public FilterReply decide(Marker marker, Logger logger, Level level,
234
String format, Object[] params, Throwable t);
235
}
236
237
/**
238
* Filter based on SLF4J markers
239
*/
240
public class MarkerFilter extends TurboFilter {
241
Marker markerToMatch;
242
FilterReply onMatch = FilterReply.NEUTRAL;
243
FilterReply onMismatch = FilterReply.NEUTRAL;
244
245
/**
246
* Set the marker to match against
247
*/
248
public void setMarker(String markerStr);
249
public String getMarker();
250
251
/**
252
* Set actions for match/mismatch
253
*/
254
public void setOnMatch(FilterReply reply);
255
public FilterReply getOnMatch();
256
public void setOnMismatch(FilterReply reply);
257
public FilterReply getOnMismatch();
258
259
@Override
260
public FilterReply decide(Marker marker, Logger logger, Level level,
261
String format, Object[] params, Throwable t);
262
}
263
264
/**
265
* Dynamic threshold filter based on MDC values
266
*/
267
public class DynamicThresholdFilter extends TurboFilter {
268
private Map<String, Level> valueLevelMap = new HashMap<String, Level>();
269
private Level defaultThreshold;
270
private String key;
271
FilterReply onHigherOrEqual = FilterReply.NEUTRAL;
272
FilterReply onLower = FilterReply.DENY;
273
274
/**
275
* Set the MDC key to use for threshold lookup
276
*/
277
public String getKey();
278
public void setKey(String key);
279
280
/**
281
* Set the default threshold when key not found in MDC
282
*/
283
public void setDefaultThreshold(Level defaultThreshold);
284
public Level getDefaultThreshold();
285
286
/**
287
* Add MDC value to level mapping
288
*/
289
public void addMDCValueLevelPair(MDCValueLevelPair mdcValueLevelPair);
290
291
/**
292
* Set actions for threshold comparison
293
*/
294
public void setOnHigherOrEqual(FilterReply reply);
295
public FilterReply getOnHigherOrEqual();
296
public void setOnLower(FilterReply reply);
297
public FilterReply getOnLower();
298
299
@Override
300
public FilterReply decide(Marker marker, Logger logger, Level level,
301
String format, Object[] params, Throwable t);
302
}
303
304
/**
305
* Reconfigure logback when configuration file changes
306
*/
307
public class ReconfigureOnChangeFilter extends TurboFilter implements ReconfigureOnChangeTask {
308
public static final long DEFAULT_REFRESH_PERIOD = 60 * 1000; // 1 minute
309
310
long refreshPeriod = DEFAULT_REFRESH_PERIOD;
311
URL mainConfigurationURL;
312
protected volatile long nextCheck;
313
ConfigurationWatchList configurationWatchList;
314
315
/**
316
* Set refresh period in milliseconds
317
*/
318
public void setRefreshPeriod(long refreshPeriod);
319
public long getRefreshPeriod();
320
321
@Override
322
public FilterReply decide(Marker marker, Logger logger, Level level,
323
String format, Object[] params, Throwable t);
324
}
325
```
326
327
### Boolean Expression Evaluators
328
329
Advanced filtering using boolean expressions.
330
331
```java { .api }
332
/**
333
* Base interface for event evaluators
334
*/
335
public interface EventEvaluator<E> extends ContextAware, LifeCycle {
336
/**
337
* Evaluate whether an event matches criteria
338
*/
339
boolean evaluate(E event) throws EvaluationException;
340
341
String getName();
342
void setName(String name);
343
}
344
345
/**
346
* Evaluator based on SLF4J markers
347
*/
348
public class OnMarkerEvaluator extends EventEvaluatorBase<ILoggingEvent> {
349
String markerStr;
350
Marker marker;
351
352
/**
353
* Set the marker to evaluate against
354
*/
355
public String getMarker();
356
public void setMarker(String markerStr);
357
358
@Override
359
public boolean evaluate(ILoggingEvent event) throws EvaluationException;
360
}
361
362
/**
363
* Evaluator that matches ERROR level events
364
*/
365
public class OnErrorEvaluator extends EventEvaluatorBase<ILoggingEvent> {
366
@Override
367
public boolean evaluate(ILoggingEvent event);
368
}
369
370
/**
371
* Evaluator based on exception matching
372
*/
373
public class ExceptionMatchEvaluator extends EventEvaluatorBase<ILoggingEvent> {
374
String exceptionClassName;
375
376
/**
377
* Set the exception class name to match
378
*/
379
public String getExceptionClassName();
380
public void setExceptionClassName(String exceptionClassName);
381
382
@Override
383
public boolean evaluate(ILoggingEvent event);
384
}
385
```
386
387
## Usage Examples
388
389
### Complex Filter Chain
390
391
```java
392
import ch.qos.logback.classic.turbo.*;
393
import ch.qos.logback.classic.filter.*;
394
395
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
396
397
// Add turbo filters to context (evaluated first)
398
DuplicateMessageFilter dupFilter = new DuplicateMessageFilter();
399
dupFilter.setContext(context);
400
dupFilter.setAllowedRepetitions(3);
401
dupFilter.setCacheSize(200);
402
dupFilter.start();
403
context.addTurboFilter(dupFilter);
404
405
// MDC-based filtering
406
MDCFilter mdcFilter = new MDCFilter();
407
mdcFilter.setContext(context);
408
mdcFilter.setMDCKey("env");
409
mdcFilter.setValue("production");
410
mdcFilter.setOnMatch(FilterReply.ACCEPT);
411
mdcFilter.setOnMismatch(FilterReply.DENY);
412
mdcFilter.start();
413
context.addTurboFilter(mdcFilter);
414
415
// Add regular filter to appender
416
ThresholdFilter appenderFilter = new ThresholdFilter();
417
appenderFilter.setContext(context);
418
appenderFilter.setLevel(Level.WARN);
419
appenderFilter.start();
420
appender.addFilter(appenderFilter);
421
```
422
423
### Dynamic Threshold Based on User
424
425
```java
426
// Different log levels for different users
427
DynamicThresholdFilter dynFilter = new DynamicThresholdFilter();
428
dynFilter.setContext(context);
429
dynFilter.setKey("userId");
430
dynFilter.setDefaultThreshold(Level.WARN);
431
432
// Admin users get DEBUG level
433
MDCValueLevelPair adminPair = new MDCValueLevelPair();
434
adminPair.setValue("admin");
435
adminPair.setLevel(Level.DEBUG);
436
dynFilter.addMDCValueLevelPair(adminPair);
437
438
// Developer users get INFO level
439
MDCValueLevelPair devPair = new MDCValueLevelPair();
440
devPair.setValue("developer");
441
devPair.setLevel(Level.INFO);
442
dynFilter.addMDCValueLevelPair(devPair);
443
444
dynFilter.start();
445
context.addTurboFilter(dynFilter);
446
447
// In application code:
448
MDC.put("userId", "admin");
449
logger.debug("This will be logged for admin users");
450
MDC.put("userId", "regular");
451
logger.debug("This will NOT be logged for regular users");
452
```
453
454
### Marker-Based Filtering
455
456
```java
457
import org.slf4j.Marker;
458
import org.slf4j.MarkerFactory;
459
460
// Create markers
461
Marker PERFORMANCE = MarkerFactory.getMarker("PERFORMANCE");
462
Marker SECURITY = MarkerFactory.getMarker("SECURITY");
463
464
// Filter for performance logs only
465
MarkerFilter perfFilter = new MarkerFilter();
466
perfFilter.setContext(context);
467
perfFilter.setMarker("PERFORMANCE");
468
perfFilter.setOnMatch(FilterReply.ACCEPT);
469
perfFilter.setOnMismatch(FilterReply.DENY);
470
perfFilter.start();
471
472
// Add to specific appender
473
performanceAppender.addFilter(perfFilter);
474
475
// Usage in code
476
logger.info(PERFORMANCE, "Operation completed in {}ms", duration);
477
logger.warn(SECURITY, "Failed login attempt from {}", ipAddress);
478
```
479
480
### Configuration File Auto-Reload
481
482
```java
483
// Enable automatic reconfiguration on file changes
484
ReconfigureOnChangeFilter reconfFilter = new ReconfigureOnChangeFilter();
485
reconfFilter.setContext(context);
486
reconfFilter.setRefreshPeriod(30000); // Check every 30 seconds
487
reconfFilter.start();
488
context.addTurboFilter(reconfFilter);
489
490
// Logback will automatically reload when logback.xml changes
491
```