Java: jdk1.8.0_144
Logback: 1.0.13html
%X
的使用方法%X用於輸出和當前線程相關聯的NDC(嵌套診斷環境),在代碼中給org.slf4j.MDC添加key/value便可增長新值git
示例 | 說明 |
---|---|
%X | 輸出全部值 |
%X{testKey} | 輸出testKey所對應的value,且無默認值 |
%X{testKey:-} | 輸出testKey所對應的value,默認爲空 |
%X{testKey:-aaa} | 輸出testKey所對應的value,默認爲aaa |
測試代碼github
public class AbstractLogWrapper<T> { private final T job; private final Map<?, ?> context; public AbstractLogWrapper(T t) { this.job = t; this.context = MDC.getCopyOfContextMap(); } public void setLogContext() { if (this.context != null) { MDC.setContextMap(this.context); } } public void clearLogContext() { MDC.clear(); } public T getJob() { return this.job; } } public class LogSupplier<T> extends AbstractLogWrapper<Supplier<T>> implements Supplier<T> { public LogSupplier(Supplier<T> supplier) { super(supplier); } @Override public T get() { this.setLogContext(); try { return getJob().get(); } finally { this.clearLogContext(); } } } @RunWith(MockitoJUnitRunner.class) public class LogSupplierTest { private static final Logger LOGGER = LoggerFactory.getLogger(LogSupplierTest.class); private ExecutorService executorService; @Before public void setUp() { executorService = Executors.newFixedThreadPool(2); } @Test public void testGet() { AtomicInteger counter = new AtomicInteger(0); Supplier<String> supplier = () -> { String rtn = String.valueOf(counter.incrementAndGet()); // 往MDC中添加內容 MDC.put(RunnabeTestHelper.RUNNABLE, rtn); LOGGER.info("This is {} supplier.", rtn); return rtn; }; LogSupplier<String> logSupplier = Mockito.spy(new LogSupplier<>(supplier)); Set<String> set = new HashSet<>(); Mockito.doAnswer(invocation -> set.add(invocation.getMethod().getName())).when(logSupplier).setLogContext(); Mockito.doAnswer(invocation -> set.add(invocation.getMethod().getName())).when(logSupplier).clearLogContext(); List<CompletableFuture<String>> futures = IntStream.rangeClosed(0, 4).mapToObj(index -> CompletableFuture.supplyAsync(logSupplier, executorService)).collect(Collectors.toList()); futures.forEach(CompletableFuture::join); Assert.assertEquals("[setLogContext, clearLogContext]", set.toString()); } } class RunnabeTestHelper { static final String RUNNABLE = "runn_able"; }
<?xml version="1.0" encoding="UTF-8"?> <configuration> <appender name="stdot" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>%X %m%n</pattern> </layout> </appender> <root level="debug"> <appender-ref ref="stdot"/> </root> </configuration>
結果正則表達式
runn_able=1 This is 1 supplier. runn_able=3 This is 3 supplier. runn_able=2 This is 2 supplier. runn_able=4 This is 4 supplier. runn_able=5 This is 5 supplier.
<?xml version="1.0" encoding="UTF-8"?> <configuration> <appender name="stdot" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>%X{runn_able} %X{runn_able:-} %X{runnable:-aaa} %m%n</pattern> </layout> </appender> <root level="debug"> <appender-ref ref="stdot"/> </root> </configuration>
結果app
1 1 aaa This is 1 supplier. 2 2 aaa This is 2 supplier. 3 3 aaa This is 3 supplier. 5 5 aaa This is 5 supplier. 4 4 aaa This is 4 supplier.
%replace
的配合使用示例 | 說明 |
---|---|
%replace(p ){r, t} | p 爲日誌內容,r 是正則表達式,將p 中符合r 的內容替換爲t |
<?xml version="1.0" encoding="UTF-8"?> <configuration> <appender name="stdot" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>%replace(Test_Method=%X{method} runn-able=%X{runn_able}){'\S+=( |$)', ''} -> %m%n</pattern> </layout> </appender> <root level="debug"> <appender-ref ref="stdot"/> </root> </configuration>
結果ide
runn-able=2 -> This is 2 supplier. runn-able=3 -> This is 3 supplier. runn-able=4 -> This is 4 supplier. runn-able=5 -> This is 5 supplier. runn-able=1 -> This is 1 supplier.