Logback中%X的使用

1. 參考資料

2. 環境

Java: jdk1.8.0_144
Logback: 1.0.13html

3. %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.

4. 與%replace的配合使用

示例 說明
%replace(p ){r, t} p 爲日誌內容,r 是正則表達式,將p 中符合r 的內容替換爲t
  • 把只有key沒有value內容從日誌中替換掉
<?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.
相關文章
相關標籤/搜索