0
# Filter System
1
2
Configurable filter system for controlling which log events are processed by appenders with threshold and custom filtering capabilities. The filter system provides both level-based filtering and extensible custom filter support.
3
4
## Capabilities
5
6
### FilterFactory Interface
7
8
Base SPI interface for creating custom Logback filters with Jackson-based polymorphic configuration.
9
10
```java { .api }
11
/**
12
* SPI for creating Logback Filter instances
13
*/
14
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
15
public interface FilterFactory<E> extends Discoverable {
16
/**
17
* Build a filter instance
18
* @return configured Filter instance
19
*/
20
Filter<E> build();
21
}
22
```
23
24
### LevelFilterFactory Interface
25
26
Interface for creating level-based filters that filter events based on logging levels.
27
28
```java { .api }
29
/**
30
* Interface for creating level-based filters
31
*/
32
public interface LevelFilterFactory<E> {
33
/**
34
* Build a level filter instance
35
* @param threshold the minimum level threshold
36
* @return configured Filter instance
37
*/
38
Filter<E> build(Level threshold);
39
}
40
```
41
42
### ThresholdLevelFilterFactory
43
44
Default implementation that creates threshold filters for filtering events below a minimum log level.
45
46
```java { .api }
47
/**
48
* Creates threshold filters for minimum log levels
49
*/
50
public class ThresholdLevelFilterFactory implements LevelFilterFactory<ILoggingEvent> {
51
/**
52
* Build a threshold filter that accepts events at or above the threshold level
53
* @param threshold the minimum level threshold
54
* @return ThresholdFilter configured with the specified level
55
*/
56
@Override
57
public Filter<ILoggingEvent> build(Level threshold);
58
}
59
```
60
61
**Usage Example:**
62
63
```java
64
ThresholdLevelFilterFactory filterFactory = new ThresholdLevelFilterFactory();
65
Filter<ILoggingEvent> filter = filterFactory.build(Level.WARN);
66
67
// The filter will accept WARN, ERROR levels and reject DEBUG, INFO levels
68
FilterReply reply1 = filter.decide(infoEvent); // Returns DENY
69
FilterReply reply2 = filter.decide(warnEvent); // Returns NEUTRAL (accept)
70
FilterReply reply3 = filter.decide(errorEvent); // Returns NEUTRAL (accept)
71
```
72
73
### NullLevelFilterFactory
74
75
No-op filter factory that creates filters which always return NEUTRAL, effectively passing all events through.
76
77
```java { .api }
78
/**
79
* Creates no-op filters that always return NEUTRAL
80
*/
81
public class NullLevelFilterFactory<E> implements LevelFilterFactory<E> {
82
/**
83
* Build a no-op filter that accepts all events
84
* @param threshold ignored parameter
85
* @return Filter that always returns NEUTRAL
86
*/
87
@Override
88
public Filter<E> build(Level threshold);
89
}
90
```
91
92
**Usage Example:**
93
94
```java
95
NullLevelFilterFactory<ILoggingEvent> filterFactory = new NullLevelFilterFactory<>();
96
Filter<ILoggingEvent> filter = filterFactory.build(Level.DEBUG); // threshold ignored
97
98
// The filter will accept all events regardless of level
99
FilterReply reply = filter.decide(anyEvent); // Always returns NEUTRAL
100
```
101
102
## Filter Configuration in Appenders
103
104
Filters can be configured on appenders to control which events are processed. The AbstractAppenderFactory provides support for multiple filter configurations.
105
106
### Using Filters with Appenders
107
108
```java { .api }
109
public abstract class AbstractAppenderFactory<E> implements AppenderFactory<E> {
110
protected List<FilterFactory<E>> filterFactories = new ArrayList<>();
111
112
/**
113
* Set additional filter factories
114
* @param filterFactories list of filter factories to apply
115
*/
116
public void setFilterFactories(List<FilterFactory<E>> filterFactories);
117
118
/**
119
* Get the configured filter factories
120
* @return list of filter factories
121
*/
122
public List<FilterFactory<E>> getFilterFactories();
123
124
/**
125
* Add a single filter factory
126
* @param filterFactory the filter factory to add
127
*/
128
public void addFilterFactory(FilterFactory<E> filterFactory);
129
}
130
```
131
132
**Usage Example:**
133
134
```java
135
// Create a console appender with custom filtering
136
ConsoleAppenderFactory<ILoggingEvent> consoleAppender = new ConsoleAppenderFactory<>();
137
138
// Add a threshold filter to only show WARN and above
139
ThresholdLevelFilterFactory thresholdFilter = new ThresholdLevelFilterFactory();
140
List<FilterFactory<ILoggingEvent>> filters = new ArrayList<>();
141
filters.add(thresholdFilter);
142
143
consoleAppender.setFilterFactories(filters);
144
consoleAppender.setThreshold(Level.WARN); // This also applies threshold filtering
145
146
// Build the appender
147
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
148
Appender<ILoggingEvent> appender = consoleAppender.build(context, "MyApp",
149
new DropwizardLayoutFactory(), thresholdFilter, new AsyncLoggingEventAppenderFactory());
150
```
151
152
## Custom Filter Implementation
153
154
You can create custom filters by implementing the FilterFactory interface:
155
156
### Custom Filter Example
157
158
```java
159
/**
160
* Example custom filter that filters by logger name pattern
161
*/
162
@JsonTypeName("logger-pattern")
163
public class LoggerPatternFilterFactory implements FilterFactory<ILoggingEvent> {
164
private String pattern;
165
private boolean include = true;
166
167
public void setPattern(String pattern) {
168
this.pattern = pattern;
169
}
170
171
public void setInclude(boolean include) {
172
this.include = include;
173
}
174
175
@Override
176
public Filter<ILoggingEvent> build() {
177
return new Filter<ILoggingEvent>() {
178
private Pattern compiledPattern = Pattern.compile(pattern);
179
180
@Override
181
public FilterReply decide(ILoggingEvent event) {
182
boolean matches = compiledPattern.matcher(event.getLoggerName()).matches();
183
184
if (include) {
185
return matches ? FilterReply.NEUTRAL : FilterReply.DENY;
186
} else {
187
return matches ? FilterReply.DENY : FilterReply.NEUTRAL;
188
}
189
}
190
};
191
}
192
}
193
```
194
195
**Usage Example:**
196
197
```java
198
// Filter to only include database-related loggers
199
LoggerPatternFilterFactory dbFilter = new LoggerPatternFilterFactory();
200
dbFilter.setPattern(".*\\.db\\..*");
201
dbFilter.setInclude(true);
202
203
// Filter to exclude noisy loggers
204
LoggerPatternFilterFactory noiseFilter = new LoggerPatternFilterFactory();
205
noiseFilter.setPattern("com\\.noisy\\..*");
206
noiseFilter.setInclude(false);
207
208
// Apply filters to an appender
209
FileAppenderFactory<ILoggingEvent> fileAppender = new FileAppenderFactory<>();
210
fileAppender.setFilterFactories(Arrays.asList(dbFilter, noiseFilter));
211
```
212
213
## Filter Chain Behavior
214
215
When multiple filters are configured on an appender, they are applied in order with the following logic:
216
217
1. **ACCEPT**: Event is immediately accepted and logged, skipping remaining filters
218
2. **DENY**: Event is immediately rejected and not logged, skipping remaining filters
219
3. **NEUTRAL**: Continue to the next filter in the chain
220
221
If all filters return NEUTRAL, the event is accepted and logged.
222
223
**Filter Chain Example:**
224
225
```java
226
// Create multiple filters
227
List<FilterFactory<ILoggingEvent>> filterChain = Arrays.asList(
228
createThresholdFilter(Level.DEBUG), // First: must be DEBUG or above
229
createLoggerPatternFilter("com.app.*"), // Second: must match logger pattern
230
createCustomBusinessFilter() // Third: custom business logic
231
);
232
233
ConsoleAppenderFactory<ILoggingEvent> appender = new ConsoleAppenderFactory<>();
234
appender.setFilterFactories(filterChain);
235
236
// Event processing:
237
// 1. ThresholdFilter: if level < DEBUG -> DENY (stop)
238
// 2. LoggerPatternFilter: if logger doesn't match -> DENY (stop)
239
// 3. CustomBusinessFilter: apply business logic -> ACCEPT/DENY/NEUTRAL
240
// 4. If all return NEUTRAL -> event is logged
241
```
242
243
## Built-in Logback Filters
244
245
You can also wrap standard Logback filters in FilterFactory implementations:
246
247
### Common Logback Filters
248
249
- **ThresholdFilter**: Filter by minimum level (provided by ThresholdLevelFilterFactory)
250
- **LevelFilter**: Filter by exact level match
251
- **RegexFilter**: Filter by regex pattern matching on formatted message
252
- **MDCFilter**: Filter by MDC (Mapped Diagnostic Context) values
253
- **EvaluatorFilter**: Filter using Groovy/Janino expressions
254
255
**Example wrapping a RegexFilter:**
256
257
```java
258
@JsonTypeName("regex")
259
public class RegexFilterFactory implements FilterFactory<ILoggingEvent> {
260
private String regex;
261
private FilterReply onMatch = FilterReply.NEUTRAL;
262
private FilterReply onMismatch = FilterReply.DENY;
263
264
@Override
265
public Filter<ILoggingEvent> build() {
266
ch.qos.logback.core.filter.Filter<ILoggingEvent> regexFilter =
267
new ch.qos.logback.core.filter.Filter<ILoggingEvent>() {
268
private Pattern pattern = Pattern.compile(regex);
269
270
@Override
271
public FilterReply decide(ILoggingEvent event) {
272
String message = event.getFormattedMessage();
273
return pattern.matcher(message).find() ? onMatch : onMismatch;
274
}
275
};
276
return regexFilter;
277
}
278
}
279
```