Log4j的使用

来源:互联网 发布:股票交易算法 编辑:程序博客网 时间:2024/06/11 00:07

OK,现在我们开始研究Log4j。Log4j是目前应用最广泛的日志空间,它分如下几个日志级别,日志级别依次升高。级别高的level会屏蔽级别低的信息。

TRACE→DEBUG→INFO→WARNING→ERROR→FATAL→OFF。

比如设置INFO级别,TRACE,DEBUG就不会输出,如果设置WARNING级别,则TRACE,DEBUG,INFO都不会输出。


  • Log4j初体验

现在我们编码尝试下Log4j。代码如下:

[java] view plain copy
print?
  1. package org.linkinpark.commons.logtest;  
  2.   
  3. import org.apache.log4j.Logger;  
  4.   
  5. public class Log4jTest  
  6. {  
  7.   
  8.     public static Logger log = Logger.getLogger(Log4jTest.class);  
  9.   
  10.     /* 
  11.       @创建时间: 2016年2月22日 
  12.       @相关参数: 
  13.       @功能描述: 定义一个输出日志的方法 
  14.       <p> 
  15.       trace→debug→info→warn→error→fatal→off 
  16.       级别依次升高,级别高的level会屏蔽级别低的level。 
  17.       </p> 
  18.      */  
  19.     public static void logTest()  
  20.     {  
  21.         log.trace(”trace级别的日志输出”);  
  22.         log.info(”info级别的日志输出”);  
  23.         log.debug(”debug级别的日志输出”);  
  24.         log.warn(”warn级别的日志输出”);  
  25.         log.error(”error级别的日志输出”);  
  26.         log.fatal(”fatal级别的日志输出”);  
  27.         try  
  28.         {  
  29.             System.out.println(9 / 0);  
  30.         }  
  31.         catch (RuntimeException e)  
  32.         {  
  33.             log.error(e.getMessage());  
  34.         }  
  35.     }  
  36.   
  37.     public static void main(String[] args)  
  38.     {  
  39.         logTest();  
  40.     }  
  41.   
  42. }  
package org.linkinpark.commons.logtest;

import org.apache.log4j.Logger;

public class Log4jTest
{

public static Logger log = Logger.getLogger(Log4jTest.class);/** * @创建时间: 2016年2月22日 * @相关参数: * @功能描述: 定义一个输出日志的方法 * &lt;p&gt; * trace→debug→info→warn→error→fatal→off * 级别依次升高,级别高的level会屏蔽级别低的level。 * &lt;/p&gt; */public static void logTest(){    log.trace("trace级别的日志输出");    log.info("info级别的日志输出");    log.debug("debug级别的日志输出");    log.warn("warn级别的日志输出");    log.error("error级别的日志输出");    log.fatal("fatal级别的日志输出");    try    {        System.out.println(9 / 0);    }    catch (RuntimeException e)    {        log.error(e.getMessage());    }}public static void main(String[] args){    logTest();}

}
这里我们用maven来管理我们该测试项目,需要添加log4j的pom依赖。

[html] view plain copy
print?
  1. <dependency>  
  2.             <groupId>log4j</groupId>  
  3.             <artifactId>log4j</artifactId>  
  4.             <version>1.2.17</version>  
  5.         </dependency>  
<dependency> 
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
日志的配置例如输出级别,输出到哪里,输出什么附加信息,输出格式等,一般都要写在配置文件log4j.properties中。
[html] view plain copy
print?
  1. #   可设置级别:TRACE→DEBUG→INFO→WARNING→ERROR→FATAL→OFF  
  2. #   高级别level会屏蔽低级别level。  
  3. #   debug:显示debug、info、error     
  4. #   info:显示info、error     
  5.   
  6. #log4j.rootLogger=DEBUG,console,file  
  7. log4j.rootLogger=INFO,console  
  8.     
  9.     
  10. #输出到控制台     
  11. log4j.appender.console=org.apache.log4j.ConsoleAppender    
  12. #设置输出样式     
  13. log4j.appender.console.layout=org.apache.log4j.PatternLayout   
  14. #日志输出信息格式为  
  15. log4j.appender.console.layout.ConversionPattern=[%-d{yyyy-MM-dd HH:mm:ss}]-[%t-%5p]-[%C-%M(%L)]: %m%n   
  16.   
  17. #输出到文件(这里默认为追加方式)     
  18. #log4j.appender.file=org.apache.log4j.FileAppender   
  19. #log4j.appender.file.File=F:/LinkinPark/logs/Log4J.log   
  20. #样式为TTCCLayout     
  21. #log4j.appender.file.layout=org.apache.log4j.TTCCLayout    
  22.   
  23. #自定义样式     
  24. #%c 输出所属的类目,通常就是所在类的全名   
  25. #%C 输出Logger所在类的名称,通常就是所在类的全名   
  26. #%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss , SSS},%d{ABSOLUTE},%d{DATE}  
  27. #%F 输出所在类的类名称,只有类名。  
  28. #%l 输出语句所在的行数,包括类名+方法名+文件名+行数  
  29. #%L 输出语句所在的行数,只输出数字  
  30. #%m 输出代码中指定的讯息,如log(message)中的message  
  31. #%M 输出方法名  
  32. #%p 输出日志级别,即DEBUG,INFO,WARN,ERROR,FATAL  
  33. #%r 输出自应用启动到输出该log信息耗费的毫秒数  
  34. #%t 输出产生该日志事件的线程名  
  35. #%n 输出一个回车换行符,Windows平台为“/r/n”,Unix平台为“/n”  
  36. #%% 用来输出百分号“%”  
  37. #log4j.appender.Linkin.layout.ConversionPattern=%n[%l%d{yy/MM/dd HH:mm:ss:SSS}][%C-%M] %m    
  38. #log4j.appender.Linkin.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss}[%C]-[%p] %m%n     
  39. #log4j.appender.Linkin.layout.ConversionPattern = %d{ABSOLUTE} %5p %t %c{2}:%L - %m%n  
#    可设置级别:TRACE→DEBUG→INFO→WARNING→ERROR→FATAL→OFF
# 高级别level会屏蔽低级别level。# debug:显示debug、info、error # info:显示info、error #log4j.rootLogger=DEBUG,console,filelog4j.rootLogger=INFO,console#输出到控制台 log4j.appender.console=org.apache.log4j.ConsoleAppender #设置输出样式 log4j.appender.console.layout=org.apache.log4j.PatternLayout #日志输出信息格式为log4j.appender.console.layout.ConversionPattern=[%-d{yyyy-MM-dd HH:mm:ss}]-[%t-%5p]-[%C-%M(%L)]: %m%n #输出到文件(这里默认为追加方式) #log4j.appender.file=org.apache.log4j.FileAppender #log4j.appender.file.File=F:/LinkinPark/logs/Log4J.log #样式为TTCCLayout #log4j.appender.file.layout=org.apache.log4j.TTCCLayout #自定义样式 #%c 输出所属的类目,通常就是所在类的全名 #%C 输出Logger所在类的名称,通常就是所在类的全名 #%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss , SSS},%d{ABSOLUTE},%d{DATE}#%F 输出所在类的类名称,只有类名。#%l 输出语句所在的行数,包括类名+方法名+文件名+行数#%L 输出语句所在的行数,只输出数字#%m 输出代码中指定的讯息,如log(message)中的message#%M 输出方法名#%p 输出日志级别,即DEBUG,INFO,WARN,ERROR,FATAL#%r 输出自应用启动到输出该log信息耗费的毫秒数#%t 输出产生该日志事件的线程名#%n 输出一个回车换行符,Windows平台为“/r/n”,Unix平台为“/n”#%% 用来输出百分号“%”#log4j.appender.Linkin.layout.ConversionPattern=%n[%l%d{yy/MM/dd HH:mm:ss:SSS}][%C-%M] %m #log4j.appender.Linkin.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss}[%C]-[%p] %m%n #log4j.appender.Linkin.layout.ConversionPattern = %d{ABSOLUTE} %5p %t %c{2}:%L - %m%n

OK,现在让我们来看看控制台输出的日志情况。

[java] view plain copy
print?
  1. [2016-02-22 22:33:35]-[main- INFO]-[org.linkinpark.commons.logtest.Log4jTest-logTest(22)]: info级别的日志输出  
  2.  [2016-02-22 22:33:35]-[main- WARN]-[org.linkinpark.commons.logtest.Log4jTest-logTest(24)]: warn级别的日志输出  
  3.  [2016-02-22 22:33:35]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest-logTest(25)]: error级别的日志输出  
  4.  [2016-02-22 22:33:35]-[main-FATAL]-[org.linkinpark.commons.logtest.Log4jTest-logTest(26)]: fatal级别的日志输出  
  5.  [2016-02-22 22:33:35]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest-logTest(33)]: / by zero  
  6.    
[2016-02-22 22:33:35]-[main- INFO]-[org.linkinpark.commons.logtest.Log4jTest-logTest(22)]: info级别的日志输出 [2016-02-22 22:33:35]-[main- WARN]-[org.linkinpark.commons.logtest.Log4jTest-logTest(24)]: warn级别的日志输出 [2016-02-22 22:33:35]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest-logTest(25)]: error级别的日志输出 [2016-02-22 22:33:35]-[main-FATAL]-[org.linkinpark.commons.logtest.Log4jTest-logTest(26)]: fatal级别的日志输出 [2016-02-22 22:33:35]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest-logTest(33)]: / by zero 


Log4j的使用十分灵活,功能也很强大。可以在配置文件中配置输出样式,可以把日志输出到屏幕,控制台,各种样式的文件,数据库,FTP服务器,HTTP服务器,远程实时监控程序,发送邮件到指定的邮箱,甚至是发送短信等。

  • Log4J的应用
Log4J是Apache的一个开源项目,通过使用Log4J,我们可以控制日志信息输送的目的地,输出格式,通过设置日志信息的级别还可以细致地控制日志的生成过程。

  • 1,Log4j的执行效率
Log4j内部做了大量的优化,缓存工作,是输出时对服务器的压力,消耗时间,资源等都达到最小,比如下面2行代码:
[java] view plain copy
print?
  1. log.debug(“debug级别的日志输出”);  
  2. log.info(”info级别的日志输出”);  
log.debug("debug级别的日志输出");log.info("info级别的日志输出");
这两句日志可能被记录到日志文件中,但是写的过程不同于常规的打开文件,写文件,关闭文件等流程,频繁的打开文件,关闭文件需要消耗大量的资源。Log4j只在初始化的时候打开文件,并保持对文件的写控制,知道在系统结束的时候才会关闭文件。这样就使I/O次数达到最小,提高了运行效率。

当输出级别设置为ERROR时,debug,info等低级别方法会因为输出级别小于error而直接返回,所以不会消耗太多的资源。这里我们来看下debug()方法内部的实现代码:
[java] view plain copy
print?
  1. public void debug(Object message)  
  2.     {  
  3.         if (repository.isDisabled(Level.DEBUG_INT))  
  4.             return;  
  5.         if (Level.DEBUG.isGreaterOrEqual(this.getEffectiveLevel()))  
  6.         {  
  7.             forcedLog(FQCN, Level.DEBUG, message, null);  
  8.         }  
  9.     }  
public void debug(Object message)    {        if (repository.isDisabled(Level.DEBUG_INT))            return;        if (Level.DEBUG.isGreaterOrEqual(this.getEffectiveLevel()))        {            forcedLog(FQCN, Level.DEBUG, message, null);        }    }


  • 2,优化日志代码

虽然设为ERROR时debug()会直接返回,但是下面的代码仍然会消耗额外的时间,原因是在执行debug()前,需要先将字符串进行连接。

[java] view plain copy
print?
  1. log.debug(“debug级别的日志输出”+i+“*”+j); // 有字符串拼接  
log.debug("debug级别的日志输出"+i+"*"+j); // 有字符串拼接

如果想要避免这种消耗,最好使用isDebugEnabled()或者isEnabledFor()判断一下,比如下面代码:

[java] view plain copy
print?
  1. if (log.isDebugEnabled())  
  2.         {  
  3.             log.debug(”debug级别的日志输出”);  
  4.         }  
  5.         if (log.isEnabledFor(Level.DEBUG))  
  6.         {  
  7.             log.debug(”debug级别的日志输出”);  
  8.         }  
if (log.isDebugEnabled())        {            log.debug("debug级别的日志输出");        }        if (log.isEnabledFor(Level.DEBUG))        {            log.debug("debug级别的日志输出");        }

  • 3,log4j配置文件
Log4j默认的配置文件为log4j.properties。启动时,会加载classpath下的log4j.properties初始化Log4j。如果文件不存在,Log4j会在控制台打印如下信息,提示说没有找到Log4j配置。比如我们现在只保留Java代码,然后删除掉log4j.properties配置文件,看控制台报错。
[java] view plain copy
print?
  1. log4j:WARN No appenders could be found for logger (org.linkinpark.commons.logtest.Log4jTest).  
  2. log4j:WARN Please initialize the log4j system properly.  
  3. log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.  
log4j:WARN No appenders could be found for logger (org.linkinpark.commons.logtest.Log4jTest).log4j:WARN Please initialize the log4j system properly.log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

OK,现在重新将log4j.properties配置文件加入到我们的项目classpath中,然后控制台输出日志正常。这里一定要注意要加载项目的Classpath中,在这里我们随便写写测试类,所以直接丢项目src下面就好了,编译过后配置文件自动就放到了class的根目录下了。


当然我们也可以使用其他的方式,只不过不推荐罢了。如果不使用默认的文件名log4j.properties,可以用PropertyConfigurator指定配置文件的路径。比如下面的代码,经过测试可行。当然还可以使用log4j.xml,只不过要在xml里面加入log4j的secma,不推荐。这里贴出使用Java类加载指定配置文件的代码:
[java] view plain copy
print?
  1. public static void logTest()  
  2.     {  
  3.         PropertyConfigurator.configure(”/Users/LinkinPark/WorkSpace/linkin-log-test/src/main/java/org/linkinpark/commons/logtest/log4j.properties”);  
  4.         if (log.isDebugEnabled())  
  5.         {  
  6.             log.debug(”debug级别的日志输出”);  
  7.         }  
  8.     }  
public static void logTest()    {        PropertyConfigurator.configure("/Users/LinkinPark/WorkSpace/linkin-log-test/src/main/java/org/linkinpark/commons/logtest/log4j.properties");        if (log.isDebugEnabled())        {            log.debug("debug级别的日志输出");        }    }

这里也贴出PropertyConfigurator类configure()方法源码:
[java] view plain copy
print?
  1. static public void configure(String configFilename)  
  2.     {  
  3.         new PropertyConfigurator().doConfigure(configFilename, LogManager.getLoggerRepository());  
  4.     }  
  5.   
  6.   
  7.     public void doConfigure(String configFileName, LoggerRepository hierarchy)  
  8.     {  
  9.         Properties props = new Properties();  
  10.         FileInputStream istream = null;  
  11.         try  
  12.         {  
  13.             istream = new FileInputStream(configFileName);  
  14.             props.load(istream);  
  15.             istream.close();  
  16.         }  
  17.         catch (Exception e)  
  18.         {  
  19.             if (e instanceof InterruptedIOException || e instanceof InterruptedException)  
  20.             {  
  21.                 Thread.currentThread().interrupt();  
  22.             }  
  23.             LogLog.error(”Could not read configuration file [“ + configFileName + “].”, e);  
  24.             LogLog.error(”Ignoring configuration file [“ + configFileName + “].”);  
  25.             return;  
  26.         }  
  27.         finally  
  28.         {  
  29.             if (istream != null)  
  30.             {  
  31.                 try  
  32.                 {  
  33.                     istream.close();  
  34.                 }  
  35.                 catch (InterruptedIOException ignore)  
  36.                 {  
  37.                     Thread.currentThread().interrupt();  
  38.                 }  
  39.                 catch (Throwable ignore)  
  40.                 {  
  41.                 }  
  42.   
  43.   
  44.             }  
  45.         }  
  46.         // If we reach here, then the config file is alright。嫁入到log4j中去了。  
  47.         doConfigure(props, hierarchy);  
  48.     }  
static public void configure(String configFilename)    {        new PropertyConfigurator().doConfigure(configFilename, LogManager.getLoggerRepository());    }    public void doConfigure(String configFileName, LoggerRepository hierarchy)    {        Properties props = new Properties();        FileInputStream istream = null;        try        {            istream = new FileInputStream(configFileName);            props.load(istream);            istream.close();        }        catch (Exception e)        {            if (e instanceof InterruptedIOException || e instanceof InterruptedException)            {                Thread.currentThread().interrupt();            }            LogLog.error("Could not read configuration file [" + configFileName + "].", e);            LogLog.error("Ignoring configuration file [" + configFileName + "].");            return;        }        finally        {            if (istream != null)            {                try                {                    istream.close();                }                catch (InterruptedIOException ignore)                {                    Thread.currentThread().interrupt();                }                catch (Throwable ignore)                {                }            }        }        // If we reach here, then the config file is alright。嫁入到log4j中去了。        doConfigure(props, hierarchy);    }

OK,log4j的配置文件内容还是比较多的,我们下一篇来详细的整理。这篇先这样。
本文转载自: http://blog.csdn.net/u011794238/article/details/50719414
原创粉丝点击