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
相关推荐
本文将深入探讨“日志4j(Log4j)、SLF4J(Simple Logging Facade for Java)和logback 1.3.0”这三者之间的关系以及它们在Java应用中的作用。 首先,Log4j是Apache软件基金会开发的一个流行的日志记录框架,它允许...
SLF4J(Simple Logging Facade for Java)是一个日志门面,它为各种日志框架提供了统一的接口,如Log4j、Logback等。它的主要目的是让开发者能够在部署时自由选择所需的日志实现,而无需修改代码。SLF4J通过引入`...
总结,SLF4J和Log4j的组合使用让日志管理更加灵活,开发者可以通过SLF4J的简洁API进行日志记录,同时利用Log4j的强大功能,如自定义输出格式和多种输出目的地。通过适当的配置和测试,我们可以确保日志系统按照预期...
总结来说,SLF4J+Logback是现代Java项目中的首选日志解决方案,因为它们提供了一种灵活、高性能的日志记录机制。然而,理解不同日志框架之间的差异和应用场景,可以帮助开发者根据项目需求做出最佳选择。在实际工作...
本文将深入探讨三个重要的Java日志框架——Log4j、Logback和SLF4J,并分析它们之间的关系和使用场景。 **Log4j** Log4j是Apache组织的一个开源项目,是Java世界中最先广泛使用的日志记录框架之一。它的核心功能...
总结一下,这个压缩包提供了Log4j 2和SLF4J的核心组件,允许开发者利用SLF4J的简单接口和Log4j 2的强大功能。通过SLF4J的绑定实现,可以在保持代码与日志实现解耦的同时,享受到Log4j 2的高效和灵活。在实际项目中,...
1. 兼容性强:Slf4j可以与多种日志系统集成,如Log4j、Logback、Java Util Logging等。 2. 灵活性强:Slf4j提供了统一的日志接口,使得用户可以选择不同的日志实现。 3. 高性能:Slf4j可以在高并发情况下提供高性能...
总结,Log4j-SLF4J-Impl结合了SLF4J的灵活性和Log4j的强大功能,为Java开发者提供了高效且可扩展的日志解决方案。了解并熟练掌握这一组件,能显著提升开发效率,同时也有助于构建更稳定、易维护的应用系统。
Logback是由log4j的创始人Ceki Gülcü设计的,它旨在提高性能并解决log4j的一些问题。Logback被认为是目前Java中最高效的日志框架之一,不仅速度快,而且功能强大,包括自定义日志级别、日志输出格式、归档策略等。...
SLF4J是一个日志门面,它提供了一个统一的接口,允许开发人员在运行时插入所需的日志框架,如Logback、Log4j或Java内置的日志系统。Logback则是SLF4J的一个实现,它高效且功能强大,被许多开发者视为替代Log4j的首选...
SLF4J允许您选择任何支持的底层日志库,如Logback、Log4j、Java Util Logging等。在实际项目中,SLF4J与Logback的组合被广泛使用,因为Logback被认为是性能优秀且功能丰富的日志实现。 首先,我们需要理解SLF4J的...
SLF4J是一个日志门面,它提供了一个统一的接口,允许开发人员在运行时插入所需的日志框架,如Logback、Log4j或Java Util Logging。而Logback是SLF4J的一个实现,由同一作者Ceki Gülcü创建,它以高效和可配置性著称...
Slf4j(Simple Logging Facade for Java)是一个日志门面,它提供了一个统一的API,允许开发者选择合适的日志框架,如Logback、Log4j等,而无需修改代码。Slf4j的主要目标是为各种日志框架提供一个简单统一的接口,...
- **log4j-over-slf4j.jar**:用于替换Log4J,需要注意的是,原有的`log4j.properties`配置文件将不再有效,需要转换为`logback.xml`。 - **jul-to-slf4j.jar**:用于替换JDK自带的日志系统,需要在程序启动时调用`...
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
在使用SLF4J和Log4j12时,你需要注意的一点是,由于Log4j1.2相比Log4j2在某些方面可能较旧,例如性能和功能更新,因此在新项目中,你可能会考虑使用更新的SLF4J绑定器,如slf4j-log4j2,以便利用Log4j2的改进特性。...
- `logback-classic`:提供了与Log4j兼容的API,是SLF4J绑定的主要实现。 - `logback-access`:提供了与Servlet容器集成的功能,用于HTTP访问日志。 **配置文件**: - **`logback.xml`**:是Logback的主要配置...
描述中提到的是`slf4j-log4j`,这通常是指SLF4J的Log4j绑定包,它提供了SLF4J到Log4j的桥接,使得SLF4J调用能够被Log4j接收并处理。在项目中,你需要将这两个jar包加入到类路径中,同时配置Log4j的配置文件,以指定...
SLF4J(Simple Logging Facade for Java)是一个日志门面,它为各种日志框架提供一个统一的接口,如Logback、Log4j、Java Util Logging等。它的主要目标是使日志库与应用程序解耦,让开发者能够在不修改代码的情况...
这个压缩包“log4j_slf4j.jar”包含了SLF4J接口以及与Log4j相关的实现,Log4j是一个广泛使用的日志记录库,提供了丰富的日志处理功能。 SLF4J的主要目标是为不同的日志框架提供一个统一的API,使得开发者可以在不...