1. 参考资料

2. 环境

Java: jdk1.8.0_144
Logback: 1.0.13

3. %X 的使用方法

%X用于输出和当前线程相关联的NDC(嵌套诊断环境),在代码中给org.slf4j.MDC添加key/value即可增加新值

示例 说明
%X 输出所有值
%X 输出testKey所对应的value,且无默认值
%X 输出testKey所对应的value,默认为空
%X 输出testKey所对应的value,默认为aaa

测试代码

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>

结果

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 ) 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>

结果

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.
 posted on 2018-11-01 01:59  hiv  阅读(14295)  评论(0编辑  收藏  举报