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 ...
随机推荐
- Filter和Interceptor的终归作用还是从入口修改或验证请求进来的数据
Filter是Java EE标准.Inteceptor是Spring 标准. Filter在servlet前面,Interveptor在servlet之后 Filter和Inteceptor都可以改变 ...
- nginx匹配规则
rewrite ^/(.*)$ /index.php/$1 last; 这句话的意思,是把slash(/)之后的所有内容在前面加上一个/index.php,这里的$1指代前面括号的正则表达式(.*)所 ...
- UP Board USB无线网卡选购指南
前言 原创文章,转载引用务必注明链接,水平有限,欢迎指正. 本文环境:ubilinux 3.0 kernel 4.4.0 本文使用Markdown写成,为获得更好的阅读体验和正常的图片.链接,请访问我 ...
- Java并发编程(三)volatile域
相关文章 Java并发编程(一)线程定义.状态和属性 Java并发编程(二)同步 Android多线程(一)线程池 Android多线程(二)AsyncTask源代码分析 前言 有时仅仅为了读写一个或 ...
- GridView的经常使用属性
1.android:numColumns="auto_fit" //GridView的列数设置为自己主动 2.android:columnWidth="90dp &q ...
- 安卓自带下拉刷新SwipeRefreshLayout加入上拉刷新功能
在项目里面要用到刷新库.曾经都是使用第三方的.只是看到官方出了 SwipeRefreshLayout之后就用SwipeRefreshLayout.可是不知道什么原因官方SwipeRefreshL ...
- C指针——C语言手记
近期敲代码的时候.发现自己非常多东西都開始忘了. 今天最终有机会好好总结一下指针.当做个笔记同一时候也希望对大家实用.假设有不对的地方.希望大家能帮我指正一下.然后我的实验环境是32位RHEL+ecl ...
- iOS 把数据库文件打包到mainbundle中,查找不到路径的解决的方法;以及在删除bundle中文件的可行性
在开发中有时我们须要把数据库文件打包到我们的项目中.一般我们都是在外部用工具生成数据库文件,然后拉入项目中.可是我们在程序中查找改文件时.返回的路径总是nil 解决的方法: 原因我们拉入其它资源文件( ...
- 在线API
JExcelApi http://jexcelapi.sourceforge.net/resources/javadocs/index.html Poi http://poi.apache.org/a ...
- php新版本号废弃 preg_replace /e 修饰符
近期serverphp版本号升级到了 5.6 发现出了非常多警告 preg_replace(): The /e modifier is deprecated, use preg_replace_ca ...