如何使用Logback打印当前调用类名的日志?
核心结论
要打印实际触发日志语句的所属类名,对应的Logback pattern关键字是%class(简写%C),你之前配置后输出?不是关键字写错,是漏了调用栈信息采集的必要配置。
配置要点说明
1. 占位符区别不要搞混
%logger(简写%c):输出的是Logger实例初始化时绑定的名称,如果你写LoggerFactory.getLogger(UserService.class),这个值和类名一致;如果初始化时传了自定义名称、或者做了日志通用封装,这个值就和实际调用类不匹配。%class(简写%C):是Logback专门设计用来获取实际发起日志调用的类名的占位符,支持传长度参数控制包名输出长度,比如%class{0}只输出类名不带包,%class{36}输出最长36字符的全类名。
2. 输出?的根因和修复方法
Logback默认不会主动采集调用栈信息(采集调用栈会带来明显的性能损耗),要让%class、%method(简写%M)、%line(简写%L)这类依赖调用栈的占位符正常输出,必须满足配置要求:
- 如果你用了
AsyncAppender做异步日志输出,必须手动打开调用栈采集开关,默认配置下异步appender会主动丢弃调用栈数据来提升性能,配置示例:
<appender name="ASYNC_EXAMPLE" class="ch.qos.logback.classic.AsyncAppender"> <!-- 打开这个配置才能拿到调用类、方法、行号信息 --> <includeCallerData>true</includeCallerData> <queueSize>512</queueSize> <appender-ref ref="CONSOLE"/> <!-- 替换成你实际使用的输出appender --> </appender>
- 如果你自己写了通用日志工具类、AOP切面统一打印日志,Logback默认只会跳过日志框架本身的栈帧,会把你写的封装类识别为调用类,这种情况要么直接在业务类中初始化Logger打印日志,要么自定义栈帧解析逻辑跳过你的封装类层级。
3. 最简可用pattern参考
不需要重复堆砌同类占位符,保留需要的字段即可:
<pattern>[%date{ISO8601}] [%level] [%thread] %C{0}.%M:%L - %msg MDC:{%mdc}%n</pattern>
生产环境注意事项
开启调用栈采集(也就是让%C/%M/%L正常输出)会让日志输出性能下降5~10倍,高并发高吞吐量的生产环境不建议开启。这类场景建议规范Logger初始化方式,统一用LoggerFactory.getLogger(当前类.class)初始化Logger,用%logger占位符输出类名,没有额外性能损耗,也能拿到正确的类名信息。
内容的提问来源于stack exchange,提问作者NiranSUS
相关产品推荐
相关产品推荐

