详谈异步log4j2中的location信息打印问题

目录
  • 异步log4j2的location信息打印问题
    • 说下解决
    • 1、全异步
    • 同步异步混合
  • log4j2支持异步打印提高打印输出速度
    • pom依赖添加
    • 全局模式2两种
    • 局部模式 AsyncLogger

异步log4j2的location信息打印问题

背景:项目改造过程中将log4j2改成异步,发现行号没有打印,于是扒了下官方文档,大概陈述下:

先说一下这个问题是怎么解决的,然后稍微扩展一下其他配置,有兴趣的可以往下看或者溜一遍官方文档

说下解决

在<AsyncLogger>标签中配置includeLocation="true",

扩展:

1、additivity:这个属性的意思是需不需要打印此logger继承的父logger,如果是false则只打印当前logger;如果是true则继续打印上一层的logger,直到root。

2、实现error日志打印双份:info.log中打印一份(即info中包括info和error日志),error.log中打印一份(只包括error日志),这样的好处是能根据error日志出现的上下文快速定位到程序bug出现的位置,这个功能需要使用过滤器实现,比如:

 <RollingFile name="error" fileName="${log_home}/error.log" immediateFlush="false" append="true"
                     filePattern="/history/error-%d{yyyy-MM-dd}.log.gz">
      <Filters>
         <!--只允许级别为error的日志通过-->
          <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
       </Filters>
       <PatternLayout charset="UTF-8">
          <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} #| %p #| %t #| %c{-1}:%L #| %m%n</Pattern>
       </PatternLayout>
       <Policies>
          <!--默认打印周期为一天-->
          <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
       </Policies>
       <!--保存日志个数为15个-->
       <DefaultRolloverStrategy max="15"/>
</RollingFile>

log4j2的异步形式大概分为两种:全异步和同步异步混合。

1、全异步

实现方式:将系统属性log4j2.contextSelector设置 为org.apache.logging.log4j.core.async.AsyncLoggerContextSelector,即

System.setProperty("log4j2.contextSelector, "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");

或者在启动时设置:

-Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector

官方给出了一个不需要location信息的配置文件示例:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <!-- Async Loggers will auto-flush in batches, so switch off immediateFlush. -->
    <RandomAccessFile name="RandomAccessFile" fileName="async.log" immediateFlush="false" append="false">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m %ex%n</Pattern>
      </PatternLayout>
    </RandomAccessFile>
  </Appenders>
  <Loggers>
   <!--不需要打印location信息-->
    <Root level="info" includeLocation="false">
      <AppenderRef ref="RandomAccessFile"/>
    </Root>
  </Loggers>
</Configuration>

注意:

如果用AsyncLoggerContextSelector实现全异步,那么配置中就要使用<root>和<logger> 。如果配置了这个属性,并且使用了<asyncRoot>和<asyncLogger>,那么程序将会产生两个线程:日志数据首先传递给线程A,然后线程A再传递给线程B,最后再输出到磁盘,这样是可行的,但是中间多了一步线程交互的过程,这是不必要的。

同步异步混合

相比起全异步,混合异步可能会花费更多的性能,

官方给出了一个混合异步的配置例子:

<?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>

对于location信息:

默认情况下,异步日志记录器不会将location信息传递给I/O线程,如果你的layouts或custom过滤器需要location信息,你需要在所有相关日志记录器(包括根日志记录器)的配置中设置“includeLocation=true”

如果其中一个layouts配置了关于位置的信息,比如HTML locationInfo,或者表达式%C或%class、%F或%file、%l或%location、%L或%line、%M或%method,log4j2将会获取堆栈的快照(snapshot),并遍历堆栈跟踪以查找位置信息,因此会消耗较多的时间。

比同步logger慢1.3到5倍,同步日志记录器在获取堆栈快照之前会等待尽可能长的时间,如果不需要位置,那么快照将永远不会被捕获。

了解更多请访问官方文档:Apache Log4j2 Async 官方文档

log4j2支持异步打印提高打印输出速度

pom依赖添加

<!--log4j2异步支持-->
<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
</dependency>

全局模式2两种

第一种:resources 下创建属性文件 log4j2.component.properties

# log4j2异步支持
Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector

第二种:springboot启动main方法添加代码

System.setProperty("Log4jContextSelector","org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");

或者采用启动参数

-DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector

局部模式 AsyncLogger

<Loggers>
        <AsyncLogger name="com.meituan.Main" level="trace" additivity="false">
            <appender-ref ref="RollingFile"/>
        </AsyncLogger>
        <AsyncLogger name="RollingFile2" level="trace" additivity="false">
            <appender-ref ref="RollingFile2"/>
        </AsyncLogger>
        <Root level="debug">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="RollingFile"/>
        </Root>
</Loggers>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Springboot2.x 使用 Log4j2 异步打印日志的实现

    介绍 目前常用的 Java 日志框架有 Log4j.Logback.Log4j2 ,性能方面推荐使用异步的 Log4j2,具体对比不多做分析,前人早已完成耕荒,我们就站在巨人的肩膀上来看看如何实操. SLF4J,简单日志门面(Simple Logging Facade for Java),是一个用于日志系统的简单 Facade,不是具体的日志解决方案,而是通过Facade Pattern提供一些Java logging API,我的理解是它和 Log4j.Logback.Log4j2 的关系类似

  • 关于log4j2的异步日志输出方式

    目录 log4j2的异步日志输出方式 第一种实现异步方式AsyncAppender 第二种实现异步方式AsyncLogger log4j2异步注意事项 log4j2异步类型 小提示 log4j2的异步日志输出方式 使用log4j2的同步日志进行日志输出,日志输出语句与程序的业务逻辑语句将在同一个线程运行. 而使用异步日志进行输出时,日志输出语句与业务逻辑语句并不是在同一个线程中运行,而是有专门的线程用于进行日志输出操作,处理业务逻辑的主线程不用等待即可执行后续业务逻辑. Log4j2中的异步日志

  • log4j2异步Logger(详解)

    1 异步Logger的意义 之前的日志框架基本都实现了AsyncAppender,被证明对性能的提升作用非常明显. 在log4j2日志框架中,增加了对Logger的异步实现.那么这一步的解耦,意义何在呢? 如图,按我目前的理解:异步Logger是让业务逻辑把日志信息放入Disruptor队列后可以直接返回(无需等待"挂载的各个Appender"都取走数据) 优点:更高吞吐.调用log方法更低的延迟. 缺点:异常处理麻烦. 可变日志消息问题.更大的CPU开销.需要等待"最慢的A

  • log4j2日志异步打印(实例讲解)

    log4j2支持日志的异步打印,日志异步输出的好处在于,使用单独的进程来执行日志打印的功能,可以提高日志执行效率,减少日志功能对正常业务的影响. 异步日志在程序的classpath需要加载disruptor-3.0.0.jar或者更高的版本. Asynchronous Loggers是一个新增特性在Log4j 2 ,可以实现完全异步也可以和同步混合使用,还可以只异步化Appender,以提升系统性能,官方数据显示混合没有完全异步化效果好. 1,完全异步模式: 这种异步日志方式,不需要修改原来的配

  • log4j2异步打印性能提升方式

    目录 log4j2异步打印性能提升 分析原因 解决方案 log4j2性能提升点 理解为以下三点 log4j2异步打印性能提升 压测结果发现,log4j升级成log4j2之后对系统性能影响并不大,更改打印日志方式(同步修改成异步打印) 压测结果发现TPS在开始阶段提升较快,当压力上来之后,TPS下降迅速,不如同步的数据(log4j2用的版本是2.3) 分析原因 获取压测是堆栈日志如下: 发现线程都在跑LockSupport.parkNanos也就是unsafe.park(false, 1);(pr

  • 详谈异步log4j2中的location信息打印问题

    目录 异步log4j2的location信息打印问题 说下解决 1.全异步 同步异步混合 log4j2支持异步打印提高打印输出速度 pom依赖添加 全局模式2两种 局部模式 AsyncLogger 异步log4j2的location信息打印问题 背景:项目改造过程中将log4j2改成异步,发现行号没有打印,于是扒了下官方文档,大概陈述下: 先说一下这个问题是怎么解决的,然后稍微扩展一下其他配置,有兴趣的可以往下看或者溜一遍官方文档 说下解决 在<AsyncLogger>标签中配置include

  • 详谈js中window.location.search的用法和作用

    用该属性获取页面 URL 地址: window.location 对象所包含的属性 属性 描述 hash 从井号 (#) 开始的 URL(锚) host 主机名和当前 URL 的端口号 hostname 当前 URL 的主机名 href 完整的 URL pathname 当前 URL 的路径部分 port 当前 URL 的端口号 protocol 当前 URL 的协议 search 从问号 (?) 开始的 URL(查询部分) 如图就是取出url中的参数. JS 脚本捕获页面 GET 方式请求的参

  • 在Spring异步调用中传递上下文的方法

    什么是异步调用? 异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步程序执行完即可执行.异步调用指,在程序在执行时,无需等待执行的返回值即可继续执行后面的代码.在我们的应用服务中,有很多业务逻辑的执行操作不需要同步返回(如发送邮件.冗余数据表等),只需要异步执行即可. 本文将介绍 Spring 应用中,如何实现异步调用.在异步调用的过程中,会出现线程上下文信息的丢失,我们该如何解决线程上下文信息的传递. Sprin

  • Perl中捕获警告信息、异常信息并写入日志详解

    虽然建议在每个Perl脚本和模块中开启警告,可是你又不想用户看到Perl发出的警告. 一方面你想在代码前面使用use warnings作为你的安全网,另一方面,通常警告会出现在屏幕上.多数情况下,客户不知道如何处理这些警告.如果幸运的话这些警告仅仅让客户惊讶一下,当然,不幸的是他们尝试着去修复它们... (这里说的不是Perl程序员.) 第三方面,你或许想要保存这些警告供之后分析. 此外,在很多地方还有很多Perl脚本和应用程序没有使用use warnings也没有在#!行中使用-w.加上了us

  • jQuery在header中设置请求信息的方法

    jquery是js的类库,js本身不能操作header,因为js是在浏览器加载页面过程中才开始执行的header需要服务器端执行操作 如果是ajax,是可以设置header $.ajax({ url: "", data: {}, type: "GET", beforeSend: function(xhr){xhr.setRequestHeader('X-Test-Header', 'test-value');},//这里设置header success: funct

  • 详谈Ajax请求中的async:false/true的作用(ajax 在外部调用问题)

    test.html <a href="javascript:void(0)" rel="external nofollow" onmouseover="testAsync()"> asy.js function testAsync(){ var temp; $.ajax({ async: false, //同步请求 type : "GET", url : 'tet.php', complete: function(

  • 详谈Java泛型中T和问号(通配符)的区别

    类型本来有:简单类型和复杂类型,引入泛型后把复杂类型分的更细了. 概述 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛型方法. Java语言引入泛型的好处是安全简单. 在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的"任意化","任意化"带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对

  • 如何在 iOS 应用中添加位置信息

    最近要在 iOS 应用中添加位置信息, 需要满足的需求如下: 应用在前台时能够获取位置信息: 通过切换. Home 按键将应用切换到后台时,停止获取位置信息: 应用程序在前台运行, 直接锁定屏幕时,能够继续获取位置信息: 接下来逐步实现这三个需求. 获取设备位置信息 在 iOS 上获取位置信息是很容易的, 网上的资料也很多, 我的代码如下: // make sure location service is enabled. if (!CLLocationManager.LocationServi

  • SpringBoot之自定义启动异常堆栈信息打印方式

    在SpringBoot项目启动过程中,当一些配置或者其他错误信息会有一些的规范的提示信息 *************************** APPLICATION FAILED TO START *************************** Description: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that's liste

  • HTTP中header头部信息详解

    HTTP Request的Header信息 1.HTTP请求方式 如下表: GET 向Web服务器请求一个文件 POST 向Web服务器发送数据让Web服务器进行处理 PUT 向Web服务器发送数据并存储在Web服务器内部 HEAD 检查一个对象是否存在 DELETE 从Web服务器上删除一个文件 CONNECT 对通道提供支持 TRACE 跟踪到服务器的路径 OPTIONS 查询Web服务器的性能 说明: 主要使用到"GET"和"POST". 实例: POST /

随机推荐