存档

文章标签 ‘log4j’

log4j日志不向父类传播的方法

2009年4月28日 没有评论

log4j的所有日志都有一个祖先,叫rootLogger,其他所有的logger都会继承他,其他的logger不仅会在自身设定的appender里打印,也会在从自身往前的所有继承链上传播,如果不想往继承链上传播,可设置additivity属性为false,默认是true:

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L – %m%n

log4j.rootLogger=info,stdout

log4j.additivity.SubLogger=false
log4j.logger.SubLogger=info,YAppender

Appender Additivity
The output of a log statement of logger C will go to all the appenders in C and its ancestors. This is the meaning of the term “appender additivity”.

However, if an ancestor of logger C, say P, has the additivity flag set to false, then C‘s output will be directed to all the appenders in C and it’s ancestors upto and including P but not the appenders in any of the ancestors of P.

Loggers have their additivity flag set to true by default.

分类: java 标签:

Log4j

2008年2月26日 没有评论

Log4j是用来记录日志的,项目中有用到,只是一直不太明白是如何配置的,最近花时间看了一下。

Log4j有三大组件:logger, appender and layout。这三个组件可以设置日志信息的类型、级别和格式。

一、Logger hierarchy

Loggers are named entities. Logger names are case-sensitive and they follow the hierarchical naming rule:

日志名称层次规则(Named Hierarchy)
若一个日志A的名称加’.'后是日志B名称的前缀,则称日志A是日志B的祖先。若日志A和日志B之间再无其他祖先日志,则称日志A是日志B的父日志。(A logger is said to be an ancestor of another logger if its name followed by a dot is a prefix of the descendant logger name. A logger is said to be a parent of a child logger if there are no ancestors between itself and the descendant logger.)

例如,名为”com.foo”的日志是名为”com.foo.bar”的日志的parent,类似的,”java”是”java.util”的parent,是”java.util.foo”的祖先。
根日志在整个层次的顶端,和其他日志相比,它有两个不同点:
1. 根日志一直存在
2. 不能通过名称获取,使用Logger.getRootLogger获取,其他日志使用Logger.getLogger获取,参数是日志名。

日志都有级别,如果一个日志没有级别,则从最近的拥有级别的祖先那里继承祖先的级别(If a given logger is not assigned a level, then it inherits one from its closest ancestor with an assigned level. )

日志级别继承规则(Level Inheritance)
日志C的级别与第一个在命名层次中级别非空的日志级别相同,从日志C开始,直至根日志。(The inherited level for a given logger C, is equal to the first non-null level in the logger hierarchy, starting at C and proceeding upwards in the hierarchy towards the root logger.)

为了确保每个日志都有级别,根节点必须有级别。
日志名称 赋值级别 最终级别
root Proot Proot
X Px Px
X.Y none Px
X.Y.Z Px.y.z Px.y.z

调用日志实例的debug,info,warn,error,fatal,log方法来记日志,这些方法决定了当前记录日志的级别,如c是一个日志实例,c.info(“…”)是级别为INFO的写日志请求。

如果一个写日志请求的级别大于或等于这个日志的级别,那么这个写日志请求enabled,否则disabled。

写日志请求enabled规则(Basic Selection Rule)
日志A的级别为q(无论自身的还是继承来的),在日志A上的一个写日志请求的级别为p,若p>=q,则说此写日志请求enabled。(A log request of level p in a logger with (either assigned or inherited, whichever is appropriate) level q, is enabled if p >= q.)

这条规则是log4j的核心,级别都是有顺序的,对于标准级别,DEBUG < INFO < WARN < ERROR < FATAL。(This rule is at the heart of log4j. It assumes that levels are ordered. For the standard levels, we have DEBUG < INFO < WARN < ERROR < FATAL.)

例子:

// get a logger instance named “com.foo”
Logger logger = Logger.getLogger(“com.foo”);
// Now set its level. Normally you do not need to set the
// level of a logger programmatically. This is usually done
// in configuration files.

logger.setLevel(Level.INFO);
Logger barlogger = Logger.getLogger(“com.foo.Bar”);

// This request is enabled, because WARN >= INFO.
logger.warn(“Low fuel level.”);

// This request is disabled, because DEBUG < INFO.
logger.debug(“Starting search for nearest gas station.”);

// The logger instance barlogger, named “com.foo.Bar”,
// will inherit its level from the logger named
// “com.foo” Thus, the following request is enabled
// because INFO >= INFO.
barlogger.info(“Located nearest gas station.”);

// This request is disabled, because DEBUG < INFO.
barlogger.debug(“Exiting gas station search”);

用同一个日志名称调用getLogger方法得到的是同一个logger object的reference.

例如,

   Logger x = Logger.getLogger("wombat");
   Logger y = Logger.getLogger("wombat");

x and y refer to exactly the same logger object.

因此,不同传递日志引用就可以在其他地方得到一个日志的引用。在生物继承里,总是先parents后children,log4j可以配置为任何顺序,父日志如果在子日志后实例化,它依然能被找到而且处于正确的命名层次中。

二、Appenders and Layouts

1.Log4j可以将写日志的请求打印到不同的目的地,一个目的地就是一个appender。

2.一个日志可以有多个appender

appender 叠加性(Appender Additivity)
日志C的会输出到所有C和C祖先的appender去,这就是appender 叠加性(The output of a log statement of logger C will go to all the appenders in C and its ancestors. This is the meaning of the term “appender additivity”.)

一 种例外,日志的C的祖先记为P,P将additivity位设为false,那么日志C输出到C和C的祖先一直到P(包括P)的appender里去,但 是不会输出到P祖先的appender里去。(However, if an ancestor of logger C, say P, has the additivity flag set to false, then C‘s output will be directed to all the appenders in C and it’s ancestors upto and including P but not the appenders in any of the ancestors of P.)

日志的additivity位默认为true(Loggers have their additivity flag set to true by default.)

例如:

Logger
Name
Added
Appenders
Additivity
Flag
Output Targets Comment
root A1 not applicable A1 root没有默认的appender
x A-x1, A-x2 true A1, A-x1, A-x2 Appenders of “x” and root.
x.y none true A1, A-x1, A-x2 Appenders of “x” and root.
x.y.z A-xyz1 true A1, A-x1, A-x2, A-xyz1 Appenders in “x.y.z”, “x” and root.
security A-sec false A-sec No appender accumulation since the additivity flag is set to false.
security.access none true A-sec Only appenders of “security” because the additivity flag in “security” is set to false.

通常不仅希望能够自定义输出的目的地,还希望自定义输出的格式,这个有appender的layout完成。layout负责格式化日志的格式以满足用户的愿望,appender负责将格式化好的日志输出到对应的目的地。

The PatternLayout, part of the standard log4j distribution, lets the user specify the output format according to conversion patterns similar to the C language printf function.
log4j.appender.appenderName.layout=org.apache.log4j.PatternLayout 配置日志信息的格式(布局)
Log4j提供的layout有以下几种:
org.apache.log4j.HTMLLayout(以HTML表格形式布局),
org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

log4j.appender. appenderName.layout.ConversionPattern=%d %p [%c] – <%m>%n 是设置打印格式格式化日志信息。
打印参数如下:
%m 输出代码中指定的消息
%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
%r 输出自应用启动到输出该log信息耗费的毫秒数
%c 输出所属的类目,通常就是所在类的全名
%t 输出产生该日志事件的线程名
%n 输出一个回车换行符,Windows平台为“\r\n”,Unix平台为“\n”
%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)

三、配置
log4j.rootCategory= [ level ] , appenderName, appenderName, … 是配置根Logger。

level 是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。Log4j建议只使用四个级别,优 先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定 义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来,默认日志级别是ERROR;appenderName就是指定 Appender组件,确定日志输出目的地。如上例:log4j.rootCategory=info, stdout, logfile 配置根Logger的级别是INFO,日志输出的目的地是stdout, logfile。
log4j.appender. appenderName =org.apache.log4j.ConsoleAppender是配置日志信息输出目的地Appender。
Log4j提供的appender有以下几种:
org.apache.log4j.ConsoleAppender(控制台),
org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

log4j.properties简单例子:

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

log4j.rootLogger=debug,stdout

#只输出名为”org.ft” logger及其子logger的级别为WARN的日志
log4j.logger.org.ft=warn
参考:

http://logging.apache.org/log4j/1.2/manual.html

http://www.javaeye.com/topic/153732

分类: 开发 标签: