日志框架的兼容性
另一篇文档:https://my.oschina.net/pingpangkuangmo/blog/406618 。
日志facade:
编程的时候,对外提供的jar中应该只能引用日志的facade,目前常见的日志facade包有:
- log4j的日志api,log4j的api与log4j的实现在同一个包中;
- log4j2的日志api;
- JCL(Jakarta Common Log)(commons-logging),这个也只是一个api;
- slf4j(Simple Log Facade for Java) api;
日志实现系统。
这些包建议可以只在运行阶段引入(
- log4j的日志实现;
- log4j2的日志实现;
- slf4j 的具体实现是logback;
- JUL 的具体实现在JDK中;
日志接口桥接器(接口转换器):
所谓的桥接器就是一个假的日志实现工具, 目前最流行的日志facade是slf4j, 由于历史原因,一些三方包已经使用了其它的日志facade, 比如,早期Spring, Apache引用的都是commons-logging的facade,那为了兼容这些接口,则就有了日志接口桥接器,也即将这些接口通过代理,转发到slf4j接口上去。
日志实现适配器:
slf4j的直接实现是logback, slf4j为了使用log4j的实现(slf4j-log4j12),slf4j适配jdk 日志的实现(slf4j-jdk14)。
日志接口桥接器(将别人的日志接口桥接到自己的日志系统) 与 日志实现适配器(将自己的日志接口适配别人的日志接口或实现) 并没有严格的区分,这两者的使用并没有一个强制的规范,这里也是引用日志的包最容易出现问题的地方,很容易互相转换,造成死循环。比如,同时引入 log4j-over-slf4j.jar 与 slf4j-log4j12 就会有问题。
- log4j-over-slf4j 与 slf4j-log4j12 不能并存
- log4j-slf4j-impl 与 slf4j-log4j12 不能并存
- log4j-slf4j-impl 与 log4j-to-slf4j 不能并存
- log4j-jcl 与 jcl-over-slf4j 不能并存
- jcl-over-slf4j 与 commons-logging 不能并存
如何确定要使用哪些桥接器,重要的是看你使用哪个日志facade及哪个日志实现系统,并要兼容哪些日志接口。
基于目前最常见的搭配 slf4j+log4j, slf4j+log4j2, 下面给出这两种搭配的最佳实践:
- slf4j+log4j, 即自己的应用使用slf4j facade 并使用 lof4j日志实现系统;
- slf4j + log4j2 即自己的应用使用slf4j facade 并使用 lof4j2日志实现系统;
异常注意事项
- 异常被打印的地方(logger);
- 异常的类型:异常的内容(message);
- at 后面是异常的堆栈信息,从 异常产生的地方(new或jvm产生) 到 最初调用的地方;
- Caused by 顾名思义,真正发生问题的地方,最下面的是直接原因;
- 分清 异常产生的地方(new或jvm产生) 与 异常被打印的地方(logger);
- catch 异常后可以抛出一个新的异常,也可抛出原异常,还可忽略异常继续执行;异常设计(catch,new E)很重要,混乱的异常设计不利于问题排查;
日志注意事项
- 打印前一般会先判断级别是否合适;info日志一般是包含关键信息的字符串,格式化要借助String.format()函数;error日志要输出异常的堆栈信息;
- 日志的格式怎么:时间,级别,(线程),名称或者类,这四样是固定的,其他的想怎么打怎么打;
- 应用下日志的分类:中间件(rpc,health-check,tracelog),本应用各子模块日志;
logbakc日志框架要点
appender -指定日志文件名,日志格式,日志文件最大天数;
logger -指向代码中的日志name,或者日志class,需要ref上面的appender
root -指向代码中的其他日志(除去上面的指定)
springProfile -在指定的profile下才生效
log4j2 日志框架
RollingFile -指定日志文件名
AsyncLogger/Logger -指向代码中的日志name,或者日志class
Tracer
TraceId 不是rpc拦截器,是SofaRequest的一个属性传下去的。