log4j2的使用

一. log4j2简介

log4j2是log4j 1.x 的升级版,参考了logback的一些优秀的设计,并且修复了一些问题,因此带来了一些重大的提升。

  • 性能提升, log4j2相较于log4j 1和logback都具有很明显的性能提升,支持异步日志处理。
  • 自动重载配置,参考了logback的设计,当然会提供自动刷新参数配置,在生产上可以动态的修改日志的级别而不需要重启应用。
  • log4j2不再支持properties文件了,只支持xml,json或是yaml。
  • 功能结构
    日志框架:slf4j
    日志实现:log4j2
    桥接包:log4j-slf4j-impl
<!-- 日志实现 -->
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-core</artifactId>
			<version>2.1</version>
		</dependency>
		<!-- 日志桥接包   桥接包的版本须对应log4j2的版本 -->
  		<dependency>
		    <groupId>org.apache.logging.log4j</groupId>
		    <artifactId>log4j-slf4j-impl</artifactId>
		    <version>2.1</version>
		</dependency>
		<!-- 日志框架(门面) -->
		<dependency>
		    <groupId>org.slf4j</groupId>
		    <artifactId>slf4j-api</artifactId>
		    <version>1.7.7</version>
		</dependency>
二. SpringBoot2.x集成Log4j2

spring boot 默认采用lobback作为日志实现框架,需要排除logback的依赖。

1.pom文件添加
<!-- 集成Log4j2日志 -->
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
2.application.properties文件添加
logging.config=classpath:log4j2.xml
3.resources文件夹下编辑log4j2.xml文件
?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">

    <Appenders>
        <Console name="STDOUT" target="SYSTEM_OUT">
            <!-- <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> -->
            <PatternLayout pattern=".%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%file:%line]
                %-5level %logger{36} - %msg %n"/>
        </Console>

        <RollingFile name="RollingFile" fileName="logs/app.log"
                     filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log">
            <PatternLayout>
                <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%file:%line] %-5level %logger{35} - %msg %n</Pattern>
            </PatternLayout>
            <Policies>
                <TimeBasedTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="102400KB"/>
            </Policies>
            <DefaultRolloverStrategy fileIndex="max" max="2"/>
        </RollingFile>
    </Appenders>
    <Loggers>

        <Root level="info">
            <AppenderRef ref="STDOUT"/>
            <AppenderRef ref="RollingFile"/>
        </Root>
    </Loggers>

</Configuration>
  • Appender
    Appender就是一个管道,定义了日志内容的去向(保存位置)。
    配置一个或者多个Filter,Filter的过滤机制和Servlet的Filter有些差别,下文会进行说明。
    配置Layout来控制日志信息的输出格式。
    配置Policies以控制日志何时(When)进行滚动。
    配置Strategy以控制日志如何(How)进行滚动。
  • Logger
    Logger就是一个路由,指定类、包中的日志信息流向哪个管道,以及控制他们的流量(日志级别)
三.异步日志

log4j2最大的特点就是异步日志,增加消息队列作为缓存,Log4j2提供了两种实现日志的方式,一个是通过AsyncAppender,一个是通过AsyncLogger,分别对应前面我们说的Appender组件和Logger组件。

AsyncAppender方式

默认使用 java.util.concurrent.ArrayBlockingQueue实现。 在多线程的环境下阻塞队列容易受到锁争用的影响,这可能会对性能产生影响。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <File name="MyFile" fileName="logs/app.log">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
    </File>
    <Async name="Async">
      <AppenderRef ref="MyFile"/>
    </Async>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Async"/>
    </Root>
  </Loggers>
</Configuration>
AsyncLogger方式

官方推荐的异步方式,速度更快,分为全局异步和混合异步,采用disruptor非阻塞消息队列。

  • 全局异步
    所有的日志都异步的记录,在系统初始化的时候,增加全局参数配置:
System.setProperty("log4j2.contextSelector, "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");

也可以加载JVM启动参数里设置:

java -Dog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
  • 混合异步
    在应用中同时使用同步日志和异步日志,这使得日志的配置方式更加灵活。
<?xml version="1.0" encoding="UTF-8"?>

<!-- No need to set system property "log4j2.contextSelector" to any value
     when using <asyncLogger> or <asyncRoot>. -->
 
<Configuration status="WARN">
  <Appenders>
    <!-- Async Loggers will auto-flush in batches, so switch off immediateFlush. -->
    <RandomAccessFile name="RandomAccessFile" fileName="asyncWithLocation.log"
              immediateFlush="false" append="false">
      <PatternLayout>
        <Pattern>%d %p %class{1.} [%t] %location %m %ex%n</Pattern>
      </PatternLayout>
    </RandomAccessFile>
  </Appenders>
  <Loggers>
    <!-- pattern layout actually uses location, so we need to include it -->
    <AsyncLogger name="com.foo.Bar" level="trace" includeLocation="true">
      <AppenderRef ref="RandomAccessFile"/>
    </AsyncLogger>
    <Root level="info" includeLocation="true">
      <AppenderRef ref="RandomAccessFile"/>
    </Root>
  </Loggers>
</Configuration>
异步日志注意事项
  • 不要同时使用AsyncAppender和AsyncLogger。
  • 不要在开启了全局同步的情况下,仍然使用AsyncAppender和AsyncLogger。
  • 如果不是确实需要,不要打印location信息,比如pattern模式里的%C or $class, %F or %file, %l or %location, %L or %line, %M or %method, 等,对于性能来说是个极大的损耗。
  • 不管是同步异步,都设置immediateFlush为false,这会对性能提升有很大帮助。
四.注解@Slf4j的使用

如果不想每次都写private final Logger logger = LoggerFactory.getLogger(当前类名.class); 可以用注解@Slf4j。

1.eclipse安装lombok插件
2.在pom文件加入lombok的依赖
<dependency>  
 <groupId>org.projectlombok</groupId> 
   <artifactId>lombok</artifactId>  
     <version>1.16.16</version>
</dependency>
3.类上面添加@Sl4j注解,然后使用log打印日志。
@Slf4j
class LogTest {

    @Test
    void testLog() {
        String testInfo = "Free flying flowers are like dreams";
        log.info("The test info is :{}", testInfo);
    }
}
五.日志整合
日志接口

可以统一到slf4,引用slf4j方式

   <dependency>  
   <groupId>org.slf4j</groupId>  
   <artifactId>slf4j-api</artifactId>  
   <version>1.7.13</version>  
   </dependency>  
日志实现

slf4j只是一个日志外壳,需要你加入slf4j-jdk14.jar, slf4j-log4j12.jar或logback.jar,将日志调用转发到实际的日志框架。在classpath中有哪个jar包,slf4j就会选择哪个实现。如果错误的同时存在多个jar包,用哪个那就看运气了。
用Log4j2的实现方式:

<!--核心log4j2jar包-->  
 <dependency>  
     <groupId>org.apache.logging.log4j</groupId>  
    <artifactId>log4j-api</artifactId>  
    <version>2.4.1</version>  
</dependency>  
<dependency>  
   <groupId>org.apache.logging.log4j</groupId>  
   <artifactId>log4j-core</artifactId>  
   <version>2.4.1</version>  
</dependency>  
 <!--用于与slf4j保持桥接-->  
<dependency>  
    <groupId>org.apache.logging.log4j</groupId>  
    <artifactId>log4j-slf4j-impl</artifactId>  
    <version>2.4.1</version>  
</dependency>  
<!--web工程需要包含log4j-web,非web工程不需要-->  
<dependency>  
    <groupId>org.apache.logging.log4j</groupId>  
    <artifactId>log4j-web</artifactId>  
    <version>2.4.1</version>  
    <scope>runtime</scope>  
</dependency>  

<!--需要使用log4j2的AsyncLogger需要包含disruptor-->  
<dependency>  
    <groupId>com.lmax</groupId>  
    <artifactId>disruptor</artifactId>  
    <version>3.2.0</version>  
 </dependency>

spring-boot-starter-log4j2已经实现集成以上各包,引入即可。

日志转换

有些第三方的工具包,已经直接使用了log4j, common-logging 或 java.util.logging。如果我们最后决定使用slf4j做最终输出,则需要放一个jcl104-over-slf4j.jar和 jul-to-slf4j.jar来假装成common-logging和java.util.logging的api,将日志请求转发给slf4j,slf4j再转发给对应日志实现,此时还需要保证,classpath里没有正牌的common-logging.jar。

在spring boot中整合

在这里插入图片描述
springboot 默认Slf4j 日志门面,采用日志是Slf4j + logback框架 来进行日志输出。有时候其他框架不一定适用springboot 日志 , 不同的框架底层使用的日志框架也是不尽相同。

  • 将系统中其他框架排除出去
    例如: spring 默认日志框架是 common-logging 日志框架
<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>commons-logging</artifactId>
          <groupId>commons-logging</groupId>
        </exclusion>
      </exclusions>
    </dependency>
  • 用中间包将日志进行替换
    springboot默认已经导入转换jar依赖
  • 导入slf4j其他的实现即可
    用log4j2实现如下:
<!-- 集成Log4j2日志 -->
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
其它方式整合

项目中的其它jar在启动的时候自己加载了其默认的配置文件,导致项目中的配置文件无法加载。
例如加入nacos包项目无法输出日志的问题
通过在系统变量中设置日志文件位置

System.setProperty("nacos.logging.config", "classpath:log4j2-spring.xml");
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值