zoukankan      html  css  js  c++  java
  • Log4j扩展使用--日志记录器Logger


    OK,现在我们认真的研究下Logger的配置,进行相关配置扩展。

    Log4j有三个主要的组件:Loggers(记录器),Appenders(输出源)和Layouts(布局)。其中,Logger负责记录日志,Appender负责输出到什么地方,Layout负责以什么格式输出,输出哪些附加信息等。综合使用这三个组件可以轻松的记录信息的类型和级别,并可以在运行时控制日志输出的样式和位置。

    • Log4J三个核心概念
    公共类     Logger       负责处理日志记录的大部分操作。 
    公共接口   Appender     负责控制日志记录的输出。 
    公共抽象类   Layout     负责格式化Appender的输出


    Logger日志记录器是日志处理的核心组件。现在我们来认真的整理下这个组件。Logger就是Java代码中的logger,例如:
    public static Logger log = Logger.getLogger(Log4jTest.class);
    Logger是有名字的,它的名字便是Logger.getLogger()方法的参数。如果参数为所在的类,Log4j会去类名作为logger的名称,比如org.linkinpark.commons.logtest.Log4jTest。

    Loggers组件在此系统中被分为五个级别:TRACE→DEBUG→INFO→WARNING→ERROR→FATAL→OFF。等级高的level自动屏蔽等级低的level,这点一定要记住。

    这里Log4j有一个规则:假设Loggers级别为P,如果在Loggers中发生了一个级别Q比P高,则可以启动,否则屏蔽掉。假设你定义的级别是info,那么error和warn的日志可以显示而比他低的debug信息就不显示了。

    注意以下几点:

    1,Logger为单态模式,相同名字的logger只会有一个实例。如果在构建一个同名的Logger,log4j会返回之前的Logger实例。

    2,一般情况下都以类名作为Logger的名称。Logger的名字类似于Java中的Package,大小写敏感,用点分开且具有继承关系。log4j.properties中通过名称来配置Logger的属性。

    3,在对Logger实例进行命名时,没有限制,可以取任意自己感兴趣的名字。一般情况下建议以类的所在位置来命名Logger实例,这是目前来讲比较有效的Logger命名方式。这样可以使得每个类建立自己的日志信息,便于管理。

    4,Log4j中有一个根记录器rootLogger,它是所有Logger的父类。

    • logger的配置
    在log.properties配置log4j.properties中,log4j.logger后面配置的是Logger,log4j.appender后面配置一个Appender。
    log4j.logger.org.linkinpark.commons.logtest.Log4jTest=INFO,console
    如果某个Logger没有配置,则使用它的父亲配置,知道找到为止。一般情况下,只需要配置根记录器rootLogger即可,所有的logger都会沿用rootLogger的配置。

    • rootLogger配置
    根记录器rootLogger直接用log4j.rootLogger配置即可。rootLogger是所有记录器的父亲,任何记录器都可以继承rootLogger的配置,代码如下:
    #log4j.rootLogger=DEBUG,console,file
    #log4j.logger.org.linkinpark.commons.logtest.Log4jTest=INFO
    log4j.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 
    注意:如果要对某个Logger进行特殊的输出,只需要再配置一下该Logger就OK,覆盖父亲的配置即可。覆盖时,可以只配置级别,输出地,也可以2者都配置。

    OK,现在我们举一个例子好了。

    比如我现在有如下需求,一般的日志打印我都按照某一种特定的配置就够了,但是有一个类比较特殊,我需要进行特殊的配置那么要如何做呢?

    1,写好2个Java源码,输出日志

    2,主要是写好这个log4j.properties文件。先定义rootLogger,然后子类重新配置覆盖rootLogger就够了。但是丫的有一个问题就是说如果子类重新定义了appender,仍然会继承rootLogger的配置,也就是说2份日志输出了,我晕。

    所以以后建议控制子类重写覆盖rootLogger配置的时候,只重写日志级别好了,其他的别动。OK,现在贴出代码:

    package org.linkinpark.commons.logtest;
    
    import org.apache.log4j.Logger;
    
    /**
     * @创建作者: LinkinPark
     * @创建时间: 2016年2月23日
     * @功能描述: 这个类用log4j的rootLogger默认输出
     */
    public class Log4jTest
    {
    
    	public static Logger log = Logger.getLogger(Log4jTest.class);
    
    	/**
    	 * @创建时间: 2016年2月22日
    	 * @相关参数:
    	 * @功能描述: 定义一个输出日志的方法
    	 * <p>
    	 * trace→debug→info→warn→error→fatal→off
    	 * 级别依次升高,级别高的level会屏蔽级别低的level。
    	 * </p>
    	 */
    	public static void logTest()
    	{
    		System.out.println("=======这里是rootLogger类的日志输出======");
    		if (log.isDebugEnabled())
    		{
    			log.debug("debug级别的日志输出");
    		}
    		log.trace("trace级别的日志输出");
    		log.info("info级别的日志输出");
    		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();
    	}
    
    }
    
    package org.linkinpark.commons.logtest;
    
    import org.apache.log4j.Logger;
    
    /**
     * @创建作者: LinkinPark
     * @创建时间: 2016年2月23日
     * @功能描述: 这个类重新配置,来重写rootLogger的日志级别
     */
    public class Log4jTest1
    {
    
    	public static Logger log = Logger.getLogger(Log4jTest1.class);
    
    	/**
    	 * @创建时间: 2016年2月22日
    	 * @相关参数:
    	 * @功能描述: 定义一个输出日志的方法
    	 * <p>
    	 * trace→debug→info→warn→error→fatal→off
    	 * 级别依次升高,级别高的level会屏蔽级别低的level。
    	 * </p>
    	 */
    	public static void logTest()
    	{
    		System.out.println("=======这里是特定类的日志输出======");
    		log.info("info级别的日志输出");
    		log.warn("warn级别的日志输出");
    		log.error("error级别的日志输出");
    		log.fatal("fatal级别的日志输出");
    		try
    		{
    			throw new NullPointerException("人工抛出一个异常");
    		}
    		catch (RuntimeException e)
    		{
    			log.error(e.getMessage());
    		}
    	}
    
    	public static void main(String[] args)
    	{
    		logTest();
    		Log4jTest.logTest();
    	}
    
    }
    
    #	可设置级别:TRACE→DEBUG→INFO→WARNING→ERROR→FATAL→OFF
    #	高级别level会屏蔽低级别level。
    #	debug:显示debug、info、error   
    #	info:显示info、error   
    
    #log4j.rootLogger=DEBUG,console,file
    log4j.logger.org.linkinpark.commons.logtest.Log4jTest1=ERROR
    log4j.rootLogger=INFO,console
    
    # 一下是rootLogger的配置,子类默认继承,但是子类重写下面配置=rootLogger+自己配置,我晕
    #输出到控制台   
    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,现在我们来看下控制台输出,没问题。

    =======这里是特定类的日志输出======
    [2016-02-23 00:23:54]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest1-logTest(24)]: error级别的日志输出
     [2016-02-23 00:23:54]-[main-FATAL]-[org.linkinpark.commons.logtest.Log4jTest1-logTest(25)]: fatal级别的日志输出
     [2016-02-23 00:23:54]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest1-logTest(32)]: 人工抛出一个异常
     =======这里是rootLogger类的日志输出======
    [2016-02-23 00:23:54]-[main- INFO]-[org.linkinpark.commons.logtest.Log4jTest-logTest(27)]: info级别的日志输出
     [2016-02-23 00:23:54]-[main- WARN]-[org.linkinpark.commons.logtest.Log4jTest-logTest(28)]: warn级别的日志输出
     [2016-02-23 00:23:54]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest-logTest(29)]: error级别的日志输出
     [2016-02-23 00:23:54]-[main-FATAL]-[org.linkinpark.commons.logtest.Log4jTest-logTest(30)]: fatal级别的日志输出
     [2016-02-23 00:23:54]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest-logTest(37)]: / by zero
     


    • 类别category配置
    logger还有一个类别(category)的概念,荣国设置类别来设置类别下所有的logger。category类似于Java的package,效果和Logger的名字等价。这里也举一个例子好了:

    OK,我们复制前面的log4jTest到一个新的包logtest1下,2份Java代码不变,然后设置配置文件控制不同的日志级别,来看看效果。

      

    #	可设置级别:TRACE→DEBUG→INFO→WARNING→ERROR→FATAL→OFF
    #	高级别level会屏蔽低级别level。
    #	debug:显示debug、info、error   
    #	info:显示info、error   
    
    #log4j.rootLogger=DEBUG,console,file
    #子类重新定义日志级别,logger的名字是日志类的权限类名
    #log4j.logger.org.linkinpark.commons.logtest.Log4jTest1=ERROR
    #子类重新定义日志级别,category的名字是日志类的包名,可以将category理解为Java的package。
    log4j.category.org.linkinpark.commons.logtest1=ERROR
    log4j.rootLogger=DEBUG,console
    
    # 以下是rootLogger的配置,子类默认继承,但是子类重写下面配置=rootLogger+自己配置,我晕
    #输出到控制台   
    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,我们现在看下控制台输出:没问题,成功输出我们自己定义的特定的包下面的日志,并且按照我们自己配置的日志级别。

    =======这里是特定包下面类的日志输出======
    [2016-02-23 00:39:56]-[main-ERROR]-[org.linkinpark.commons.logtest1.Log4jTest1-logTest(30)]: error级别的日志输出
     [2016-02-23 00:39:56]-[main-FATAL]-[org.linkinpark.commons.logtest1.Log4jTest1-logTest(31)]: fatal级别的日志输出
     [2016-02-23 00:39:56]-[main-ERROR]-[org.linkinpark.commons.logtest1.Log4jTest1-logTest(38)]: 人工抛出一个异常
     =======这里是rootLogger类的日志输出======
    [2016-02-23 00:39:56]-[main-DEBUG]-[org.linkinpark.commons.logtest.Log4jTest-logTest(29)]: debug级别的日志输出
     [2016-02-23 00:39:56]-[main- INFO]-[org.linkinpark.commons.logtest.Log4jTest-logTest(32)]: info级别的日志输出
     [2016-02-23 00:39:56]-[main- WARN]-[org.linkinpark.commons.logtest.Log4jTest-logTest(33)]: warn级别的日志输出
     [2016-02-23 00:39:56]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest-logTest(34)]: error级别的日志输出
     [2016-02-23 00:39:56]-[main-FATAL]-[org.linkinpark.commons.logtest.Log4jTest-logTest(35)]: fatal级别的日志输出
     [2016-02-23 00:39:56]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest-logTest(42)]: / by zero
     

    OK,下一篇我会整理到日志的输出组件Appender。

  • 相关阅读:
    matlab cell
    matlab linux 快捷键设置——有问题还是要解决
    latex 小结
    TOJ 1258 Very Simple Counting
    TOJ 2888 Pearls
    HDU 1248 寒冰王座
    TOJ 3486 Divisibility
    TOJ 3635 过山车
    TOJ 1840 Jack Straws
    HDU 4460 Friend Chains
  • 原文地址:https://www.cnblogs.com/LinkinPark/p/5232851.html
Copyright © 2011-2022 走看看