Java日志体系(log4j2)

1 log4j2

1.1 简介

log4j2,一个日志的实现框架,是log4j的升级版本,于2014年7月正式亮相。与第一代log4j不同,log4j2完全重写了log4j的日志实现,并不是在原有基础上进行的升级,解决了log4j中的一些问题,例如:多线程下性能低下、api不支持占位符{}的使用、配置文件不能自动重新加载等。

为什么说log4j在多线程情况下性能低下呢?主要是synchronized锁在作怪,当我们的log4jzai 获取appender对象时,需要进行加锁处理;而接下来对appender操作(将要进行日志打印)时,也进行了加锁处理,这样一来性能自然得不到提升,从而导致整个应用的qps下降。

而在log4j2中,由于引入了异步logger,使得log4j2的性能得到了巨大的提升,相比于log4j,logback而言,提升了数10倍之多。关于异步logger的情况,我们后面进行讲解。

1.2 log4j2结构


LoggerContext:Logger上下文,主要负责读取log4j2的配置以及获取Logger对象的工作;

Logger:日志对象,负责日志信息的打印;跟之前的几个日志框架相同,log4j2也包含了5大日志级别,分别为TRACE,DEBUG,INFO,WARN,ERROR 以及FATAL;具体等级如下:TRACE < DEBUG < INFO < WARN < ERROR < FATAL;

LoggerConfig:Logger的配置对象,每一个Logger的配置信息就是一个LoggerConfig对象;

Configuration:log4j2配置文件的解析,当我们的配置文件是xml的格式时,具体的实现是XmlConfiguration;每一个LoggerContext都有一个Configuration对象,包含了所有的Appender、Filter、LoggerConfig

1.3 使用

首先,需要在应用的pom.xml中添加依赖:

  <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.8.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.8.2</version>
    </dependency>

其次,声明测试代码:

public class log4j2Demo {

    private Logger logger = LogManager.getLogger(log4j2Demo.class);

    @Test
    public void test() throws InterruptedException {
        logger.error("Error Message!");
        logger.warn("Warn Message!");
        logger.info("Info Message!");
        logger.debug("Debug Message!");
        logger.trace("Trace Message!");
    }
}

最后,在classpath下声明配置文件:log4j2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info" monitorInterval="30">
    <Appenders>
        <!--控制台-->
        <Console name="Console" target="SYSTEM_OUT">-->
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>

        <!--普通文件:-->
        <File name="File" fileName="e:/log.out" append="true" immediateFlush="true" >
            <PatternLayout>
                <Pattern>%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %L- %msg%n</Pattern>
            </PatternLayout>
        </File>
    </Appenders>
    <Loggers>
        <Root level="debug" >
            <AppenderRef ref="File"/>
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

通过以上步骤,log4j2就可以正常的运行了。

1.4 log4j2配置文件详解

与log4j不同的是,log4j2只支持.xml或者.json格式的配置文件,不在支持.properties格式的配置文件。那么,下面我们就以.xml来进行讲解:

默认情况下,系统会在classpath下查找配置文件:(按照以下顺序)

1.classpath下名为 log4j-test.json 或者log4j-test.jsn文件
2.classpath下名为 log4j2-test.xml
3.classpath下名为 log4j.json 或者log4j.jsn文件
4.classpath下名为 log4j2.xml

请注意,此处我们常用的是log4j2.xml,这块与log4j不同;

以下是log4j2常用的配置信息:(逐一进行讲解)

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info" monitorInterval="30">
    <Appenders>

        <!--控制台-->
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>

        <!--普通文件:-->
        <File name="File" fileName="e:/log.out" append="true" immediateFlush="false" bufferedIO="true" bufferSize="1024">
            <PatternLayout>
                <Pattern>%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %L- %msg%n</Pattern>
            </PatternLayout>
        </File>

        <!--异步appender:-->
        <Async name="Async">
            <AppenderRef ref="File"/>
        </Async>

        <!--循环写入文件:-->
        <RollingFile name="RollingFile" fileName="e:/log.out" filePattern="e:/app-%d{yyyy-MM-dd_HH-mm}-%i.out">
            <PatternLayout>
                <Pattern>%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</Pattern>
            </PatternLayout>
            <!--滚动策略:-->
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <SizeBasedTriggeringPolicy size="100 kb"/> 
            </Policies>
            <DefaultRolloverStrategy max="5"/>
        </RollingFile>

    </Appenders>

    <Loggers>
       
        <!--单独指定logger-->
        <Logger name="com.jiaboyan.logDemo.log4j2Demo" level="info" additivity="false" includeLocation="true">
            <AppenderRef ref="File"/>
        </Logger>
        
        <!--根logger-->
        <Root level="info" >
            <AppenderRef ref="Async"/>
            <AppenderRef ref="File"/>
            <AppenderRef ref="Console"/>
        </Root>
        
        <!--异步logger-->
        <AsyncRoot level="info">
            <AppenderRef ref="File"/>
        </AsyncRoot>
    </Loggers>

</Configuration>

1.Configuration -- 根节点

<Configuration status="debug" monitorInterval="30"></Configuration>
    Configuration:表示log4j2中的Configuration对象,实际为XmlConfiguration;
    
    status:表示log4j2本身的日志信息打印级别,当设置为TRACE 或者 DEBUG 级别时,便会打印出log4j2内部初始化的一些日志信息; 
    
    monitorInterval:表示每隔一定时间重新加载log4j2配置文件,单位秒;

2.Appenders -- Console

<Console name="Console" target="SYSTEM_OUT">
    <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>

name:表示控制台Appender的名称,<logger>中会依赖此名称,起名没有具体要求,但最好简明直译;

target:表示ConsoleAppender使用哪种方式将日志输出到控制台,一般调用System.out.println()方法;

PatternLayout--pattern:表示日志信息输出的格式;

3.Appenders -- File

<File name="File" fileName="e:/log.out" append="true" immediateFlush="false" bufferedIO="true" bufferSize="8096">
    <PatternLayout>
        <Pattern>%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %L- %msg%n</Pattern>
    </PatternLayout>
</File>

name:表示文件Appender的名称,<logger>中会依赖此名称,起名没有具体要求,但最好简明直译;

fileName:表示生成的日志文件名称;

append:表示新生成的日志是否追加到日志文件中,如果为true则表示追加,false表示覆盖原有日志信息;

immediateFlush:表示日志打印请求是否立即输出,true为立即,false表示使用缓存;

bufferedIO:表示日志打印请求是否使用缓存,true为使用,false为不使用;

bufferSize:表示日志打印请求的使用缓存的大小,默认为8096字节;

PatternLayout--pattern:同上;

4.Appenders -- RollingFile

<RollingFile name="RollingFile" fileName="e:/log.out" filePattern="e:/app-%d{yyyy-MM-dd_HH-mm}-%i.out">
    <PatternLayout>
        <Pattern>%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</Pattern>
    </PatternLayout>
    <Policies>
        <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
        <CronTriggeringPolicy schedule="0 0 * * * ?"/>
        <SizeBasedTriggeringPolicy size="100 kb"/> 
    </Policies>
    <DefaultRolloverStrategy max="5"/>
</RollingFile>

name:表示滚动文件Appender的名称,<logger>中会依赖此名称,起名没有具体要求,但最好简明直译;

fileName:表示当前日志所在的日志文件名称; 

filePattern:表示滚动日志的文件名称模板,当日志文件进行滚动后,滚动后的文件按照此模板进行命名;

PatternLayout--pattern:同上;

Policies:表示日志文件滚动策略;

Policies -- TimeBasedTriggeringPolicy:表示日志文件按照时间间隔来进行滚动;

Policies -- CronTriggeringPolicy:表示日志文件按照设置的时间点来进行滚动;

Policies -- SizeBasedTriggeringPolicy:表示日志文件按照文件大小来进行滚动;

DefaultRolloverStrategy:表示log4j2进行滚动后保存的日志文件数量,默认为7个;

5.TimeBasedTriggeringPolicy

<TimeBasedTriggeringPolicy interval="1" modulate="true"/>

TimeBasedTriggeringPolicy表示按照时间间隔来进行日志文件的滚动,间隔单位可以是分钟、小时,具体需要根据filePattern的格式来进行判别;
例如filePattern="e:/app-%d{yyyy-MM-dd_HH-mm}-%i.out",则表示mm(分钟)为单位;

interval:表示分隔日志的时间间隔大小,如果时间间隔单位是分钟,则表示相隔1分钟、10分钟等进行一次日志分隔;

modulate:表示是否对分隔时间进行调制;如果设置为true则表示分隔的时间从每天的0点、每小时的0分钟开始进行计算,每间隔多久进行一次切割;比如,modulate=true,interval=4hours,那么假设上次封存日志的时间为03:00,则下次封存日志的时间为04:00,之后的封存时间依次为08:00,12:00,16:00。。。

6.CronTriggeringPolicy

<CronTriggeringPolicy schedule="0 0 * * * ?"/>

CronTriggeringPolicy表示按照Cron表达式设置的时间点进行切割日志;

schedule:表示设置的cron表达式;

7.SizeBasedTriggeringPolicy

<SizeBasedTriggeringPolicy size="100 kb"/> 

SizeBasedTriggeringPolicy表示按照规定的日志文件大小进行切割日志;

size:表示进行切割日志文件大小的极值,当日志文件大小满足size的值时,就会进行日志的切割;

DefaultRolloverStrategy

<DefaultRolloverStrategy max="5"/>

DefaultRolloverStrategy表示log4j2每单位时间内最多能保存多少个日志切割文件,一般与SizeBasedTriggeringPolicy结合使用;

max:表示保存的最大值,默认为7;

例如:你的log4j2.xml设置如下:fileName="e:/log.out" filePattern="e:/app-%d{yyyy-MM-dd_HH-mm}-%i.out"
那么在每分钟内,你可以保留2个日志切割文件,多余的日志进行覆盖;

8.Appenders -- Async

<Async name="Async">
    <AppenderRef ref="File"/>
</Async>

name:表示异步Appender的名称,<logger>中会依赖此名称,起名没有具体要求,但最好简明直译;
异步Appender使用消费者生产者模式进行日志信息的打印,适用于并发量较大的情况;

9.PatternLayout

<PatternLayout>
    <Pattern>%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</Pattern>
</PatternLayout>

Pattern:设置输出的日志信息格式;具体格式如下:

%d{yyyy-MM-dd HH:mm:ss, SSS} : 日志生产时间
%t : 线程名称
%p : 日志级别
%level : 日志级别
%c : logger的名称
%logger : logger的名称
%C : Java类名
%m : 日志内容
%n : 换行符
%L : 日志输出所在行数
%M : 日志输出所在方法名

10.Loggers -- Logger

<Logger name="com.jiaboyan.logDemo.log4j2Demo" level="info" additivity="false">
    <AppenderRef ref="File"/>
</Logger>

在<Loggers>节点下,对某个类单独进行日志配置,便可使用<logger>节点;
上例中,我们对名称为com.jiaboyan.logDemo.log4j2Demo的类进行日志配置。
level指定级别,additivity表示是否向上传递打印日志信息(若为true则向上传递,那么root根对象也会进行日志打印);

11.Loggers -- Root

<Root level="info" >
    <AppenderRef ref="Async"/>
    <AppenderRef ref="File"/>
    <AppenderRef ref="Console"/>
</Root>

Root根日志节点,指定具体的日志级别,以及使用何种Appender进行日志输出;

12.Loggers -- AsyncRoot

<AsyncRoot level="info" includeLocation="false">
    <AppenderRef ref="File"/>
</AsyncRoot>
    
如果想使用异步logger,还需要在pom.xml中添加disruptor的依赖。
includeLocation结合异步logger使用,当其设置为true时,才会显示具体的行号,以及日志所在的类名;
如果设置为false,哪怕<Pattern>设置了输出行号也不会显示出来;

1.5 log4j2源码分析

暂略

1.6 log4j2性能测试

Java日志框架性能比较

1.7 DISRUPTOR RING BUFFER介绍

暂略

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • 在应用程序中添加日志记录总的来说基于三个目的:监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析...
    时待吾阅读 4,817评论 1 13
  • 在应用程序中添加日志记录总的来说基于三个目的:监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析...
    时待吾阅读 4,907评论 0 6
  • log4j 1.1 简介 Log4j是一个由Java编写可靠、灵活的日志框架,是Apache旗下的一个开源项目;现...
    贾博岩阅读 7,780评论 1 31
  • 一、Log4j简介 Log4j有三个主要的组件:Loggers(记录器),Appenders (输出源)和Layo...
    默默守护阅读 1,863评论 2 8
  • from:https://www.cnblogs.com/ITtangtang/p/3926665.html一、L...
    enshunyan阅读 3,173评论 0 0