Logback中%X的使用
1. 参考资料
- https://gist.github.com/logogin/ff44c254f655340b653c
- http://www.cnblogs.com/zhudongchang/p/6861375.html
2. 环境
Java: jdk1.8.0_144
Logback: 1.0.13
3. %X 的使用方法
%X用于输出和当前线程相关联的NDC(嵌套诊断环境),在代码中给org.slf4j.MDC添加key/value即可增加新值
| 示例 | 说明 |
|---|---|
| %X | 输出所有值 |
| %X{testKey} | 输出testKey所对应的value,且无默认值 |
| %X{testKey:-} | 输出testKey所对应的value,默认为空 |
| %X{testKey:-aaa} | 输出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 ){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>
结果
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.
Logback中%X的使用的更多相关文章
- Logback中使用TurboFilter实现日志级别等内容的动态修改
可能看到这个标题,读者会问:要修改日志的级别,不是直接修改log.xxx就好了吗?为何要搞那么复杂呢?所以,先说一下场景,为什么要通过TurboFilter去动态的修改日志级别.我们在使用Java开发 ...
- Logback中如何自定义灵活的日志过滤规则
当我们需要对日志的打印要做一些范围的控制的时候,通常都是通过为各个Appender设置不同的Filter配置来实现.在Logback中自带了两个过滤器实现:ch.qos.logback.classic ...
- Logback中文文档(二):体系结构
logback Logback 的基本结构充分通用,可应用于各种不同环境.目前,logback 分为三个模块:Core.Classic 和 Access. Core模块是其他两个模块的基础.Class ...
- 守护线程在logback中的使用 - 论基础知识的重要性
守护线程在logback中的使用 先说问题,在java应用中,logback的异步Appender是怎么在主线程结束后,停下来的? 复盘 我在一个logback的测试用例中,写了这样的代码和logba ...
- logback中appender继承
实例: <?xml version="1.0" encoding="UTF-8"?> <configuration debug="t ...
- logback中配置的日志文件的生成地址
配置文件如下 <?xml version="1.0" encoding="UTF-8"?> <configuration debug=&quo ...
- logback中logger详解
前言 logback实践笔记 上一篇主要对root进行了实践总结,现在基于上一篇中的springboot代码环境对logback.xml中的logger来进行实践和自己遇到的坑. logger简介 ...
- Logback中文文档(四):Appender
什么是 Appender Appender是负责写记录事件的组件.Appender 必须实现接口"ch.qos.logback.core.Appender".该接口的重要方法总结如 ...
- Logback中文文档(三):配置
在第一部分,我们将介绍配置 logback 的各种方法,给出了很多配置脚本例子.在第二部分,我们将介绍 Joran,它是一个通用配置框架,你可以在自己的项目里使用 Joran. Logback里的配置 ...
- logback中MDC使用
今天在项目发现别人写了很多MDC.put("taskid", "testThread/heart/main_heart");或者MDC.put("ta ...
随机推荐
- 【paddle学习】图像分类
https://zhuanlan.zhihu.com/p/28871960 深度学习模型中的卷积神经网络(Convolution Neural Network, CNN)近年来在图像领域取得了惊人的成 ...
- NPOI操作Excel 005:写入空Excel(Winform版)
前文写了一个BS版本号的导出Excel的样例(http://blog.csdn.net/yysyangyangyangshan/article/details/47904119).对于CS版在保存的地 ...
- C#中Queue<T>类的使用以及部分方法的源代码分析
Queue<T>类 表示对象的先进先出集合. 队列在按接收顺序存储消息方面很实用,以便于进行顺序处理. 存储在 Queue,<T> 中的对象在一端插入,从还有一端移除. Que ...
- 一览新的 Android Gradle 构建工具:新的 DSL 结构 和 Gradle 2.5
译者地址:[翻]一览新的 Android Gradle 构建工具:新的 DSL 结构 和 Gradle 2.5 原文:First Look at New Android Gradle Build To ...
- java设计模式----真实世界的模式
设计模式的定义: 模式是在某情境下,针对某问题的某种解决方案 反模式: 告诉你如何采用一个不好的解决方案解决一个问题 要点: 1.让设计模式自然而然地出现在你的设计中,而不是为了使用而使用 2.设计模 ...
- 写码时应该缩进使用 tab 还是空格?
对于程序员来说,其实Tab和空格远远不只是“立场”问题那么简单. 在不同的编辑器里tab的长度可能不一致,所以在一个编辑器里用tab设置缩进后,在其它编辑器里看可能缩进就乱了.空格不会出现这个问题,因 ...
- ArrayList遍历的4种方法
public class ArrayListDemo { public static void main(String args[]){ List<String> list = new A ...
- SQL常见问题及解决备忘
1.mysql中:you cant't specify tartget table for update in from clause 错误 含义:在同一语句中update或delete某张表的时候, ...
- hadoop shuffle
1 hadoop shuffle的地位 hadoop shuffle是map reduce算法的核心,是它连接了多个map和多个reduce,它将map的输出交给reduce作为输入. 2 hado ...
- 使用双引擎,让kbmmw 的客户端访问更方便(既给浏览器做服务,也给桌面程序做服务)
前面我们一直都讲了如何使用kbmmw smarthttpservice 给客户端提供REST 服务.主要都是返回给 浏览器访问的,如果我们使用delphi 开发桌面应用,如何使用这些服务呢?其实一切 ...