本文主要讲述一个日志分级应用的模型和如何利以及扩展Log4J来达到目的,关于Log4J的配置说明和基础应用就不再累述,详情可参见官方文档http://logging.apache.org/log4j/1.2/manual.html
另外3篇比较详细的博文:
首先我们来看一个模型:
Kernel和 Applications都运行于同一个JVM中,且Applications运行于Kernel之上。JVM启动时依次会创建Bootstrap ClassLoader, Extension ClassLoader和AppClassLoader,分别会去加载JRE/lib,JRE/lib/ext下的核心包和kernel以及相关依赖的classes,jars等,之后由kernel创建并加载各个application,整个过程和一般的java web服务器启动比较类似(如tomcat)。
自然而然就有了这样的日志分级需求:
-
Kernel的日志记录到kernel.log文件中
-
各个Application的日志分别记录到各自的文件中,如BBS的日志记录到bbs.log;Mails的日志记录到mails.log文件中
-
其它日志(所有非kernel和application中所关心的日志)记录到root.log中,以备不时之需
那么接下我们就要考虑log4j的配置问题了?——在这里我使用的配置文件是log4j.properties
-
log4j.properties文件的位置?
-
log4j.properties文件的内容?
对于问题1,从2个方面考虑:
-
kernel中有使用log4j,并且可以kernel独立,所以log4j.properties需要在kernel中存在
-
kernel并不知将来有多少applications,所以关于application日志的配置信息可以:
-
采用默认机制创建,即在kernel加载application时创建
-
在application中也加入log4j的配置信息,加载时读取
此外我们已经分析了整个模型的类加载机制,很显然log4j.jar也只会被kernel加载一次。看过log4j(1.2.16)源代码的同学都知道log4j的初始化是在静态块中进行的,也就是说log4j.properties只会被加载一次,那么对于application中的配置文件就需要我们自己用log4j提供的API在kernel加载application时进行初始化了。
有了问题1的分析,我们可以把模型稍微简化成下图后再来分析问题2
依然是要求app1包下的日志写到app1.log文件中,app2包下的日志写到app2.log文件中,kernel包下的日志写到kernel.log文件中,其余的日志则写到root.log文件中。
log4.properties则如下所示
运行得到了以下日志输出:
不同package下的日志输出到了不同的日志文件中,看起来目的达到了,不过还是存在问题——即便root的log级别设置为了error,但kernel和application中的info信息还是会被输出到root.log中。大家可以想一下这是为什么?
如何避免写到kernel或application中的日志重复被写到root中呢?——关键是org.apache.log4j.Category中的方法callAppenders
/**
Call the appenders in the hierrachy starting at
<code>this</code>. If no appenders could be found, emit a
warning.
<p>This method calls all the appenders inherited from the
hierarchy circumventing any evaluation of whether to log or not
to log the particular log request.
@param event the event to log. */
public
void callAppenders(LoggingEvent event) {
int writes = 0;
for(Category c = this; c != null; c=c.parent) {
// Protected against simultaneous call to addAppender, removeAppender,...
synchronized(c) {
if(c.aai != null) {
writes += c.aai.appendLoopOnAppenders(event);
}
if(!c.additive) {
break;
}
}
}
if(writes == 0) {
repository.emitNoAppenderWarning(this);
}
}
我们最终的目的就是阻止其输出日志后还继续上溯输出,因此需做如下修改:
if(c.aai != null) {
writes += c.aai.appendLoopOnAppenders(event);
break;
}
除了修改log4j其原生代码外,我们还可以通过继承和扩展的手段实现,下面便是所有实现代码。
- 扩展org.apache.log4j.Logger和DefaultLoggerFactory如下
package com.xxx.cases
public class DefaultLoggerFactory implements org.apache.log4j.spi.LoggerFactory {
public DefaultLoggerFactory() {
}
public Logger makeNewLoggerInstance(String name) {
return new Logger(name);
}
}
package com.xxx.cases;
import org.apache.log4j.Appender;
import org.apache.log4j.helpers.AppenderAttachableImpl;
import org.apache.log4j.spi.LoggingEvent;
public class Logger extends org.apache.log4j.Logger{
private static final DefaultLoggerFactory defaultFactory = new DefaultLoggerFactory();
private AppenderAttachableImpl aai;
protected Logger(String name) {
super(name);
}
@Override
public void callAppenders(LoggingEvent event) {
if (this.aai == null && !(this.getParent() instanceof Logger)) {
super.callAppenders(event);
} else {
int writes = 0;
for (Logger c = this; c != null; c = (Logger) c.getParent()) {
// Protected against simultaneous call to addAppender, removeAppender,...
synchronized (c) {
if (c.aai != null) {
writes += c.aai.appendLoopOnAppenders(event);
break;
}
if (!c.getAdditivity()) {
break;
}
}
}
if (writes == 0) {
repository.emitNoAppenderWarning(this);
}
}
}
public synchronized void addAppender(Appender newAppender) {
if (aai == null) {
aai = new AppenderAttachableImpl();
}
aai.addAppender(newAppender);
repository.fireAddAppenderEvent(this, newAppender);
}
public static Logger getLogger(Class clazz){
return (Logger)org.apache.log4j.Logger.getLogger(clazz.getName(), defaultFactory);
}
}
- 修改log4j.properties配置文件,增加loggerFactory配置项
package com.xxx.cases.kernel;
import com.xxx.cases.Logger;
public class KernelBean {
private static Logger logger = Logger.getLogger(KernelBean.class);
public void testMethod(){
logger.info("in kernel bean test method");
}
}
后记:经朋友提醒,还有一种更加简便的方式,只需要修改log4.properties配置信息——其目的和原理是一样的。
注意黄色高亮的部分。
——结束
- 大小: 44 KB
- 大小: 18.4 KB
- 大小: 34.1 KB
- 大小: 17 KB
- 大小: 2 KB
- 大小: 38.3 KB
分享到:
相关推荐
Log4j是一款广泛使用的日志记录框架,尤其在Java应用程序中。它允许开发者灵活地控制日志信息的输出,提供了一种分级的日志记录机制,便于调试、性能分析和问题排查。这个“log4j简单范例 日志文件是相对路径的”...
本话题将深入探讨"用到的两个log4j日志架包"——`android-logging-log4j-1.0.3.jar`和`log4j-1.2.15.jar`。 首先,`android-logging-log4j-1.0.3.jar`是专门为Android平台设计的日志库,它是Log4j的一个变种,使得...
- **复制 JAR 文件**:解压后,将 `jakarta-log4j-1.2.8\dist\lib` 目录下的 `log4j-1.2.8.jar` 文件复制到 Tomcat 的 `common\lib` 目录下或其他应用程序的 `lib` 盏录下。 - **配置 web.xml**:在应用的 `web.xml`...
【hibernate-log4j日志】专题详细解析 日志框架在软件开发中起着至关重要的作用,尤其是在Java世界中。本文将深入探讨Hibernate框架与Log4j的结合使用,帮助开发者更好地理解和运用日志功能。 **简介** 日志记录...
Log4J的实现原理是通过提供分级的日志记录方法,允许开发者在代码中嵌入日志记录语句,这些语句具有多种输出格式和多个输出级别。这与传统的在代码中插入`System.out.println`或其他输出语句的方式不同,后者往往...
Log4j是一款广泛应用于Java平台的日志记录框架,它提供了灵活且强大的日志记录功能,使得开发者能够方便地控制日志信息的输出级别、格式以及目的地。本实例将深入探讨Log4j的基本使用方法和配置。 一、Log4j的核心...
### log4j使用配置方法及项目中的应用 #### 概述与背景 在软件开发过程中,日志记录是一项至关...通过以上配置,Log4j能够按照预设规则高效、准确地记录和输出日志信息,极大提升了应用程序的可观测性和可维护性。
例如,你可以配置日志分级(DEBUG, INFO, WARN, ERROR等),并实现日志分片以方便日志管理和分析。 6. **测试和调试**:升级后,全面测试应用程序以确保所有功能正常工作。如果遇到错误,检查日志输出,这通常是...
这个“关于Log4j的Demo”是帮助开发者更好地理解和应用Log4j的一个实例。Log4j不仅提高了代码的可读性和可维护性,还允许开发者根据需要调整日志输出的级别,从而实现不同环境下的日志管理。 **Log4j的基本组件** ...
- **应用**:Log4J广泛应用于Java应用程序中,用于记录程序运行时的重要信息,以便于后续的问题定位、性能优化及审计等目的。 #### 3. 日志输出组件的设计思路 - **背景**:本文介绍的LogUtil组件是针对一款中型...
Log4j是Apache组织提供的一款开源日志框架,它具有高效、灵活、可扩展的特点,广泛应用于各种Java项目中,包括Mybatis这样的持久层框架。 ### 1. Log4j的基本组件 - **Logger**: 日志记录器是Log4j的核心组件,...
通常建议使用更稳定、经过充分测试的正式版本,比如`apache-log4j-2.0-beta3-bin`,它是Log4j 2.0的早期版本,带来了更多改进和新特性,如异步日志处理器、更丰富的日志级别(如TRACE)以及日志分级配置。...
log4j是Apache组织开发的一款开源日志记录工具,主要服务于Java应用程序。它的设计目标是提供一个灵活、高效的日志记录框架,允许开发者定制日志级别,选择不同的日志输出格式,甚至配置日志存储位置。log4j-1.2.17...
四、使用Log4j 在Java代码中,通过`Logger`类获取logger实例,然后调用相应的方法进行日志记录: ```java import org.apache.log4j.Logger; public class MyClass { private static final Logger logger = ...
以下是Log4j的核心组成部分、使用方法以及日志分级的详细解释。 1. **LOG4J组成**: - **Logger**:是Log4j的核心,负责决定哪些日志信息应该被记录和哪些应该被忽略。它根据预定义的级别来过滤日志,由`org....
5. **日志分级**:遵循日志级别的标准(TRACE、DEBUG、INFO、WARN、ERROR、FATAL、OFF),Log4j-core-2.5可以方便地控制不同级别日志的输出。 二、SLF4J接口的集成 SLF4J(Simple Logging Facade for Java)是一个...
Log4j是Java平台上广泛使用的日志记录框架,它的全称是Apache Log4j,它为应用程序提供了灵活的日志记录功能。在Java开发中,日志记录是非常关键的一部分,可以帮助开发者跟踪程序运行状态,定位错误,进行性能分析...
Log4j是Apache组织提供的一款开源的日志记录工具,广泛应用于Java开发中。它提供了灵活的日志记录功能,帮助开发者跟踪程序运行状态,调试问题,以及收集运行数据,对系统的监控和维护起着至关重要的作用。本手册将...
log4j 是一个广泛使用的 Java 日志框架,它提供了一种高效、灵活的方式来记录应用程序中的事件。这篇介绍旨在帮助初学者理解 log4j 的核心概念和使用方法。 **1. 简介** 日志记录在软件开发中扮演着重要角色,因为...
Log4j 2.0 Alpha2支持多种应用程序框架,如Spring、Struts等,并且与Log4j 1.x和Logback等其他日志框架具有良好的兼容性,方便迁移和集成。 **8. XML配置** 在"apache-log4j-2.0-alpha2-bin"压缩包中,包含的XML...