日志门面和日志框架(日志实现框架log4j2)

一、log4j2简介

Apache Log4j 2是对Log4j的升级,是最优秀的java日志框架。

二、log4j2特征

性能提升:Log4j2包含基于LMAX Disruptor库的下一代异步记录器。在多线程场景中,异步记录器的吞吐量比log4j和logback高18倍,延迟低。

自动重新加载配置:与logback一样,log4j2可以在修改时自动重新加载其配置。与logback不同,它会在重新配置时不会丢失日志事件。

高级过滤:与logback一样,log4j2支持基于log事件中的上下文数据,标记,正则表达式和其他组件进行过滤。此外,过滤器还可以与记录器关联。与logback不同,logback可以在任何这些情况下使用通用的Filter类。

插件架构:log4j2使用插件模式配置组件。因此,无需编写代码来创建和配置Appender,layout,pattern Converter等。在配置了的情况下,log4j2自动识别插件并使用它们。

无垃圾机制:在稳定日志记录期间,log4j2在独立应用程序中是无垃圾的,在web应用程序中是低垃圾。这减少了垃圾收集器的压力,并且可以提供更好的响应性能。

总之:SLF4j+Log4j2的组合,是市场上最强大的日志功能实现方式。

三、slf4j集成log4j2

1. slf4j集成log4j2步骤共4步

  1. 导入slf4j日志门面
  2. 导入log4j2的适配器
  3. 导入log4j2日志门面
  4. 导入log4j2日志实现
<!--slf4j日志门面 -->
<dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.32</version>
</dependency>
<!--log4j2适配器 -->
      <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-slf4j-impl</artifactId>
      <version>2.14.1</version>
</dependency>
<dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-api</artifactId>
      <version>2.14.1</version>
</dependency>
<!--log4j2日志实现 -->
<dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>2.14.1</version>
</dependency>

2. 集成原理

slf4j门面调用的是log4j2的门面,再由log4j2的门面调用log4j2的实现。

四、log4j2配置文件

log4j2是参考logback创作出来的,所以配置文件也是使用xml。log4j2同样是默认加载类路径(resources)下的log4j2.xml文件中的配置。

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <!--配置appender -->
    <Appenders>
        <Console name="consoleAppender" target="SYSTEM_ERR"></Console>
    </Appenders>

    <!--配置logger -->
    <Loggers>
        <!--配置rootlogger -->
        <Root level="info">
            <AppenderRef ref="consoleAppender"></AppenderRef>
        </Root>
    </Loggers>
</configuration>

五、日志文件输出

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>

    <!--全局配置 -->
    <properties>
        <property name="logDir">F:\\project\\springboot_log</property>
        <property name="pattern" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L  %thread %m%n"></property>
    </properties>

    <!--配置appender -->
    <Appenders>
        <!--控制台输出 -->
        <Console name="consoleAppender" target="SYSTEM_ERR"></Console>
        <!--配置文件输出 -->
        <File name="fileAppender" fileName="${logDir}\\log4j2.log">
            <!--配置文件输出格式 -->
            <PatternLayout pattern="${pattern}"></PatternLayout>
        </File>
    </Appenders>

    <!--配置logger -->
    <Loggers>
        <!--配置rootlogger -->
        <Root level="info">
            <AppenderRef ref="consoleAppender"></AppenderRef>
            <AppenderRef ref="fileAppender"></AppenderRef>
        </Root>
    </Loggers>
</configuration>

六、日志文件的拆分和压缩

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>

    <!--全局配置 -->
    <properties>
        <property name="logDir">F:\\project\\springboot_log</property>
        <property name="pattern" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L  %thread %m%n"></property>
    </properties>

    <!--配置appender -->
    <Appenders>
        <!--按照指定规则来拆分日志文件
         fileName:日志文件名字
         filePattern:日志文件拆分后文件的明明规则
                $${date:yyyy-MM-dd}:根据日期当天,创建一个文件夹
                rolllog-%d{yyyy-MM-dd-HH-mm}-%i.log:为文件命名的规则:%i表示序号,从0开始,目的是为了让每一份文件名字不会重复
         -->
        <RollingFile name="rollingFile" fileName="${logDir}\\rolllog.log"
                     filePattern="${logDir}/$${date:yyyy-MM-dd}/rolllog-%d{yyyy-MM-dd-HH-mm}-%i.log">
            <!-- 日志消息格式-->
            <PatternLayout pattern="${pattern}"></PatternLayout>
            <Policies>
                <!--在系统启动时,触发拆分规则,产生一个日志文件-->
                <OnStartupTriggeringPolicy></OnStartupTriggeringPolicy>
                <!--按照文件的大小进行拆分 -->
                <SizeBasedTriggeringPolicy size="1KB"></SizeBasedTriggeringPolicy>
                <!--按照时间节点进行拆分,拆分规则就是 filePattern-->
                <TimeBasedTriggeringPolicy></TimeBasedTriggeringPolicy>
            </Policies>
            <!--在同一目录下,文件的个数限制,如果超出了设置的数值,则根据时间进行覆盖,新的覆盖旧的规则 -->
            <DefaultRolloverStrategy max="30"></DefaultRolloverStrategy>
        </RollingFile>
    </Appenders>

    <!--配置logger -->
    <Loggers>
        <!--配置rootlogger -->
        <Root level="info">
            <AppenderRef ref="rollingFile"></AppenderRef>
        </Root>
    </Loggers>
</configuration>

七、异步日志

log4j2提供了两种实现日志的方式,一个是通过AsyncAppender,一个是通过AsyncLogger,分别对应前面的Appender组件和Logger组件。

1. AsyncAppender方式

AsyncAppender方式是通过引用别的Appender来实现,当有日志事件到达时,会开启另外一个线程来处理它们。需要注意的是,如果在Appender的时候出现异常,对应用来说是无法感知的。

扫描二维码关注公众号,回复: 14586424 查看本文章

AysncAppender应该在它引用的Appender之后配置,默认使用java.util.concurrent.ArrayBlockingQueue实现而不需要其它外部的类库。当使用此Appender的时候,在多线程的环境下需要注意,阻塞队列容易受到锁争用的影响,这可能会对性能产生影响。这时候,我们应该考虑使用无锁的异步记录器(AsyncLogger).

2. AsyncLogger方式(最推荐混合异步)

AsyncLogger才是log4j2实现异步最重要的功能体现,也是官方推荐的异步方式。

它可以使得调用Logger.log返回的更快。可以有两种选择:全局异步和混合异步。

全局异步:所有的日志都异步的记录,在配置文件上不用做任何改动,只需要在jvm启动的时候增加一个参数即可实现。

混合异步:可以在应用中同时使用同步日志和异步日志,这使得日志的配置方式更加灵活。虽然Log4j2提供一套异常处理机制,可以覆盖大部分状态,但是还是有一小部分的特殊情况是无法完全处理的,比如我们如果是记录审计日志(特殊情况之一),那么官方就推荐使用同步日志的方式,二对于其他的一些仅仅是记录一个程序日志的地方,使用异步日志将大幅提升性能,减少应用本身的影响。

        混合异步的方式需要通过修改配置文件来实现,使用AsyncLogger标记配置

八、AsyncAppender方式异步日志

1. 实现步骤

1. 添加异步日志的依赖

 <!--异步日志依赖 -->
<dependency>
      <groupId>com.lmax</groupId>
      <artifactId>disruptor</artifactId>
      <version>3.4.3</version>
</dependency>

2. 在Appender标签中,对于异步进行配置,使用Async标签

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <!--配置appender -->
    <Appenders>
        <!--控制台输出 -->
        <Console name="consoleAppender" target="SYSTEM_OUT"></Console>
        <!-- 配置异步-->
        <Async name="myAsync">
            <!-- 将控制台输出异步的操作-->
            <AppenderRef ref="consoleAppender"></AppenderRef>
        </Async>

    </Appenders>

    <!--配置logger -->
    <Loggers>
        <!--配置rootlogger -->
        <Root level="info">
            <AppenderRef ref="myAsync"></AppenderRef>
        </Root>
    </Loggers>
</configuration>

3. rootlogger引用Async,如上图

九、AsyncLogger-全局异步日志

全局异步:所有的日志都是异步的日志记录,在配置文件上不用做任何的改动。只需要在类路径resources下添加一个properties属性文件,做异步配置即可。

        文件要求是:文件名必须为log4j2.component.properties

                文件内容为键值对:Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector

十、AsyncLogger-混合异步日志(推荐使用)

混合异步:可以在应用中同时使用同步日志和异步日志,这使得日志的配置和输出会更加的灵活。

需求:假设我们有自定义的logger -- com.atredhorse,让自定义的Logger是异步的。让rootLogger是同步的,也即其他包下是同步的。

<!--配置logger -->
    <Loggers>
        <!--自定义logger,让自定义的logger为异步logger-->
        <!-- includeLocation="false" 表示取出日志记录中的行号信息,这个行号信息非常的影响日志记录的效率,
            生产中都不加这个行号
            additivity="false":表示不继承rootlogger-->
        <AsyncLogger name="com.atredhorse" level="debug"
                includeLocation="false" additivity="false">
            <AppenderRef ref="consoleAppender"></AppenderRef>
        </AsyncLogger>
        <!--配置rootlogger -->
        <Root level="info">
            <AppenderRef ref="consoleAppender"></AppenderRef>
        </Root>
    </Loggers>

总之:如果使用异步日志,AsyncAppender、AsyncLogger不要同时出现,没有这个需求,效果也不会叠加。如果同时出现,那么效率会以AsyncAppender为主。

        AsyncLogger的全局异步和混合异步也不要同时出现,没有这个需求,效果也不会叠加。

猜你喜欢

转载自blog.csdn.net/weixin_51725434/article/details/128652343
今日推荐