分享

** Log4j的配置说明与使用原则

 niefeng2011 2014-02-27


一、Log4j简介与配置参数说明 

Log4j有三个主要的组件:Loggers(记录器),Appenders (输出源)和Layouts(布局)。这里可简单理解为日志类别,日志要输出的地方和日志以何种形式输出。综合使用这三个组件可以轻松地记录信息的类型和级别,并可以在运行时控制日志输出的样式和位置。 

1、Loggers 

Loggers组件在此系统中被分为五个级别:DEBUG、INFO、WARN、ERROR和FATAL。这五个级别是有顺序的,DEBUG < INFO < WARN < ERROR < FATAL,分别用来指定这条日志信息的重要程度,明白这一点很重要,Log4j有一个规则:只输出级别不低于设定级别的日志信息,假设Loggers级别设定为INFO,则INFO、WARN、ERROR和FATAL级别的日志信息都会输出,而级别比INFO低的DEBUG则不会输出。 

2、Appenders 

禁用和使用日志请求只是Log4j的基本功能,Log4j日志系统还提供许多强大的功能,比如允许把日志输出到不同的地方,如控制台(Console)、文件(Files)等,可以根据天数或者文件大小产生新的文件,可以以流的形式发送到其它地方等等。 

常使用的类如下: 

org.apache.log4j.ConsoleAppender(控制台) 
org.apache.log4j.FileAppender(文件) 
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件) 
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件) 
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方) 

配置模式: 
log4j.appender.appenderName = className 
log4j.appender.appenderName.Option1 = value1 

log4j.appender.appenderName.OptionN = valueN 

3、Layouts 

有时用户希望根据自己的喜好格式化自己的日志输出,Log4j可以在Appenders的后面附加Layouts来完成这个功能。Layouts提供四种日志输出样式,如根据HTML样式、自由指定样式、包含日志级别与信息的样式和包含日志时间、线程、类别等信息的样式。 

常使用的类如下: 

org.apache.log4j.HTMLLayout(以HTML表格形式布局) 
org.apache.log4j.PatternLayout(可以灵活地指定布局模式) 
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串) 
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等信息) 

配置模式: 

log4j.appender.appenderName.layout =className 
log4j.appender.appenderName.layout.Option1 = value1 
 
log4j.appender.appenderName.layout.OptionN = valueN 

二、配置详解 

在实际应用中,要使Log4j在系统中运行须事先设定配置文件。配置文件事实上也就是对Logger、Appender及Layout进行相应设定。 Log4j支持两种配置文件格式,一种是XML格式的文件,一种是properties属性文件。下面以properties属性文件为例介绍 log4j.properties的配置。 

1、配置根Logger: 
log4j.rootLogger = [ level ] , appenderName1, appenderName2, … 
log4j.additivity.org.apache=false:表示Logger不会在父Logger的appender里输出,默认为true。 
level :设定日志记录的最低级别,可设的值有OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定义的级别,Log4j建议只使用中间四个级别。通过在这里设定级别,您可以控制应用程序中相应级别的日志信息的开关,比如在这里设定了INFO级别,则应用程序中所有DEBUG级别的日志信息将不会被打印出来。 
appenderName:就是指定日志信息要输出到哪里。可以同时指定多个输出目的地,用逗号隔开。 
例如:log4j.rootLogger=INFO,A1,B2,C3 

2、配置日志信息输出目的地(appender): 
log4j.appender.appenderName = className 
appenderName:自定义appderName,在log4j.rootLogger设置中使用; 
className:可设值如下: 
(1)org.apache.log4j.ConsoleAppender(控制台) 
(2)org.apache.log4j.FileAppender(文件) 
(3)org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件) 
(4)org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件) 
(5)org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方) 

(1)ConsoleAppender选项: 
Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG。 
ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。 
Target=System.err:默认值是System.out。 

(2)FileAppender选项: 
Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG。 
ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。 
Append=false:true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是true。 
File=D:/logs/logging.log4j:指定消息输出到logging.log4j文件中。 

(3)DailyRollingFileAppender选项: 
Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG。 
ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。 
Append=false:true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是true。 
File=D:/logs/logging.log4j:指定当前消息输出到logging.log4j文件中。 
DatePattern='.'yyyy-MM:每月滚动一次日志文件,即每月产生一个新的日志文件。当前月的日志文件名为logging.log4j,前一个月的日志文件名为logging.log4j.yyyy-MM。 
另外,也可以指定按周、天、时、分等来滚动日志文件,对应的格式如下: 
1)'.'yyyy-MM:每月 
2)'.'yyyy-ww:每周 
3)'.'yyyy-MM-dd:每天 
4)'.'yyyy-MM-dd-a:每天两次 
5)'.'yyyy-MM-dd-HH:每小时 
6)'.'yyyy-MM-dd-HH-mm:每分钟 

(4)RollingFileAppender选项: 
Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG。 
ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。 
Append=false:true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是true。 
File=D:/logs/logging.log4j:指定消息输出到logging.log4j文件中。 
MaxFileSize=100KB:后缀可以是KB, MB 或者GB。在日志文件到达该大小时,将会自动滚动,即将原来的内容移到logging.log4j.1文件中。 
MaxBackupIndex=2:指定可以产生的滚动文件的最大数,例如,设为2则可以产生logging.log4j.1,logging.log4j.2两个滚动文件和一个logging.log4j文件。 

3、配置日志信息的输出格式(Layout): 
log4j.appender.appenderName.layout=className 
className:可设值如下: 
(1)org.apache.log4j.HTMLLayout(以HTML表格形式布局) 
(2)org.apache.log4j.PatternLayout(可以灵活地指定布局模式) 
(3)org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串) 
(4)org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息) 
(1)HTMLLayout选项: 
LocationInfo=true:输出java文件名称和行号,默认值是false。 
Title=My Logging: 默认值是Log4J Log Messages。 
(2)PatternLayout选项: 
ConversionPattern=%m%n:设定以怎样的格式显示消息。 
格式化符号说明: 
格式化符号说明例子
%p输出日志信息的优先级,即DEBUG,INFO,WARN
,ERROR,FATAL。
%d输出日志时间点的日期或时间,默认格式为ISO8601,
也可以在其后指定格式
如:%d{yyyy/MM/dd HH:mm:ss,SSS}
%r输出自应用程序启动到输出该log信息耗费的毫秒数
%t输出产生该日志事件的线程名
%l输出日志事件的发生位置,相当于%c.%M(%F:%L)的组合,包括类全名、方法、文件名以及在代码中的行数例如:com.buy360.restFul.AsTest.main(AsTest.java:10)
%c输出日志信息所属的类目,通常就是所在类的全名com.buy360.restFul.AsTest
%M输出产生日志信息的方法名
%F输出日志消息产生时所在的文件名称
%L输出代码中的行号
%m输出代码中指定的具体日志信息
%n输出一个回车换行符,Windows平台为"\r\n",Unix平台为"\n"
%x输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中

另外,还可以在%与格式字符之间加上修饰符来控制其最小长度、最大长度、和文本的对齐方式。如: 
1) c:指定输出category的名称,最小的长度是20,如果category的名称长度小于20的话,默认的情况下右对齐。 
2)%-20c:"-"号表示左对齐。 
3)%.30c:指定输出category的名称,最大的长度是30,如果category的名称长度大于30的话,就会将左边多出的字符截掉,但小于30的话也不会补空格。 
三、如何正确地输出日志。 
     1、理解正确的日志输出级别 
          很多程序员都忽略了日志输出级别, 甚至不知道如何指定日志的输出级别. 相对于System.out来说, 日志框架有两个最大的优点就是可以指定输出类别(category)和级别(level). 对于日志输出级别来说, 下面是我们应该记住的一些原则: 
 
ERROR系统发生了严重的错误, 必须马上进行处理, 否则系统将无法继续运行. 比如数据库不可用等
WARN系统能继续运行, 但是必须引起关注. 对于存在的问题一般可以分为两类: 一种系统存在明显的问题
(比如, 数据不可用), 另一种就是系统存在潜在的问题, 需要引起注意或者给出一些建议(比如, 系统运
行在安全模式或者访问当前系统的账号存在安全隐患). 总之就是系统仍然可用, 但是最好进行检查和调整.
INFO重要的业务逻辑处理完成. 在理想情况下, INFO的日志信息要能让高级用户和系统管理员理解, 并从日
志信息中能知道系统当前的运行状态. 比如
DEBUG主要用于调试、测试时使用,一般是在程序中不是非常重要的地方,这部分的日志较多,但是在线上运行
时我们一般会将日志级别设置为INFO,避免DEBUG日志过多影响性能.
TRACE系统详细信息, 主要给开发人员用, 一般来说, 如果是线上系统的话, 可以认为是临时输出, 而且随时可以
通过开关将其关闭. 有时候我们很难将DEBUG和TRACE区分开, 一般情况下, 如果是一个已经开发测试完
成的系统, 再往系统中添加日志输出, 那么应该设为TRACE级别

    2、日志的作用: 
        首先,它能在程序运行过程中精确的提供运行时的上下文(context)方便开发人员找到 BUG,一旦在程序中加入了Log 输出的代码,程序运行过程中就能自动的生成并输出logging信息。其次,log信息可以输出到不同的地方(控制台,文件,日志服务器等等)以备时候研究、统计。 
    3、日志的副作用: 
        降低应用性能(日志的输出必然会有字符串的创建、合并,然后输出到文件又必然会有IO的消耗,在一个100万次的循环中,输出日志和不输出日志的性能差距甚至可以达到100倍,千倍),增加代码的编写量,这个大家都懂的。 
    4、日志输出的原则: 
         Log4j建议只使用四个级别,优先级从高到低分别是 ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。
     (1)、对程序的输入输出要以DEBUG记录下来,常包括从文件、数据库、网络、用户等输入的信息,向文件、数据库、网络输出的信息。    
     (2)、对重要对象或程序状态的修改,要以INFO记录修改前的信息和修改后的状态。
     (3)、不能忽视每个调用错误,异常日志的内容要能清晰描述运行上下文,这样有助于排查错误,输出异常日志时, 第一个参数一定是一个字符串, 一般都是对问题的描述信息, 而不能是异常message(因为堆栈里面会有), 第二个参数才是具体的异常实例. ,例如:log.error("导入数据失败,错误信息为:", e); 
     (4)、记下打印信息时所在的文件名和函数名(必须能区分开重载函数),有行数最好。
     (5)、
 对于高并发系统,能不打印日志就不打印日志, 输出的 日志数量、 级别、内容都要经过评估,避免日志输出影响性能, ,可以采用初期上线时多打印一些日志,上线运行一段时间后,通过观察方法调用次数,响应性能来决定减少那些日志的打印或者改变打印日志的级别 
     (6)、对于异常日志的内容要能清晰描述运行上下文,这样有助于排查错误。
 

四、使用Log4j需要注意的地方 
     1、打印DEBUG日志时最好加上isDebugalbe()的判断,虽然Log4j不会输出debug的日志内容(日志级别是INFO),但是调用log.debug的时候必然会传参进去,对于参数又是字符串拼接的时候,对于方法调用次数特别大的场景下,对性能的影响是明显的,加上isDebugalbe()的判断,这样做会减少字段串的合并,理论上可以减少JVM的垃圾回收次数。 
    2、对于 日志内容, 通常应该包含当前时间、日志级别、线程名称、日志描述信息,也可以包含方法名,类名,行号(但是让log4j输出这些信息对性能是很有影响的),所以对于要求高性能的应用最好不要输出这些信息。 

五、Log4j按级别输出日志到不同的文件 

会按日存分割日志文件,并且根据级别输出到不同的文件

log4j.rootLogger=info,stdout,info,debug,error
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%-5p] [%d{HH:mm:ss}] %c - %m%n

log4j.logger.info=info
log4j.appender.info=org.apache.log4j.DailyRollingFileAppender
log4j.appender.info.layout=org.apache.log4j.PatternLayout
log4j.appender.info.layout.ConversionPattern=[%-5p] [%d{HH:mm:ss}] %c - %m%n
log4j.appender.info.datePattern='.'yyyy-MM-dd
log4j.appender.info.Threshold = INFO 
log4j.appender.info.append=true
log4j.appender.info.File=${webApp.root}/WEB-INF/logs/info.log

log4j.logger.debug=debug
log4j.appender.debug=org.apache.log4j.DailyRollingFileAppender
log4j.appender.debug.layout=org.apache.log4j.PatternLayout
log4j.appender.debug.layout.ConversionPattern=[%-5p] [%d{HH:mm:ss}] %c - %m%n
log4j.appender.debug.datePattern='.'yyyy-MM-dd
log4j.appender.debug.Threshold = DEBUG 
log4j.appender.debug.append=true
log4j.appender.debug.File=${webApp.root}/WEB-INF/logs/debug.log

log4j.logger.error=error
log4j.appender.error=org.apache.log4j.DailyRollingFileAppender
log4j.appender.error.layout=org.apache.log4j.PatternLayout
log4j.appender.error.layout.ConversionPattern=[%-5p] [%d{HH:mm:ss}] %c - %m%n
log4j.appender.error.datePattern='.'yyyy-MM-dd
log4j.appender.error.Threshold = ERROR 
log4j.appender.error.append=true
log4j.appender.error.File=${webApp.root}/WEB-INF/logs/error.log
 
六、在程序中使用 SLF4J 来隔离log4j 
1、SLF4J简介 
       SLF4J,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只服务于各种各样的日志系统。按照官方的说法,SLF4J是一个用于日志系统的简单Facade,允许最终用户在部署其应用时使用其所希望的日志系统。 实际上,SLF4J所提供的核心API是一些接口以及一个LoggerFactory的工厂类。从某种程度上,SLF4J有点类似JDBC,不过比JDBC更简单,在JDBC中,你需要指定驱动程序,而在使用SLF4J的时候,不需要在代码中或配置文件中指定你打算使用那个具体的日志系统。如同使用JDBC基本不用考虑具体数据库一样,SLF4J提供了统一的记录日志的接口,只要按照其提供的方法记录即可,最终日志的格式、记录级别、输出方式等通过具体日志系统的配置来实现,因此可以在应用中灵活切换日志系统。 
2、什么情况可以使用 
       如果你开发的是类库或者嵌入式组件,那么就应该考虑采用SLF4J,因为不可能影响最终用户选择哪种日志系统。在另一方面,如果是一个简单或者独立的应用,确定只有一种日志系统,那么就没有使用SLF4J的必要。假设你打算将你使用log4j的产品卖给要求使用JDK 1.4 Logging的用户时,面对成千上万的log4j调用的修改,相信这绝对不是一件轻松的事情。但是如果开始便使用SLF4J,那么这种转换将是非常轻松的事情。 
     采用SLF4J可以轻松切换到性能更高、实现更完善的日志组件,比如LogBack,关于LogBack的介绍与使用请参考http://www.cnblogs.com/yuanermen/archive/2012/02/13/2348942.html这篇贴子,或者官网http://logback./LogBack与Log4j是同一个作者开发,可以看作是LOG4J的升级版或者改良版。 
3、使用SFL4J 
      需要的配置文件和组件包,下面三个 jar 文件和一个 properties 文件都是要放在项目的 ClassPath 上 
A. slf4j-api-1.5.11.jar 
B. slf4j-log4j12-1.5.11.jar 
C. log4j-1.2.16.jar 
D. log4j.properties(也可以是 log4j.xml,本例中用 log4j.propertes)
 
    如果是Mavn工程,那么就在POM中引入。   
<dependency> 
                <groupId>log4j</groupId> 
                <artifactId>log4j</artifactId> 
                <version>1.2.16</version> 
</dependency> 
<dependency> 
                <groupId>org.slf4j</groupId> 
                <artifactId>slf4j-log4j12</artifactId> 
                <version>1.6.1</version>  
</dependency> 
<dependency> 
                <groupId>org.slf4j</groupId> 
                <artifactId>slf4j-api</artifactId> 
                <version>1.6.1</version> 
</dependency> 

4、使用 SLF4J  的代码:

import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;  

public class TestSlf4J {  
    private static final Logger logger = LoggerFactory.getLogger(TestSlf4j.class);  
    public static void main(String[] args) {  
        logger.info("Hello {}","SLF4J"); //log4j的API是不支持这种写法的。 
    }  
 

执行它,控制台输出:

2013-11-07 15:34:45,245 [com.unmi.TestSlf4j]-[INFO] Hello

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多