Java日志组件 commons-logging和log4j介绍

jopen 12年前
     <p><strong>一、日志系统介绍</strong></p>    <p>日志的重要性是随着系统的膨胀而显现的,在一个庞大的系统中查错没有各种日志信息是寸步难行的。所以在系统加入日志是必须的。</p>    <p>最原始的日志方式,就是在程序的适当地方添加System.out.println()方法,但是带来的问题是,系统稳定后,日志太大,如果要减少日志量,就需要重新修改程序,虽然只是注释掉System.out.println()方法。但是万一系统再次出错,又要改。</p>    <p><strong>commons-logging</strong>提供分级日志功能,相当于把System.out.println()方法加强了,原来是一定输出到控制台,现在commons-logging有6级日志,但是apache建议使用4级,即ERROR、WARN、INFO、 DEBUG。什么情况下输出日志由程序中写日志的方法决定,输出什么级别以上的日志和输出到哪里由配置文件决定。</p>    <p>使用commons-logging如下:</p>    <pre class="brush:java; toolbar: true; auto-links: false;">//导入类 import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class TestLog {     //获取以当前类为参数的日志对象     private static Log log = LogFactory.getLog(TestLog.class);     public static void main(String[] args){         //输出4种不同级别的日志         log.debug("111");         log.info("222");         log.warn("333");         log.error("444");     } }</pre>    <p></p>    <p>当然还要配置commons-logging.properties文件,其中定义输出哪个级别以上的日志。略。</p>    <p>好像这就完了,和log4j没啥关系。那么为什么一般系统都会使用commons-logging和log4j两个包来记录日志呢?</p>    <p>原因就是commons-logging的输出功能比较弱,也就是输出格式和输出设备选择有限,只有原生输出类 org.apache.commons. logging.impl.SimpleLog。但是它提供了一个通用的日志接口org.apache.commons.logging.log,让其他的包来实现复杂的输出。其中就有Jdk14Logger, Log4JLogger,前面是jdk1.4之后加入的,后面就是log4j中的类。</p>    <p><strong>log4j</strong>也可以直接像commons-logging一样在程序中定义输出信息,然后再配置文件中定义输出级别,但是这样做就会使程序唯一的和log4j绑定(如果你一定要单独使用log4j,那么也是可以的),而且commons-logging更加智能,帮我们‘自动选择’‘适当的’日志实现系统”:</p>    <p>1)        首先在classpath下寻找自己的配置文件commons-logging.properties,如果找到,则使用其中定义的Log实现类;</p>    <p>2)        如果找不到commons-logging.properties文件,则在查找是否已定义系统环境变量org.apache.commons.logging.Log,找到则使用其定义的Log实现类;</p>    <p>3)        否则,查看classpath中是否有Log4j的包,如果发现,则自动使用Log4j作为日志实现类;</p>    <p>4)        否则,使用JDK自身的日志实现类(JDK1.4以后才有日志实现类);</p>    <p>5)        否则,使用commons-logging自己提供的一个简单的日志实现类SimpleLog;</p>    <p>(以上顺序不保证完全准确,请参考官方文档)</p>    <p>所以,在前面程序的基础上,只要导入log4j的包,则commons-logging会自动使用log4j作为输出类,程序不需要任何改动,但是注意:log4j的配置文件log4j.properties对Log4j来说是必须的。如果classpath中没有该配置文件,或者配置不对,将会引发运行时异常。所以下面介绍log4j.properties的配置。</p>    <p><strong>二、log4j.properties的配置<br /> </strong>其实您也可以完全不使用配置文件,而是在代码中配置Log4j环境。但是,使用配置文件将使您的应用程序更加灵活。 <br /> Log4j支持两种配置文件格式,一种是XML格式的文件,一种是properties格式的文件。下面我们介绍使用properties格式做为配置文件的方法: <br /> 示例:<br /> log4j.rootLogger=INFO, A1 <br /> log4j.appender.A1=org.apache.log4j.ConsoleAppender <br /> log4j.appender.A1.layout=org.apache.log4j.PatternLayout <br /> log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n <br /> <br /> <span style="color:blue;">1. 配置根Logger,其语法为:</span> <br /> log4j.rootLogger = [ level ] , appenderName, appenderName, … <br /> 其中,level 是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来。 <br /> appenderName就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。 appenderName是自定义的,但是为了明了,都会使用console,file等特殊名字表示输出到哪里去。<br /> <br /> <span style="color:blue;">2. 配置日志信息输出目的地Appender,其语法为:</span> <br /> log4j.appender.appenderName = fully.qualified.name.of.appender.class <br /> log4j.appender.appenderName.option1 = value1 <br /> … <br /> log4j.appender.appenderName.option = valueN <br /> 其中,Log4j提供的appender有以下几种: <br /> org.apache.log4j.ConsoleAppender(控制台), <br /> org.apache.log4j.FileAppender(文件), <br /> org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件), <br /> org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件), <br /> org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方) <br /> (1).ConsoleAppender选项 <br /> Threshold=WARN:指定日志消息的输出最低层次。 <br /> ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。 <br /> Target=System.err:默认情况下是:System.out,指定输出控制台 <br /> (2).FileAppender 选项 <br /> Threshold=WARN:指定日志消息的输出最低层次。 <br /> ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。 <br /> File=mylog.txt:指定消息输出到mylog.txt文件。 <br /> Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。 <br /> (3).DailyRollingFileAppender 选项 <br /> Threshold=WARN:指定日志消息的输出最低层次。 <br /> ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。 <br /> File=mylog.txt:指定消息输出到mylog.txt文件。 <br /> Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。 <br /> DatePattern=’.'yyyy-ww:每周滚动一次文件,即每周产生一个新的文件。当然也可以指定按月、周、天、时和分。即对应的格式如下: <br />   1)’.'yyyy-MM: 每月 <br />   2)’.'yyyy-ww: 每周 <br />   3)’.'yyyy-MM-dd: 每天 <br />   4)’.'yyyy-MM-dd-a: 每天两次 <br />   5)’.'yyyy-MM-dd-HH: 每小时 <br />   6)’.'yyyy-MM-dd-HH-mm: 每分钟 <br /> (4).RollingFileAppender 选项 <br /> Threshold=WARN:指定日志消息的输出最低层次。 <br /> ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。 <br /> File=mylog.txt:指定消息输出到mylog.txt文件。 <br /> Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。 <br /> MaxFileSize=100KB: 后缀可以是KB, MB 或者是 GB. 在日志文件到达该大小时,将会自动滚动,即将原来的内容移到mylog.log.1文件。 <br /> MaxBackupIndex=2:指定可以产生的滚动文件的最大数。 <br /> <br /> <span style="color:blue;">3. 配置日志信息的布局,其语法为:</span> <br /> log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class <br /> log4j.appender.appenderName.layout.option1 = value1 <br /> … <br /> log4j.appender.appenderName.layout.option = valueN <br /> 其中,Log4j提供的layout有以下几种: <br /> org.apache.log4j.HTMLLayout(以HTML表格形式布局), <br /> org.apache.log4j.PatternLayout(可以灵活地指定布局模式), <br /> org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串), <br /> org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息) <br /> <br /> <span style="color:blue;">4、输出格式设置</span> <br /> 在配置文件中可以通过log4j.appender.A1.layout.ConversionPattern设置日志输出格式。 <br /> 参数: <br /> %p: 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL, <br /> %d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921 <br /> %r: 输出自应用启动到输出该log信息耗费的毫秒数 <br /> %c: 输出日志信息所属的类目,通常就是所在类的全名 <br /> %t: 输出产生该日志事件的线程名 <br /> %l: 输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10) <br /> %x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。 <br /> %%: 输出一个”%”字符 <br /> %F: 输出日志消息产生时所在的文件名称 <br /> %L: 输出代码中的行号 <br /> %m: 输出代码中指定的消息,产生的日志具体信息 <br /> %n: 输出一个回车换行符,Windows平台为”\r\n”,Unix平台为”\n”输出日志信息换行 <br /> 可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如: <br /> 1)%20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,默认的情况下右对齐。 <br /> 2)%-20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,”-”号指定左对齐。 <br /> 3)%.30c:指定输出category的名称,最大的宽度是30,如果category的名称大于30的话,就会将左边多出的字符截掉,但小于30的话也不会有空格。 <br /> 4)%20.30c:如果category的名称小于20就补空格,并且右对齐,如果其名称长于30字符,就从左边交远销出的字符截掉。</p>    <p>三、<strong>log4j.properties的几个例子</strong></p>    <div id="highlighter_858125" class="syntaxhighlighter ">     <div class="lines">      <div class="line alt2">       <pre class="brush:shell; toolbar: true; auto-links: false;">log4j.rootLogger=DEBUG,CONSOLE,A1,im  log4j.addivity.org.apache=true # 应用于控制台  log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender  log4j.appender.Threshold=DEBUG  log4j.appender.CONSOLE.Target=System.out  log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout  log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n  #log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[thread] n%c[CATEGORY]%n%m[MESSAGE]%n%n  #应用于文件  log4j.appender.FILE=org.apache.log4j.FileAppender  log4j.appender.FILE.File=file.log  log4j.appender.FILE.Append=false log4j.appender.FILE.layout=org.apache.log4j.PatternLayout  log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n  # Use this layout for LogFactor 5 analysis  # 应用于文件回滚  log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender  log4j.appender.ROLLING_FILE.Threshold=ERROR  log4j.appender.ROLLING_FILE.File=rolling.log //文件位置,也可以用变量${java.home}、rolling.log  log4j.appender.ROLLING_FILE.Append=true //true:添加 false:覆盖  log4j.appender.ROLLING_FILE.MaxFileSize=10KB //文件最大尺寸  log4j.appender.ROLLING_FILE.MaxBackupIndex=1 //备份数  log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout  log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n     #应用于socket  log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender  log4j.appender.SOCKET.RemoteHost=localhost  log4j.appender.SOCKET.Port=5001 log4j.appender.SOCKET.LocationInfo=true # Set up for Log Facter 5 log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout  log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[thread]%n%c[CATEGORY]%n%m[MESSAGE]%n%n     # Log Factor 5 Appender  log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender  log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000 # 发送日志给邮件  log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender  log4j.appender.MAIL.Threshold=FATAL  log4j.appender.MAIL.BufferSize=10 log4j.appender.MAIL.From=web@www.wuset.com  log4j.appender.MAIL.SMTPHost=www.wusetu.com  log4j.appender.MAIL.Subject=Log4J Message  log4j.appender.MAIL.To=web@www.wusetu.com  log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout  log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n  # 用于数据库  log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender  log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test  log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver  log4j.appender.DATABASE.user=root  log4j.appender.DATABASE.password=  log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES (’[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n’)  log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout  log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n     log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender  log4j.appender.A1.File=SampleMessages.log4j  log4j.appender.A1.DatePattern=yyyyMMdd-HH’.log4j’  log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout  #自定义Appender  log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender  log4j.appender.im.host = mail.cybercorlin.net  log4j.appender.im.username = username  log4j.appender.im.password = password  log4j.appender.im.recipient = corlin@cybercorlin.net  log4j.appender.im.layout=org.apache.log4j.PatternLayout  log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n</pre>       <br />      </div>     </div>    </div>    <p>其中:log4j.addivity.org.apache=true的作用在于 children-logger是否使用 rootLogger的配置,例如 输出终端。</p>    <p><strong>四、使用日志的其他问题</strong></p>    <p>在程序中输出日志可以直接写 log.debug(theResult); 有些程序又使用if判断:   </p>    <p> if (log.isDebugEnabled()) {<br />         ... do something expensive ...<br />         log.debug(theResult);<br />     }<br /> 其实是关于log.debug()参数的问题,如果参数初始化代价大,则先if判断,避免多余的初始化,例如多个String对象拼接。如果只是简单的传参,则无所谓使用何种方式。不过有人说为了统一风格,全部使用if判断。这个看个人喜欢了。</p>    <p>参考:<a href="/misc/goto?guid=4959499926903270907" rel="nofollow">http://www.cnblogs.com/suman/archive/2010/10/23/1858864.html</a></p>    <p><a href="/misc/goto?guid=4959499926998322248" rel="nofollow">http://www.blogjava.net/sy1214520/default.html?page=3</a></p>    <p></p>