ls4j初始化过程参考:logback如何发现configuration file
今天使用logback遇到一个问题:NND已经使用了logback.xml但log4j还是会提示警告
2013-12-10 17:48:56 [INFO] com.taobao.hsf.tlog.proxy.gather.impl.ProxyAgentGather - ProxyAgentGather process jobs : 0, time cost : 0 ms log4j:WARN No appenders could be found for logger (org.apache.commons.httpclient.HttpClient). log4j:WARN Please initialize the log4j system properly.
我的logback配置
<?xml version="1.0" encoding="UTF-8"?> <!-- Logback Configuration. --> <configuration debug="false"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss} [%p] %c - %m%n</pattern> </encoder> </appender> <root> <level value="INFO" /> <appender-ref ref="STDOUT" /> </root> </configuration>
我完美的想法是logback作为最牛逼的日志组件,应该把之前的log4j等实现接管过来吧,怎么没有呢?我debug了一下,首先从出现警告的HttpClient开始,使用的是apache-commons-logging。其实只要搞懂这样代码做了什么事情,对日志系统就理解了。
private static final Log LOG = LogFactory.getLog(HttpClient.class);
首先这行代码在commons-logging内部实际执行的是:
getFactory().getInstance(clazz)
问题1,commong-logging如何查找LogFactory?
我就不翻译了,请看官方代码注释,5种情况写得很清楚明白:
Construct and return a LogFactory instance, using the following ordered lookup procedure to determine the name of the implementation class to be loaded.
1.The org.apache.commons.logging.LogFactory system property.
2.The JDK 1.3 Service Discovery mechanism
3.Use the properties file commons-logging.properties file, if found in the class path of this class. The configuration file is in standard
4.java.util.Properties format and contains the fully qualified name of the implementation class with the key being the system property defined above.(org.apache.commons.logging.LogFactory)
5.Fall back to a default implementation class (org.apache.commons.logging.impl.LogFactoryImpl).
NOTE - If the properties file method of identifying the LogFactory implementation class is utilized, all of the properties defined in this file will be set as configuration attributes on the corresponding LogFactory instance.
NOTE - In a multithreaded environment it is possible that two different instances will be returned for the same classloader environment.
在我的情况下会执行到最后一种情况,也就是使用org.apache.commons.logging.impl.LogFactoryImpl。
问题2,logFactory如何创建logger?
LogFactoryImpl的调用栈如下:
- LogFactoryImpl.getInstance(Class clazz)
- LogFactoryImpl.getInstance(String name)
- LogFactoryImpl.newInstance(String name)
- LogFactoryImpl.discoverLogImplementation(String logCategory)
最后实现的时候按照一下顺序尝试创建Class,如果成功则返回:
- org.apache.commons.logging.impl.Log4JLogger
- org.apache.commons.logging.impl.Jdk14Logger
- org.apache.commons.logging.impl.Jdk13LumberjackLogger
- org.apache.commons.logging.impl.SimpleLog
Log4JLogger是一个代理类,其构造函数如下:
public Log4JLogger(String name) { this.name = name; this.logger = getLogger(); } public Logger getLogger() { if (logger == null) { logger = Logger.getLogger(name); } return (this.logger); }可以看到实际使用的org.apache.log4j.Logger.getLogger(name)来创建logger。由于我们的环境有log4j包,所以在我们的环境中第一个Log4j的Logger会创建成功。log4j logger创建之后会自动检测,如果没有发现log4j.properties等配置信息就会提示警告。
所以得出一个结论,出现问题是因为apache-common-logging不会自动发现logback。
问题3,logback和log4j如何桥接
既然apache-common-logging不能发现logback,那log4j和logback如何桥接呢?slf4j官方当然考虑到这个问题,参考官方文档:http://logback.qos.ch/bridge.html
使用log4j-over-slf4j,相当于ACL-->log4j-->slf4j-->logback打通。中间的log4j到slf4j,通过log4j-over-slf4j进行桥接。那么log4j-over-slf4j实际上如何桥接的呢?答案是直接在slf4j中定义同名的log4j的Logger包。这个问题参考:log4j-over-slf4的log4j Loger加载问题
问题4,slf4j存在的价值?
一个很实际的问题是为啥要搞掉JCL? 引入slf4j的成本还是很高的,这篇文章有回答:
http://articles.qos.ch/classloader.html
http://articles.qos.ch/thinkAgain.html
总结,混乱的各种日志组合情况
- slf4j-log4j-<version>.jar: 上层是SLF4J,底层通过log4j实现。
- slf4j-jcl-<version>.jar: 上层是SLF4J,底层还是通过Commons Logging的动态查找机制。
- jcl-over-slf4j-<version>.jar:上层是Commons Logging,底层交给SLF4J提供的静态绑定机制查找真正的日志实现框架。(注意:slf4j-jcl和jcl-over-slf4j不能同时出现在classpath)
- log4j-over-slf4j-<version>.jar: 上层是Log4J,底层交给SLF4J静态绑定要真正实现日志打印的框架。
各种冲突情况总结:
- slf4j-log4j,slf4j-simple不能同时出现,两个jar包都有sl4j的StaticLoggerBindder会冲突。
- log4j-over-slf4j和log4j不能同时出现,两个jar包都有org.apache.log4j.Logger会冲突。
- 同理,jcl-over-slf4j和common-loggng不能同时出现。
- slf4j-jcl和jcl-over-slf4j不能同时出现,逻辑上进入无限递归。
各种日志方案
1.使用slf4j-log4j12+log4j
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.6</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
ps:不用依赖slf4j-api, slf4j-log4j12会自动依赖slf4j-api。
2.使用log4j-over-slf4j+logback
<dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.0.11</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>log4j-over-slf4j</artifactId> <version>1.7.4</version> </dependency>
ps:不用依赖slf4j-api, logback-classic和log4j-over-slf4j都会自动依赖slf4j-api。
[INFO] +- ch.qos.logback:logback-classic:jar:1.0.11:compile
[INFO] | +- ch.qos.logback:logback-core:jar:1.0.11:compile
[INFO] | \- org.slf4j:slf4j-api:jar:1.6.4:compile (version managed from 1.7.4)
[INFO] +- org.slf4j:log4j-over-slf4j:jar:1.7.4:compile
[INFO] | \- org.slf4j:slf4j-api:jar:1.6.4:compile (version managed from 1.7.4)
log4j的体系结构
log4j主要由logger,appender,layout构成:
appender在log系统中的含义是定义输出日志的策略,常用的包括:
- ConsoleAppender
- DailyRollingFileAppender
- RollingFileAppender
- RandomAccessFileAppender(FastFileAppender)
关于log4j的架构可以参考:http://logging.apache.org/log4j/2.x/manual/architecture.html
配置可以参考:http://logging.apache.org/log4j/1.2/manual.html#Configuration
参考
桥接方案可以参考这篇文章:http://ihyperwin.iteye.com/blog/1455596
相关推荐
log4j-slf4j+logback1.3.0 共六个jar包
janino-2.3.17.jar jcl-over-slf4j-1.6.1.jar log4j-1.2.8.jar logback-access-0.9.24.jar logback-classic-0.9.24.jar logback-core-0.9.24.jar ... slf4j-1.6.1+logback-0.9.24.rar slf4j-api-1.6.1.jar
NULL 博文链接:https://tristan-s.iteye.com/blog/1966020
commons-logging-1.2.jar、log4j-1.2.17.jar、logback-classic-1.1.2.jar、logback-core-1.1.2.jar、slf4j-api-1.7.12.jar、slf4j-jcl-1.7.12.jar、slf4j-simple-1.7.12.jar
Logback 实例,log4,slf4,logback日志输出 demo.通过配置即可指定日志信息的存储位置。
无论从设计上还是实现上,Logback相对log4j而言有了相对多的改进。所以下面这篇文章主要给大家介绍了关于如何将应用的log4j换成logback的相关资料,文中介绍的很详细,需要的朋友可以参考下。
NULL 博文链接:https://wwwzhouhui.iteye.com/blog/391950
SLF4J结合logback已经逐步替代了Log4j,带来了更好的性能和灵活性。
日志框架与日志门面的区别 日志框架技术 JUL 使用 Log4j 组件 使用 Logback 由Log4j之父做的另一个开源项目,业界中称作logj后浪,一个可靠、同样且灵活的java日志框架。 Logback组件 ...SLF4j 使用
日历客户端 dioCalendar 项目的客户端。 研究日志框架(log4j、slf4j、logback)+Maven和通用接口... 包含从 log4j -> log4j 和 log4j -> slf4j -> logback 方案进行日志记录的 SimpleLogging 和 NewLogging 两个模块。
包含log4j-over-slf4j-1.7.7、logback-classic-1.1.3、logback-core-1.1.3、Flink使用logback须知、自己目前使用的一份logback.xml
用于集成以下框架工具的示例项目Gradle to Build and Dependency Control MyIbatis as ORM for Mapping & Persistence JDBC Driver for PostgreSQL Junit For Some Unite Test Log4J 或 logback 或 SLF4J for LOGGIN...
Logback是由log4j创始人设计的另一个开源日志组件,基于slf4j的日志规范实现的框架,性能比log4j要好。 Logback主要分为三个技术模块: logback-core:该模块为其他两个模块奠定了基础。 logback-classic:是log4j...
国内可能打不开官网,所以在这里转载,...此外logback-classic完整实现SLF4J API使你可以很方便地更换成其它日志系统如log4j或JDK14 Logging。logback-access访问模块与Servlet容器集成提供通过Http来访问日志的功能。
快速了解常用日志技术(JCL、Slf4j、JUL、Log4j、Logback、Log4j2)-附件资源
java.util.logging, logback, log4j) allowing the end user to plug in the desired logging framework at deployment time. Note that SLF4J-enabling your library implies the addition of only a single ...
要引入logback,由于Logback-classic依赖slf4j-api.jar和logback-core.jar,所以要把slf4j-api.jar、logback-core.jar、logback-classic.jar,添加到要引入Logbac日志管理的项目的class path中.
spring-log 为 Spring 项目提供了额外的和支持: 记录器自动注入webapp、独立和测试环境中的自定义配置请参阅。二进制文件在哪里? 从 1.0.4 开始,您可以在 maven central 中找到二进制文件: < dependency>< ...
logback-classic:它是log4j的一个改良版本,同时它完整实现了slf4j API使你可以很方便地更换成其它日志系统如log4j或JDK14 Logging。() logback-access:访问模块与Servlet容器集成提供通过Http来访问日志的功能。...