- 浏览: 948407 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (423)
- mysql (37)
- hibernate (3)
- struts (9)
- spring (33)
- dom4j (2)
- junit (0)
- exception (1)
- 随笔杂谈 (12)
- google app engine (1)
- XMPP (1)
- OAuth安全授权 (1)
- 版本控制 (8)
- 心情感悟 (0)
- core java (19)
- log4j (7)
- jquery (12)
- javascript (10)
- 网站性能优化及工具 (11)
- 服务器架设配置等 (38)
- EXT (4)
- 正则表达式 (5)
- 日志统计分析 (2)
- htmlparse (4)
- httpclient (5)
- java随笔 (5)
- dhtmlxtree (1)
- freemarke (5)
- memcached (6)
- javamail (5)
- Linux命令 (10)
- 应用监控cpu web jdbc等 (4)
- jmagick (9)
- 第三方缓存策略 (9)
- ORM (2)
- hadoop (2)
- 大数据量处理 (8)
- 经典 (1)
- 权限设计 (1)
- andriod (1)
- mybatis (12)
- redis (24)
- 数据结构_算法 (5)
- 分布式系统 (1)
- php (1)
- 网络编程 (3)
- 服务器部署 (3)
- ios (2)
- IM (23)
- mina (1)
- 视讯和语音 (1)
- 代码生成 (1)
- 架构 (4)
- 建模工具 (1)
- oracle (4)
- solr (10)
- 构建工具 (7)
- html5 (1)
- nginx (5)
- css (1)
- 大数据-分布式 (2)
- 设计模式 (2)
- mq (2)
- jvm调优 (8)
- 并发编程 (2)
- 搜索引擎 (1)
- UML (2)
最新评论
-
天使建站:
jquery获取网页里多选框checkbox选中项的值的方法及 ...
JS jQuery分别获取选中的复选框值 -
abao1:
发现一个小问题 sortAndSave方法中的for循环 第二 ...
完整java实现外部排序 -
西巴拉古呀那:
Kafka分布式消息系统实战(与JavaScalaHadoop ...
消息系统kafka介绍 -
kafodaote:
Kafka分布式消息系统实战(与JavaScalaHadoop ...
消息系统kafka介绍 -
成大大的:
Kafka分布式消息系统实 ...
消息系统kafka介绍
一般使用Logger.getLogger(String name)取得logger,
LogManager.getLogger()---->getLoggerRepository().getLogger(name)
getLoggerRepsitory()函数返回一个LoggerRepository()对象,LoggerRepository是一个接口,
其实现者是Hierarahy
static public Logger getLogger(String name) { return LogManager.getLogger(name); }
- public static Logger getLogger(final String name) {
- // Delegate the actual manufacturing of the logger to the logger repository.
- return getLoggerRepository().getLogger(name);
- }
public static Logger getLogger(final String name) { // Delegate the actual manufacturing of the logger to the logger repository. return getLoggerRepository().getLogger(name); }
- static public LoggerRepository getLoggerRepository() {
- if (repositorySelector == null) {
- repositorySelector = new DefaultRepositorySelector(new NOPLoggerRepository());
- guard = null;
- LogLog.error("LogMananger.repositorySelector was null likely due to error in class reloading, using NOPLoggerRepository.");
- }
- return repositorySelector.getLoggerRepository();
- }
static public LoggerRepository getLoggerRepository() { if (repositorySelector == null) { repositorySelector = new DefaultRepositorySelector(new NOPLoggerRepository()); guard = null; LogLog.error("LogMananger.repositorySelector was null likely due to error in class reloading, using NOPLoggerRepository."); } return repositorySelector.getLoggerRepository(); }
public LoggerRepository getLoggerRepository() { return repository; } }
下面是Hierarchy类getLogger方法
- public
- Logger getLogger(String name, LoggerFactory factory) {
- //System.out.println("getInstance("+name+") called.");
- CategoryKey key = new CategoryKey(name);
- // Synchronize to prevent write conflicts. Read conflicts (in
- // getChainedLevel method) are possible only if variable
- // assignments are non-atomic.
- Logger logger;
- synchronized(ht) {
- Object o = ht.get(key);
- if(o == null) {
- logger = factory.makeNewLoggerInstance(name);
- logger.setHierarchy(this);
- ht.put(key, logger);
- updateParents(logger);
- return logger;
- } else if(o instanceof Logger) {
- return (Logger) o;
- } else if (o instanceof ProvisionNode) {
- //System.out.println("("+name+") ht.get(this) returned ProvisionNode");
- [color=red]logger = factory.makeNewLoggerInstance(name);[/color]
- logger.setHierarchy(this);
- ht.put(key, logger);
- updateChildren((ProvisionNode) o, logger);
- updateParents(logger);
- return logger;
- }
- else {
- // It should be impossible to arrive here
- return null; // but let's keep the compiler happy.
- }
- }
- }
public Logger getLogger(String name, LoggerFactory factory) { //System.out.println("getInstance("+name+") called."); CategoryKey key = new CategoryKey(name); // Synchronize to prevent write conflicts. Read conflicts (in // getChainedLevel method) are possible only if variable // assignments are non-atomic. Logger logger; synchronized(ht) { Object o = ht.get(key); if(o == null) { logger = factory.makeNewLoggerInstance(name); logger.setHierarchy(this); ht.put(key, logger); updateParents(logger); return logger; } else if(o instanceof Logger) { return (Logger) o; } else if (o instanceof ProvisionNode) { //System.out.println("("+name+") ht.get(this) returned ProvisionNode"); [color=red]logger = factory.makeNewLoggerInstance(name);[/color] logger.setHierarchy(this); ht.put(key, logger); updateChildren((ProvisionNode) o, logger); updateParents(logger); return logger; } else { // It should be impossible to arrive here return null; // but let's keep the compiler happy. } } }
下面是找到一篇非常好的文章~因为还没有概览到这个程度所以只能转载了
一、Log4j中Logger的层次结构
Log4j中的Logger是以一个双向树的结构来组织的,但是Log4j却不是用通常使用的叶子结点和树枝结点来组织的。Log4j中使用了虚拟结点(ProvisionNode)和Logger(Logger)结点两种组织树的结构。
用户真正创建的Logger结点用真正的Logger结点表示,而Logger结点的祖先却可能不是真正的Logger,为了提升Log4j的效率这里用一个简单的Vector来代替。
ProvisionNode继承至Vector,并提供了一个接受一个Logger的构造方法。在Log4j的层次结构中仅仅是一个站位符。注意:ProvisionNode保存所有子Logger的实例。
如果一个Logger的父Logger为虚拟结点(ProvisionNode),则其父Logger为RootLogger。
二、Log4j中层次结构的作用
1、使每一个层次中确定的结点只有一个Logger实例,减少Logger的内存消耗。
2、使层次底层的Logger可以基层其祖先的等级。不用每个Logger都设置等级,并在底层Logger没有设置等级的情况下,可以一次性从祖先Logger中直接将Logger关闭(将祖先Logger的等级设为OFF)。
实现方法:从自己开始向祖先方法访问各Logger的等级,直到访问到一个不为空的。如果父Logger为虚拟结点(ProvisionNode),则其父Logger为RootLogger。
3、使层次底层的Logger可以基层其祖先的Appender。不用每个Logger都设置Appender,并在底层Logger没有设置Appender的情况下,可以一次性从祖先Logger中直接将更换Logger的Appender。
实现方法:从自己开始向祖先方法访问各Logger的Appenders。如果继承属性(additive)为false,则在调用了自己所有的Appender后,就直接跳出循环。
4、
三、Log4j中Logger的创建
1、所有Logger的创建最总都会发送到接口LoggerRepository的getLogger()方法中。Log4j中对此接口的实现是Hierarchy。Hierarchy中提供的创建过程如下:
2、判断在Logger容器中是否已经存在此名称的Logger。可能有如下三种情况
1)、不存在,已用工厂方法创建一个新Logger,设置Logger的repository属性,将Logger放入Logger容器中,调用updateParents()方法更新Logger的层次结构。
2)、存在且类型为Logger,直接返回该Logger。
3)、存在且类型为ProvisionNode,设置Logger的repository属性,将Logger放入Logger容器中,调用updateChildren()方法和updateParents()方法更新Logger的层次结构。
3、updateParents(Logger)方法。更新父Logger的层次结构。
尝试取得祖先Logger的实例,可能存在如下情况
1)、如果父Logger存在,且类型为Logger,则设置为本Logger的父Logger。跳出循环。
2)、如果父Logger存在,且类型为ProvisionNode,则将本Logger添加到ProvisionNode中,然后继续循环。
3)、如果父Logger不存在,就创建相应的ProvisionNode,则将本Logger添加到ProvisionNode中,然后继续循环。
注意:当时2、3情况时继续循环非常重要,这是维系Logger等级的一个重要方法。这样的结果是“ProvisionNode保存所有子Logger的实例。”
4、updateChildren(ProvisionNode,Logger)方法。
遍历ProvisionNode中所有的Logger,将所有没有正常连接到自己真正的父Logger上的Logger的父Logger设置为新建的用以替代ProvisionNode的Logger。
5、
四、Log4j中Log层次总揽
1、如果一个Logger的所有父Logger类型为Logger:本Logger的父Logger直接指向父Logger。
2、如果一个Logger的所有父Logger类型为ProvisionNode:本Logger的父Logger指向RootLogger。
3、如果一个Logger的父Logger类型为ProvisionNode,但是祖先Logger中存在Logger。本Logger的父Logger指向所有祖先中最近的一个Logger。
五、Log4j中Log的打印过程
以Info()方法解析Log的打印过程。使用ConsoleAppender和PatternLayout。
1、首先调用LoggerRepository接口的isDisabled()方法,通过和设置的Threshold等级比较,判断本层次的Log等级(在Info()方法中是Level.INFO_INT)能否打印。如果不可以就直接退出。
2、调用getEffectiveLevel()方法遍历Logger的等级结构,找出本Logger的等级。并和本层次的Log等级(在Info()方法中是Level.INFO)比较,判断本Logger能否打印这个层次的Log。如果可以打印就调用forcedLog()方法。forcedLog()方法通过传入得参数生成一个LoggingEvent实例,然后调用callAppenders()方法。
3、callAppenders(LoggingEvent)方法通过AppenderAttachableImpl类,先遍历本Logger中所有的Appender并调用相应的doAppend()方法。如果本Logger关闭了继承开关,就直接退出循环,否则依次遍历所有祖先的Appender。最后判断写Log的次数,如果等于0就打印没有Appender错误履历。
4、AppenderAttachableImlp类实现了AppenderAttachable接口,并提供了一个Appender的聚集,和遍历聚集的方法appendLoopOnAppenders(LoggingEvent)。通过调用该方法可以以LoggingEvent为参数调用聚集中所有的Appender的doAppend方法打印履历。
5、ConsoleAppender的doAppend()方法的实现在其祖先类AppenderSkeleton上,在doAppend()方法中,首先判断Appender是否已经关闭,如果已经关闭就打印一条错误履历并返回。然后比较Appender的Threshold等级,如果不通过就直接返回。调用Filter对象进行Log过滤。如果不通过就直接放回。然后调用append()方法。
6、append()方法在ConsoleAppender的父类WriterAppender类中实现,它调用了本地的两个方法,checkEntryCoditions()判断Appender是否关闭,是否有Layout,输出的字符串是否为空。subAppned()方法实现真正的打印。
7、subAppend()方法首先调用Layout格式化输出字符串,然后输出。在判断Layout是否忽略Throwable,如果不忽略掉用event.getThrowableStrRep()方法获取堆栈信息,然后答应。最后判断Appender是否要立即刷新输入,如果是就刷新输出。
8、Over,结束一次完整的Log打印过程。不过怎么少了解释器的调用????
9、原来,还有Layout没有看。在PatternLayout类的format()方法中,PatternLayout类会将LoggingEvent交给PatternConverter抽象类的format()方法来处理。这个抽象类的format方法中,调用了抽象方法convert(),这个方法最简单的实现时在PatternParser.java的BasicPatternConverter类中。在BasicPatternConverter的convert方法的末尾调用了LoggingEvent的getRenderedMessage()方法,看名字就知道了,在这里进行对象的解释。
10、在LoggingEvent.getRenderedMessage()方法中,首先判断message是否是个字符串,如果是就直接返回String,如果不是就判断Logger的容器是否实现了RendererSupport接口。如果Logger容器实现了RendererSupport接口,就调用接口的getRendererMap()方法获取Renderer的一个聚集RendererMap,并调用他的findAndRender()方法。
11、RendererMap中的findAndRender()方法中,用message的class对象去掉用get()方法,以获取也这个类对应的Renderer。get()方法会从下向上依次查找RendererMap中是否有对应的Renderer,如果有就直接退出,否则返回defaultRenderer实例(调用对象的toString()方法)。
12、获取Renderer实例后,根据“面对抽象编程,而不面对实现编程。”显然我们使用ObjectRenderer接口,调用方法doRender(),解析对象,并返回一个String对象。
13、over!
13点为转载内容,其中似乎有几个错别字,基层?继承?
有个问题,在"写"这篇文章时候突然明白了,使用provisionNode的好处,例如:
x.y.z
我们这里假设xweirootlogger下面的一个子节点,x.y是一个不存在的节点。
这样我们创建x.y.z时候,如果不使用provisionNode节点,我们一个比较好的方法是把其挂在
在x的下面,然而这样做的缺点是,当我有一天要使用x.y时候,我要创建x.y。这个时候情况
会怎样,x.y.z和x.y同级了。
发表评论
-
java日志处理组件log4j--log4j.xml配置详解
2013-05-14 18:06 4083<!-- log4j 系统日志--> 注:本资 ... -
Log4j日志配置
2012-12-17 10:23 1012LOG4J的配置之简单使它遍及于越来越多的应用中了:Log4J ... -
log4j配置信息详情
2011-01-21 15:45 1238一、前言: log4 ... -
log4j配置
2010-01-16 11:37 17941.基本参数解释: ⑴全局配制 log4j.rootL ... -
Log4j的简单入门
2009-04-28 12:34 1231Log4j实在是很熟悉,几乎所有的Java项目都用它啊。但是我 ... -
使用Log4j进行日志记录
2009-04-27 17:38 1541发布日期:2006年07月30日,更新日期:2006年07月3 ...
相关推荐
Log4j是一个开源的日志组件,由Ceki Gülcü于20世纪90年代末创建。它的主要目标是提供一个灵活、高性能的日志记录框架,使得开发者能够轻松地控制日志信息的输出级别、格式和目的地。Log4j不仅支持标准输出,如...
接下来,你需要创建Log4j的配置文件`log4j.properties`。这个文件通常放在`src/main/resources`目录下,内容如下: ```properties log4j.rootLogger=WARN, stdout log4j.appender.stdout=org.apache.log4j....
首先,我们需要在项目的类路径下创建一个名为`log4j.properties`或`log4j.xml`的配置文件。这里以`log4j.properties`为例,介绍其基本结构和配置选项: 1. **配置日志级别**:日志级别定义了日志信息的严重程度,...
要在项目中使用Log4j,首先需要将`log4j.jar`添加到项目的类路径中,然后创建或引用`log4j.xml`配置文件。在代码中,通过以下方式创建和使用Logger: ```java import org.apache.log4j.Logger; public class ...
2. **配置Log4j**:在项目的类路径下创建`log4j.properties`或`log4j.xml`配置文件,指定日志级别、输出目的地等。例如: ```properties # log4j.properties log4j.rootLogger=DEBUG, stdout log4j.appender....
这个压缩包“log4j.jar.rar”包含的是Log4j的核心库文件“log4j.jar”,这是一个Java Archive (JAR) 文件,用于封装和分发Java类、资源以及元数据。Log4j的目的是提供一种灵活且高性能的方式来处理应用程序中的日志...
我们可以创建一个定制的PrintStream类,重写`print()`和`println()`方法,将调用转发给Log4j的Logger。下面是一个简单的实现: ```java public class Log4jPrintStream extends PrintStream { private Logger ...
2. **配置文件**:创建`log4j.properties`或`log4j.xml`文件,定义日志级别和输出目的地。例如: ```properties # log4j.properties 示例 log4j.rootLogger=DEBUG, stdout, file log4j.appender.stdout=org.apache....
Log4j主要包括三个核心组件:Logger(日志器)、Appender(输出端)和Layout(格式化器)。 - **Logger**: 负责生成日志信息,是日志操作的入口。根据严重性级别(如DEBUG、INFO、WARN、ERROR、FATAL),Logger可以...
- **定义日志文件Appender**:如`log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender`,每天创建新的日志文件。 - **文件Appender属性**:`log4j.appender.FILE.File=logs/app.log`,指定日志文件的...
log4j的使用习惯,让每个类都拥有一个private static的...注意:在一个项目中,log4j环境只需要被配置一次,而不是在每个使用了logger的类里都需要调用一次 ,用MyClass.class作为参数创建该类的静态Logger对象 。
标题提及的是"log4j-API-最新稳定版本log4j-1.2.17",这表明我们关注的是日志框架Log4j的一个特定版本,即1.2.17。Log4j是Apache软件基金会开发的一个用于Java应用程序的日志记录工具,它提供了灵活的日志记录功能,...
Root Logger是Log4j中的一种特殊的logger,定义了根日志输出器。Root Logger可以定义自己的日志级别和输出目的地,并且可以继承父logger的属性。 Level Level是Log4j中的一种日志级别,包括ALL、DEBUG、INFO、WARN...
7. **自定义Logger**: 如果标准的Logger不能满足需求,可以通过继承`org.apache.log4j.Logger`并覆写相关方法来创建自定义Logger。 8. **MDC (Mapped Diagnostic Context)** 和 **NDC (Nested Diagnostic Context)*...
2. **配置文件**:创建log4j.properties或log4j.xml配置文件,设置日志级别、Appender、Layout和Filter。 3. **编程接口**:在代码中使用Logger接口创建并初始化logger对象,然后调用相应的方法(如debug(), info()...
4. **创建 log4j.properties 文件**:在 `WEB-INF/classes` 目录下创建 `log4j.properties` 文件,并指定日志的级别、输出目的地等。 ```properties log4j.rootLogger=DEBUG, A1 log4j.appender.A1=org.apache....
虽然Log4j非常流行,但随着技术的发展,出现了许多其他优秀的日志框架,如Logback(由Log4j的作者创建,更高效、更灵活)、SLF4J(Simple Logging Facade for Java,作为日志API,可与其他日志框架集成)。...
1. **配置文件**:在项目中,首先需要创建一个配置文件,例如`log4j.properties`,设置日志级别、Appender和Layout。例如: ``` log4j.rootLogger=DEBUG, FILE log4j.appender.FILE=org.apache.log4j....
- **Logger**: 日志记录器,是Log4j的核心组件,负责实际的日志输出。你可以为每个功能模块创建一个独立的Logger,以便区分日志来源。 - **Appender**: 输出目的地,用于定义日志信息被发送到哪里,如控制台、文件...
log4j.rootLogger=DEBUG, FILE log4j.appender.FILE=org.apache.log4j.FileAppender log4j.appender.FILE.File=/path/to/logfile.log log4j.appender.FILE.layout=org.apache.log4j.PatternLayout log4j.appender....