zoukankan      html  css  js  c++  java
  • Logging的这点小事

    真正做项目,才发觉Logging的好处和学问。自己胡搞的时候,常常使用System.out.println作为输出。

    但实际的项目,尤其是library比较多的时候,好好配置好Logging,才能在后面的工作以及追查结果时,事半功倍。否则,很有可能无法获取所有的log以致无法追查问题发生的原因。

    首先介绍的,是最传统的log4j。log4j的使用相当简单。例子如下:

    // 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");

    值得注意的,是log4j的日志优先级:TRACE<DEBUG<INFO<WARN<ERROR<FATAL;以及,日志的配置文件和方法:

    #1. Logger: Logger分根Logger(Root Logger)和其它类Logger;主要是定义日志优先级和是否Additivity:

        <!-- root logging -->
        <root>
            <priority value ="INFO" />
            <appender-ref ref="console"/>
            <appender-ref ref="common"/>
        </root>
    
        <!-- specific logger for abc -->
        <logger name="com.test.abc" additivity="false">
            <level value="INFO"/>
            <appender-ref ref="AAppender" />
        </logger> 

    log4j.additivity指定特定包下的类的日志信息是否输出到rootLogger中,true表示输出,false表示不输出。

    #2. Appender: Appender是真正进行日志记录的类;通常的做法是通过配置不同的Appender分发给不同的Logger,达到多层级日志的目的:

      <appender name="console" class="org.apache.log4j.ConsoleAppender">
            <param name="Target" value="System.out"/>
            <layout class="org.apache.log4j.PatternLayout">
                <param name="ConversionPattern" value="%d{yyyMMdd HH:mm:ss} [%-5p] %m --By %t : %l%n"/>
            </layout>
        </appender>
        
        <!-- for common logging -->
        <appender name="common" class="org.apache.log4j.DailyRollingFileAppender">
            <param name="File" value="logs/common.log"/>
            <param name="Threshold" value="DEBUG"/>
            <param name="DatePattern" value="'.'yyyyMMdd"/>
            <layout class="org.apache.log4j.PatternLayout">
                <param name="ConversionPattern" value="%d{yyyyMMdd HH:mm:ss} [%-5p] %m --By %t : %l%n"/>
            </layout>
        </appender>
    
        <!-- for journal logging-->
        <appender name="AAppender" class="org.apache.log4j.DailyRollingFileAppender">
            <param name="File" value="logs/a.log"/>
            <param name="Threshold" value="DEBUG"/>
            <param name="DatePattern" value="'.'yyyyMMdd"/>
            <layout class="org.apache.log4j.PatternLayout">
                <param name="ConversionPattern" value="%d{yyyyMMdd HH:mm:ss} [%-5p] %m --By %t
    "/>
            </layout>
        </appender>

    Appender的配置非常丰富,也有不少定义好的Appender可以选择(ConsoleAppender, DailyRollingFileAppender),这里不展开,详细的配置可以参考官网。

    #3. Category:log4j.category是对日志类别的补充说明,可以指定特定包下的日志使用category指定的日志级别和appender。例如:

    <category name="org.springframework.jdbc.core.namedparam">   
         <priority value="ERROR"/>
    </category>

    这样,某个特定的类,例如spring下的这个包的类,输出的日志级别提高到了ERROR

    由于历史原因,不同的库使用的logging framework并不一样,例如大名鼎鼎的Spring,使用的其实是commons-logging,还有Java本身的logging framework。如果不统一起来管理,那么Spring发生的错误,只会通过commons-logging输出到console,而不会被log4j记录下来。所以,不同的日志系统,需要统一起来管理,统一由log4j输出。这样,就需要SLF4J.

    SLF4J本质上,就是做刚刚所说的统一管理Logging的工作,真正日志记录的工作,交给log4j。Spring用commons-logging对吧,没问题,SLF4J有一个包是jcl-over-slf4j,把commons-logging的日志输出到SLF4J;又例如LMAX Disruptor是用java.util.logging,也没问题,SLF4J有一个包是jul-to-slf4j,把java的logging输出到SLF4J。那么SLF4J输出到哪里了?通过slf4j-log4j12这个包,输出到log4j这里,统一在输出到各自的appender那里。

    这样,可以保证所有的日志,都可以被记录下来。

    需要注意的是,使用jul-to-slf4j时,需要代码上开启桥接java.util.logging到slf4j:

            // Enable logging of Disruptor point to slf4j
            LogManager.getLogManager().reset();
            SLF4JBridgeHandler.install();

    本文完

  • 相关阅读:
    linux下LD_PRELOAD的用处
    三个通用的脚本,处理MySQL WorkBench导出表的JSON数据进SQLITE3
    ubuntu 18.04下,KMS_6.9.1服务器启动后,客户端连接一段时间因为libnice而crash的问题修复
    Daliy Algorithm(线段树&组合数学) -- day 53
    Daliy Algorithm(链表&搜索&剪枝) -- day 52
    Daliy Algorithm(二分&前缀和) -- day 51
    每日算法
    动态规划--01背包模型
    每日算法
    每日算法
  • 原文地址:https://www.cnblogs.com/techyc/p/3596537.html
Copyright © 2011-2022 走看看