java常用日志框架简介

log4j和logback都是java项目中经常使用的日志框架,通常会结合slf4j一起使用。
log4j和logback都是具体的日志实现框架,slf4j是一个接口层框架,slf4j-log4j,slf4j-logback则是针对log4j和logback的桥接框架。使用slf4j,就可以随意切换日志框架,而不用修改代码。

高并发系统日志记录

多线程环境会由于多个线程同时会向一个日志文件记录日志,所以会导致日志混乱,查找某个线程的日志变的不方便。比如跟踪某个订单号、某个用户的相关日志。
我们可以使用slf4j的MDC来解决这个问题。

MDC ( Mapped Diagnostic Contexts ),顾名思义,其目的是为了便于我们诊断线上问题而出现的方法工具类。虽然,Slf4j 是用来适配其他的日志具体实现包的,但是针对 MDC功能,目前只有logback以及log4j支持。
MDC对外提供的接口:

1
2
3
4
5
6
7
8
9
10
11
public class MDC {
//Put a context value as identified by key
//into the current thread's context map.
public static void put(String key, String val);
//Get the context identified by the key parameter.
public static String get(String key);
//Remove the context identified by the key parameter.
public static void remove(String key);
//Clear all entries in the MDC.
public static void clear();
}

接口定义非常简单,此外,其使用也非常简单。

一般,我们在代码中,只需要将指定的值put到线程上下文的Map中,然后,在对应的地方使用 get方法获取对应的值。此外,对于一些线程池使用的应用场景,可能我们在最后使用结束时,需要调用clear方法来清洗将要丢弃的数据。

看看一个MDC使用的简单示例

1
2
3
4
5
6
MDC.put("traceNo","jd.com");
logger.info("method testFindByName in UserServiceTest");
User user = userService.findByName("test");
logger.info("user:{}",user);
Assert.assertNotNull(user);
MDC.clear();

logback.xml配置:

1
2
3
4
5
6
7
8
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<!-- 对日志进行格式化。 -->
<encoder>
<pattern>
%d{yyyy-MM-dd HH:mm:ss} %level %logger.%M\(%F:%L\)] [%X{traceNo}] %msg%n
</pattern>
</encoder>
</appender>

如上,在logback.xml中的pattern中我们加入了[%X{traceNo}],在MDC中放入traceNo的值,就可以记录日志了。

1
2018-03-03 10:11:27 INFO com.tommy.myapp.dao.UserServiceTest.testFindByName(UserServiceTest.java:52)] [jd.com] user:User{id=1, name='test', birthday=Sat Mar 03 10:11:27 CST 2018}

注意日志中的[jd.com],这就是我们日志中加入的自定义的字段,在Linux系统中,我们可以通过grep traceNo xx.log --color查询某个跟踪号相关的日志,并高亮显示。

在WEB系统中,则可以新建一个自定义的请求过滤器,对业务请求进行过滤,在过滤器内处理请求前加入traceNo,请求处理完毕后,从MDC删除traceNo。

logback MDC的使用和分析可以参考:Slf4j MDC 使用和 基于 Logback 的实现分析

logback使用参考:Java 日志组件slf4j+logback使用实例logback.xml常用配置

参考:Java日志终极指南