log4j

Posted Desneo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了log4j相关的知识,希望对你有一定的参考价值。

1. 描述和备注

a). 两种配置方式,log4j.xml和log4j.properties
b). 由3个东西组成,
        "logger"--负责采集日志,程序中使用,有继承关系
        "appender"--负责日志输出到哪里,控制台或文件
        "layout"--定义日志输出的格式
        

1.1 Maven

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

1.14 日志打印时组件调用顺序

a). 日志信息传入 Logger.
b). 将日志信息封装成 LoggingEvent 对象并传入 Appender.
c). 在 Appender 中调用 Filter 对日志信息进行过滤,调用 Layout 对日志信息进行格式化,然后输出.

3. log4j.xml

3.1. 参考使用规则

a). 对于info、warning和error这几种错误,都需要输出到文件去,而且是不同的文件
b). 自动按天新建文件,避免单个日志文件过大
c). debug信息不需要输出到文件,只需要在控制台中显示
d). spring框架输出的debug信息太多,要屏蔽

3.2 Appender--日志位置

Log4j 提供的 appender 有以下几种: 
    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 (将日志信息以流格式发送到任意指定的地方) 

3.2.1 示例-每天输出一个日志

<!--设置通道名称是:file,输出方式DailyRollingFileAppender-->  
<appender name="FILE" class="org.jboss.logging.appender.DailyRollingFileAppender">  

    <!--日志文件路径和文件名称 -->  
    <param name="File" value="${jboss.server.home.dir}/log/server.log"/>  

    <!-- 设置是否在重新启动服务时,在原有日志的基础添加新日志 -->  
    <param name="Append" value="false"/>  
    <!-- Rollover at midnight each day -->  
    <param name="DatePattern" value="‘.‘yyyy-MM-dd"/>  
    <!-- Rollover at the top of each hour <param name="DatePattern" value="‘.‘yyyy-MM-dd-HH"/> -->   
    
    <!-- 日志输出格式 -->
    <layout class="org.apache.log4j.PatternLayout">  
        <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>  
    </layout>  

</appender>  

3.2.2 cmi中实际使用示例

    <appender name="SYSTEM_RUN_FILE"
              class="com.huawei.mdn.cms.log.CMSAppender">
        <param name="File" value="../logs/run/CMI_system_run" />
        <param name="MaxFileSize" value="&runLogSize;" />
        <param name="MaxBackupIndex" value="20" />
        <param name="Append" value="true" />
        
        <layout class="com.huawei.mdn.cms.log.MdnSystemRunLogLayout"/>
        
        <filter class="org.apache.log4j.varia.LevelRangeFilter">
            <param name="LevelMin" value="INFO"/>
            <param name="LevelMax" value="FATAL"/>
        </filter>

    </appender>

3.2.3 filter标签

    <!--过滤器设置输出的级别-->       
    <filter class="org.apache.log4j.varia.LevelRangeFilter">       
        <param name="levelMin" value="debug" />       
        <param name="levelMax" value="warn" />       
        <param name="AcceptOnMatch" value="true" />       
    </filter> 

3.2.5 自定义Appender--如把日志发送到flute

继承AppenderSkeleton类-->[一般]实现Append方法即可

 

3.4. layout--日志格式

//内置layout
    org.apache.log4j.htmlLayout(以HTML表格形式布局),
    org.apache.log4j.PatternLayout(可自定义布局和输出内容)-- 常用 
    org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
    org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

Log4J采用类似C的printf函数的格式化日志,打印参数如下: -- 常用 “[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n”
    %m  输出代码中指定的消息
    %p  输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
    %r  输出自应用启动到输出该log信息耗费的毫秒数
    %c  输出所属的类目,通常就是所在类的全名
    %t  输出产生该日志事件的线程名
    %n  输出一个回车换行符,Windows平台为“rn”,Unix平台为“n”
    %d  输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
    %l  输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)
    %M   调用logger的方法名。
    

3.4.1 示例参见3.3.1节

    <layout class="org.apache.log4j.PatternLayout">  
        <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>  
    </layout>  
</appender>  

3.4.2 自定义layout--自定义输出格式

继承 TTCCLayout等内置的layout,或是layout接口-->实现format方法即可
public class MdnDebugLogLayout extends TTCCLayout
{
    private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";

    public MdnDebugLogLayout()
    {
    }

    @SuppressWarnings("unchecked")
    public String format(LoggingEvent event)
    {
        LocationInfo locationInfo = event.getLocationInformation();
        String lineNumber = locationInfo.getLineNumber();
        String fileName = locationInfo.getFileName();
        String threadName = event.getThreadName();
        String message = event.getRenderedMessage();

        setDateFormat(DATE_FORMAT);
        buf.setLength(0);
        buf.append("[");
        buf.append(threadName);
        buf.append("]");
        dateFormat(buf, event);//日期时间
        buf.append("|");
        buf.append(event.getLevel().toString());//级别为debug
        buf.append("|");
        buf.append("CMI");//模块
        buf.append("|");
        String traceID = TraceContextHolder.getDataContext().getTraceID();//traceID
        if (traceID != null)
        {
            buf.append(traceID);
        }
        buf.append("|");
        buf.append(message);//代码中指定的消息
        buf.append("|||");
        buf.append(fileName);
        buf.append("-");
        buf.append(lineNumber);
        buf.append(Layout.LINE_SEP);

        return buf.toString();
    }

    @Override
    public void dateFormat(StringBuffer buf, LoggingEvent event)
    {
        if (dateFormat != null)
        {
            date.setTime(event.timeStamp);
            dateFormat.format(date, buf, pos);
        }
    }
}

3.5 catagory/root标签--定义打印日志的包

Logger Logger = LogManager.getLogger("categorylog");   (<category标签的name属性>) -->  category --> Appender 

category的name,指定的是控制某个包下的日志 , 可以按照业务逻辑进行日志分类输出打印 
root是控制整个工程的日志
root和category都是通过<appender-ref ref="CONSOLE"/>执行具体appender中的日志策略,配置哪个appender执行哪个
root和category是父子关系,root标签可以不写,category也可以不写 , 但是必须写一个
       category的属性additivity="false"表示在category中定义日志输在root中过滤掉

例如:定义name = “userManagerLog” , 那么在代码中与用户管理相关的业务引入日志的时候  LogManager.getLogger(“userManagerLog”) ,
    则可以通过控制一个业务逻辑的日志打到一个文件下
    <appender name="FILE-DEBUG" class="org.apache.log4j.DailyRollingFileAppender">  
        <param name="DatePattern" value="‘.‘yyyyMMdd" />  
        <param name="Append" value="true"/>  
        <param name="Threshold" value="DEBUG"/>  
        <param name="Encoding" value="UTF-8"/>  
        <param name="file" value="${profile.log.root.path}/${profile.log.name.web}/${profile.log.name.web}-debug.log"/>  
        <layout class="org.apache.log4j.PatternLayout">  
            <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%7r] %-5p %c %M:%L - %m%n"/>  
        </layout>  
    </appender>  
  
    <!-- 日志过滤,只打印 com.portal.controller路径下日志 -->
    <category name="com.portal.controller">  
        <priority value="INFO"/>  
        <appender-ref ref="CONSOLE"/>  
    </category>  
  
    <root>  
        <priority value="INFO"/>  
        <appender-ref ref="CONSOLE"/>  
        <appender-ref ref="FILE-DEBUG"/>  
    </root>  
</log4j:configuration>  

以上是关于log4j的主要内容,如果未能解决你的问题,请参考以下文章

log4j怎样控制只输出自己写的代码的日志,不输出框架中的日志

Log4j反序列化远程代码执行漏洞(CVE-2019-17571)

由log4j远程执行漏洞说起

混合 log4j 1.x 和 log4j 2

Java 标准日志工具 Log4j 的使用(附源代码)

log4jspringboot项目启动 ,使用的druid数据源,log4j报错 log4j:WARN Please initialize the log4j system properly.(代码片