Skip to content

Commit 4d2aa25

Browse files
committed
Refactor: change BoskLogFilter into a TurboFilter.
TurboFilter is better for several reasons: - It applies to all appenders. Filter must be applied per-appender. - It's faster than Filter - It has access to the Logger so it can honour explicitly configured log levels
1 parent a0cc191 commit 4d2aa25

File tree

3 files changed

+51
-13
lines changed

3 files changed

+51
-13
lines changed

bosk-logback/src/main/java/works/bosk/logback/BoskLogFilter.java

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
package works.bosk.logback;
22

33
import ch.qos.logback.classic.Level;
4-
import ch.qos.logback.classic.spi.ILoggingEvent;
5-
import ch.qos.logback.core.filter.Filter;
4+
import ch.qos.logback.classic.Logger;
5+
import ch.qos.logback.classic.turbo.TurboFilter;
66
import ch.qos.logback.core.spi.FilterReply;
77
import java.util.Map;
88
import java.util.concurrent.ConcurrentHashMap;
99
import java.util.stream.Stream;
10-
import org.slf4j.Logger;
1110
import org.slf4j.LoggerFactory;
1211
import org.slf4j.MDC;
12+
import org.slf4j.Marker;
1313
import works.bosk.Bosk;
1414
import works.bosk.DriverFactory;
1515
import works.bosk.StateTreeNode;
@@ -20,7 +20,39 @@
2020
import static java.util.stream.Collectors.toMap;
2121
import static works.bosk.logging.MdcKeys.BOSK_INSTANCE_ID;
2222

23-
public class BoskLogFilter extends Filter<ILoggingEvent> {
23+
/**
24+
* A Logback {@link TurboFilter} that provides per-bosk logging control.
25+
* Intended to suppress expected warnings and errors during testing.
26+
* <p>
27+
* A {@link Bosk} whose driver stack includes {@link #withController}
28+
* will be able to set log levels using {@link LogController#setLogging}
29+
* without affecting other logs.
30+
* <p>
31+
* This class infers that a log message is associated with a particular bosk
32+
* by checking the MDC for the key {@link MdcKeys#BOSK_INSTANCE_ID},
33+
* which you can set using {@link works.bosk.logging.MappedDiagnosticContext#setupMDC setupMDC}.
34+
* <p>
35+
* <em>Note</em>: most bosk drivers don't set this MDC key. TODO: Improve this.
36+
* <p>
37+
* Log levels are determined using the following precedence:
38+
* <ol>
39+
* <li>
40+
* If the specific logger is configured with some level,
41+
* that level is used;
42+
* </li>
43+
* <li>
44+
* otherwise, if the logger is associated with a bosk whose driver
45+
* was configured with {@link #withController} and that controller
46+
* has an override for that specific logger, that override is used;
47+
* </li>
48+
* <li>
49+
* otherwise, the usual Logback rules apply, which means
50+
* that the logger inherits the level from its ancestors.
51+
* </li>
52+
* </ol>
53+
*
54+
*/
55+
public class BoskLogFilter extends TurboFilter {
2456
private static final ConcurrentHashMap<String, LogController> controllersByBoskID = new ConcurrentHashMap<>();
2557

2658
public static final class LogController {
@@ -57,7 +89,11 @@ public static <R extends StateTreeNode> DriverFactory<R> withController(LogContr
5789
}
5890

5991
@Override
60-
public FilterReply decide(ILoggingEvent event) {
92+
public FilterReply decide(Marker marker, Logger logger, Level messageLevel, String format, Object[] params, Throwable t) {
93+
if (logger.getLevel() != null) {
94+
// Respect user-supplied log levels
95+
return NEUTRAL;
96+
}
6197
String boskID = MDC.get(BOSK_INSTANCE_ID);
6298
if (boskID == null) {
6399
return NEUTRAL;
@@ -66,16 +102,18 @@ public FilterReply decide(ILoggingEvent event) {
66102
if (controller == null) {
67103
return NEUTRAL;
68104
}
69-
Level level = controller.overrides.get(event.getLoggerName());
70-
if (level == null) {
105+
Level overrideLevel = controller.overrides.get(logger.getName());
106+
if (overrideLevel == null) {
71107
return NEUTRAL;
72108
}
73-
if (event.getLevel().isGreaterOrEqual(level)) {
74-
return NEUTRAL;
75-
} else {
109+
110+
// There is an override. Deny if the message's level is too low.
111+
if (overrideLevel.isGreaterOrEqual(messageLevel)) {
76112
return DENY;
113+
} else {
114+
return NEUTRAL;
77115
}
78116
}
79117

80-
private static final Logger LOGGER = LoggerFactory.getLogger(BoskLogFilter.class);
118+
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(BoskLogFilter.class);
81119
}

example-hello/src/main/resources/logback.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<configuration>
2+
<turboFilter class="works.bosk.logback.BoskLogFilter"/>
23
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
3-
<filter class="works.bosk.logback.BoskLogFilter"/>
44
<encoder>
55
<pattern>%d %-5level [%thread] [%X{bosk.name}]%X{bosk.MongoDriver.transaction}%X{bosk.MongoDriver.event} %logger{25}: %msg%n</pattern>
66
</encoder>

lib-testing/src/main/resources/logback.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<configuration>
2+
<turboFilter class="works.bosk.logback.BoskLogFilter"/>
23
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
3-
<filter class="works.bosk.logback.BoskLogFilter"/>
44
<encoder>
55
<pattern>%d %-5level [%thread] [%X{bosk.name}]%X{bosk.MongoDriver.transaction}%X{bosk.MongoDriver.event} %logger{25}: %msg%n</pattern>
66
</encoder>

0 commit comments

Comments
 (0)