关于log4j2的性能和原理就不赘述了,这篇主要讲使用,配置文件解读,和添加自定义参数,偏应用的一篇文章。

相比与其他的日志系统,log4j2丢数据这种情况少;disruptor技术,在多线程环境下,性能高于logback等10倍以上;利用jdk1.5并发的特性,减少了死锁的发生;

目前看来,log4j2的性能最突出。

添加依赖(这里省略了版本号)

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions><!-- 去掉springboot默认配置 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency> <!-- 引入log4j2依赖 -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

然后再各个项目中添加文件log4j2.xml,在要使用的类上添加@slf4j 注解(lombok的),即可使用log对象。

log4j 2.0与以往的1.x有一个明显的不同,其配置文件只能采用.xml, .json或者 .jsn。在默认情况下,系统选择configuration文件的优先级如下:(classpath为src文件夹)

  • classpath下名为 log4j-test.json 或者log4j-test.jsn文件
  • classpath下名为 log4j2-test.xml
  • classpath下名为 log4j.json 或者log4j.jsn文件
  • classpath下名为 log4j2.xml

level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.

下面写一个生产可用的log4j2.xml的模板

<?xml version="1.0" encoding="UTF-8"?>
<!-- Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!-- monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="WARN">
<Properties>
<!--常用变量配置 供下文中使用-->
<property name="APP_NAME">项目名称</property>
<property name="LOGGER_LEVEL">INFO</property>
<!--日志路径 对应服务器路径-->
<property name="LOGGER_PATH">/data/logs</property>
<Property name="LOG_HOME">${LOGGER_PATH}/${APP_NAME}</Property>
<!--文件大小-->
<Property name="FILE_SIZE">10M</Property>
<!--日志格式-->
<Property name="log_pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] %-5level %logger{36} - %msg%n</Property>
<!--日志文件命名格式-->
<Property name="rolling_file_name">-%d{yyyy-MM-dd}.%i.zip</Property>
<!--日志留存最大文件数-->
<Property name="rollover_strategy_max">30</Property><Property name="LOG_HOME_PROJECT">${LOG_HOME}/${APP_NAME}-project</Property>
<Property name="LOG_HOME_PROJECT_ERROR">${LOG_HOME}/${APP_NAME}-project-error</Property>
<Property name="LOG_HOME_SQL">${LOG_HOME}/${APP_NAME}-sql</Property>
</Properties>
<appenders>
<!--控制台打印 及格式-->
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${log_pattern}" />
</Console>
<!--定义rolling() 供下文使用-->
<RollingRandomAccessFile name="projectRolling"
fileName="${LOG_HOME_PROJECT}.log"
filePattern="${LOG_HOME_PROJECT}${rolling_file_name}"
immediateFlush="false" append="true">
<PatternLayout>
<Pattern>${log_pattern}</Pattern>
<Charset>UTF-8</Charset>
</PatternLayout>
<Policies>
<!--滚动规则 时间或者文件大小 滚动后将按照filePattern命名-->
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
<TimeBasedTriggeringPolicy interval="24"/>
<SizeBasedTriggeringPolicy size="${FILE_SIZE}"/>
</Policies>
<DefaultRolloverStrategy max="${rollover_strategy_max}" />
</RollingRandomAccessFile><RollingRandomAccessFile name="projectErrorRolling"
fileName="${LOG_HOME_PROJECT_ERROR}.log"
filePattern="${LOG_HOME_PROJECT_ERROR}${rolling_file_name}"
immediateFlush="false" append="true">
<Filters>
<!-- 只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)可以使用多个ThresholdFilter 达到精准过滤某个级别的日志-->
<ThresholdFilter level="${LOGGER_LEVEL}" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
<PatternLayout>
<Pattern>${log_pattern}</Pattern>
<Charset>UTF-8</Charset>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="${FILE_SIZE}"/>
</Policies>
<DefaultRolloverStrategy max="${rollover_strategy_max}" />
</RollingRandomAccessFile></RollingRandomAccessFile>
<RollingRandomAccessFile name="sqlRolling"
fileName="${LOG_HOME_SQL}.log"
filePattern="${LOG_HOME_SQL}${rolling_file_name}"
immediateFlush="false" append="true">
<PatternLayout>
<Pattern>${log_pattern}</Pattern>
<Charset>UTF-8</Charset>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="${FILE_SIZE}"/>
</Policies>
<DefaultRolloverStrategy max="${rollover_strategy_max}" />
</RollingRandomAccessFile>
</appenders><!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->
<loggers>
<!--异步日志 区别于普通使用的logger root 搭配-->
<!--name 为包名 对应配置日志输出等级level -->
<!--若是additivity设为false,则 子Logger 只会在自己的appender里输出,而不会在 父Logger 的appender里输出。-->
<!--将org.springframework包下的日志打印到Console控制台,projectRolling文件,projectErrorRolling(error级别单独一个文件)-->
<AsyncLogger name="org.springframework" level="${LOGGER_LEVEL}" additivity="false">
<appender-ref ref="Console"/>
<appender-ref ref="projectRolling"/>
<appender-ref ref="projectErrorRolling"/>
</AsyncLogger>
<AsyncLogger name="com.alibaba.dubbo" level="${LOGGER_LEVEL}" additivity="false">
<appender-ref ref="Console"/>
<appender-ref ref="projectRolling"/>
<appender-ref ref="projectErrorRolling"/>
</AsyncLogger>
<AsyncLogger name="druid.sql" level="${LOGGER_LEVEL}" additivity="false">
<appender-ref ref="Console"/>
<appender-ref ref="sqlRolling"/>
</AsyncLogger>
<AsyncLogger name="org.mybatis" level="${LOGGER_LEVEL}" additivity="false">
<appender-ref ref="Console"/>
<appender-ref ref="sqlRolling"/>
</AsyncLogger><AsyncLogger name="com.项目包名" level="${LOGGER_LEVEL}" additivity="false">
<appender-ref ref="Console"/>
<appender-ref ref="projectRolling"/>
<appender-ref ref="projectErrorRolling"/>
</AsyncLogger><AsyncRoot level="${LOGGER_LEVEL}">
<appender-ref ref="Console"/>
<appender-ref ref="projectRolling" />
<appender-ref ref="projectErrorRolling" />
</AsyncRoot>
</loggers>
</configuration>

如上配置会产生3个日志文件

  • 项目名称-project.log
  • 项目名称-project-error.log
  • 项目名称-sql.log

补充知识

onMatch和onMismatch都有三个属性值,分别为Accept、DENY和NEUTRAL

  • 分别介绍这两个配置项的三个属性值:

  • onMatch=“ACCEPT” 表示匹配该级别及以上

  • onMatch=“DENY” 表示不匹配该级别及以上

  • onMatch=“NEUTRAL” 表示该级别及以上的,由下一个filter处理,如果当前是最后一个,则表示匹配该级别及以上

  • onMismatch=“ACCEPT” 表示匹配该级别以下

  • onMismatch=“NEUTRAL” 表示该级别及以下的,由下一个filter处理,如果当前是最后一个,则不匹配该级别以下的

  • onMismatch=“DENY” 表示不匹配该级别以下的

自定义日志格式

  • %d{HH:mm:ss.SSS} 表示输出到毫秒的时间
  • %logger{36} 简单理解为类名
  • %thread 输出当前线程名称
  • %-5level 输出日志级别,-5表示左对齐并且固定输出5个字符,如果不足在右边补0
  • %logger 输出logger名称,因为Root Logger没有名称,所以没有输出
  • %msg 日志文本
  • %n 换行
  • %X{xxx} xxx为自定义参数

如何在日志中添加自己想传的参数?

定义拦截器(web服务拦controller,dubbo服务拦api),每次请求过来,拦住,然后将自定义参数传入。至于自定义参数怎么存,就是另一个问题了。

eg: traceId 跟踪号 对应log4j2.xml中的 %X{traceId}

下面是关键代码:


public class ContextFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {String traceId = UUID.randomUUID().toString().replaceAll("-", "");
// org.slf4j.MDC MDC.put(CommonConsts.TRACE_ID_LOG, traceId);// 用来给日志文件使用
// org.apache.logging.log4j.ThreadContextThreadContext.put(CommonConsts.TRACE_ID_LOG, traceId); //经测试,这两行都可行。filterChain.doFilter(servletRequest, servletResponse);
}

最后的日志打印效果如下:

2019-05-29 12:04:30.122 [http-nio-8080-exec-2] [2333333] INFO com.core.web.filter.ContextFilter - 接口调用时间:245毫秒

参考:
https://blog.csdn.net/chenhaotong/article/details/50274135

https://www.cnblogs.com/keeya/p/10101547.html

log4j2的异步使用及添加自定义参数相关推荐

  1. 还在用Logback?Log4j2的异步性能已经无敌了,还不快试试

    以下文章来源方志朋的博客,回复"666"获面试宝典 Logback  算是JAVA 里一个老牌的日志框架,从06年开始第一个版本,迭代至今也十几年了.不过logback最近一个稳定 ...

  2. log4j mysql 异步_spring boot:配置druid数据库连接池(开启sql防火墙/使用log4j2做异步日志/spring boot 2.3.2)...

    一,druid数据库连接池的功能? 1,Druid是阿里巴巴开发的号称为监控而生的数据库连接池 它的优点包括: 可以监控数据库访问性能 SQL执行日志 SQL防火墙 2,druid的官方站: http ...

  3. vue $emit子组件传出多个参数,如何在父组件中在接收所有参数的同时添加自定义参数...

    前言 很多时候用$emit携带参数传出事件,并且又需要在父组件中使用自定义参数时,这时我们就无法接受到子组件传出的参数了. 找到了两种方法可以同时添加自定义参数的方法. 方法一 子组件传出单个参数时: ...

  4. TDH添加自定义参数

    一.概述 TDH只是预定义了一些参数,如果某些参数需要用到,在预定义参数中又找不到的话,我们可以通过"添加自定义参数"的形式添加我们需要的参数. 二.添加MapReduce参数 2 ...

  5. 关于ajax异步请求后台接受参数为null的问题

    关于ajax异步请求后台接受参数为null的问题 问题描述: 近日楼主在前端页面,使用ajax异步post方式发送请求, 1: 前台访问路径正常,参数携带正常 2: 后台拦截请求成功,使用reques ...

  6. FreeRADIUS服务器添加自定义参数

    FreeRADIUS服务器添加自定义参数 1.安装freeradius服务端 yum install freeradius -y 2.新增自定义厂商(例:mycompany) Radius服务端安装后 ...

  7. SpringMVC→简介、MVC、SpringMVC工作原理、Maven搭建第一个SpringMVC、请求参数接收、重定向、文件上传、AJAX异步访问、请求参数接收绑定JSON、@注解及传参

    MVC SpringMVC工作原理 Maven搭建第一个SpringMVC 目录结构 web.xml *-servlet.xml Controller请求处理类 跳转页面 Maven运行服务器项目 浏 ...

  8. 线程间共享 部分变量 Spring框架下向异步线程传递HttpServletRequest参数

    参考 https://www.jianshu.com/p/6bf1adb775e0 https://blog.csdn.net/kid551/article/details/88703414 需求场景 ...

  9. vue父组件在接收子组件方法传递参数的时,如何添加自定义参数

    在vue中,父组件中使用子组件方法的和传递过来的参数时直接只用参数就可以了,如下: // child this.$emit('change', param) // parent @change='pa ...

  10. python基础-进程池、submit同异步调用、shutdown参数、ProcessPoolExecutor进程池、进程池ftp

    引入进程池 使用ProcessPoolExecutor进程池 使用shutdown 使用submit同步调用 使用submit异步调用 进程池实现ftp 引入进程池 在学习线程池之前,我们先看一个例子 ...

最新文章

  1. ida 中segment中的extern是什么
  2. 25%的游戏通过Steam支持Linux系统
  3. Win2D 官方文章系列翻译 - 避免内存泄漏
  4. Python+selenium 自动化-通过窗口名切换窗口,如何获取当前窗口的title窗口名
  5. SpringMVC拦截器HandlerInterceptor使用
  6. linux下程序如何实现单实例运行
  7. 买房贷款被拒,该如何补救?
  8. 前端学习(2528):一个简单的vue app
  9. fork()调用使子进程先于父进程被调度
  10. python从云端数据库获取数据失败_使用%s的Python MySQL Connector数据库查询失败
  11. 细说HTTP中POST与GET的区别与联系
  12. 【论文写作】毕业论文该如何选择自己的导师?
  13. Windows平台下安装MongoDB(集群)
  14. 服务器处理蜘蛛抓取网页的过程,搜索引擎抓取网页的蜘蛛爬行流程
  15. Ubuntu安装播放mp4格式视频(安装ffmpeg)
  16. 网口压线顺序_RJ45水晶头排线顺序
  17. android lint
  18. Microbiome | 黄海所陈松林院士/华科宁康等-肠道菌群在龙利鱼(半滑舌鳎)抗弧菌病性状形成中的机制...
  19. 纽约大学Gary Marcus等撰文:人类思维对于AI的11个启示
  20. 如何添加或删除ubuntu用户和组

热门文章

  1. 在QQ浏览器打开html,QQ浏览器显示网页打开错误的解决方法
  2. android系统无法识别u盘,OTG无法识别U盘怎么办 OTG无法识别解决方法
  3. 外贸最全出口流程,外贸必看基础知识
  4. 设置页眉为计算机网络,word文档设置页眉线如题,怎么设置上边的 – 手机爱问...
  5. HttpClient在Android新API上的java.lang.NoSuchFieldError: No static field INSTANCE问题
  6. 【回溯】B033_LQ_填字母游戏(暴搜+注意参数传递机制)
  7. c语言计算二元一次不定方程,二元一次不定方程的解
  8. android oppo 模拟器,小姚Android构建VIVO华为魅族OPPO小米联想手游Android模拟器
  9. Ubuntu18.04 iso文件下载地址
  10. OpenCV 视频捕捉