log4j2的异步使用及添加自定义参数方式

网友投稿 617 2022-09-07


log4j2的异步使用及添加自定义参数方式

目录log4j2异步使用及添加自定义参数添加依赖(这里省略了版本号)下面写一个生产可用的log4j2.xml的模板补充知识自定义日志格式如何在日志中添加自己想传的参数?log4j 输入自定义参数测试代码如下

log4j2异步使用及添加自定义参数

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

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

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

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

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-logging

org.springframework.boot

spring-boot-starter-log4j2

然后再各个项目中添加文件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的模板

项目名称

INFO

/data/logs

${LOGGER_PATH}/${APP_NAME}

10M

%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] %-5level %logger{36} - %msg%n

-%d{yyyy-MM-dd}.%i.zip

30

${LOG_HOME}/${APP_NAME}-project

${LOG_HOME}/${APP_NAME}-project-error

${LOG_HOME}/${APP_NAME}-sql

fileName="${LOG_HOME_PROJECT}.log"

filePattern="${LOG_HOME_PROJECT}${rolling_file_name}"

immediateFlush="false" append="true">

${log_pattern}

UTF-8

fileName="${LOG_HOME_PROJECT}.log"

filePattern="${LOG_HOME_PROJECT}${rolling_file_name}"

immediateFlush="false" append="true">

${log_pattern}

UTF-8

fileName="${LOG_HOME_PROJECT_ERROR}.log"

filePattern="${LOG_HOME_PROJECT_ERROR}${rolling_file_name}"

immediateFlush="false" append="true">

${log_pattern}

UTF-8

fileName="${LOG_HOME_PROJECT_ERROR}.log"

filePattern="${LOG_HOME_PROJECT_ERROR}${rolling_file_name}"

immediateFlush="false" append="true">

${log_pattern}

UTF-8

fileName="${LOG_HOME_SQL}.log"

filePattern="${LOG_HOME_SQL}${rolling_file_name}"

immediateFlush="false" append="true">

${log_pattern}

UTF-8

fileName="${LOG_HOME_SQL}.log"

filePattern="${LOG_HOME_SQL}${rolling_file_name}"

immediateFlush="false" append="true">

${log_pattern}

UTF-8

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

项目名称-project.log

项目名称-project-error.log

项目名称-sql.log

补充知识

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

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

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

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

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

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 {

@Override

public 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.ThreadContext

ThreadContext.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毫秒

log4j 输入自定义参数

使用log4j、log4j2输入日志时,有时想追加打印自定义参数(比如客户端环境:手机型号、浏览器数据,request数据、用户数据等),以便于快速定位问题所在。

亦或在多线程环境中,快速定位哪些日志是由同一用户输出,便于其他工具进行日志分析。

log4j提供了ThreadContext 线程上下文类,用于存储自定义数据,以便在输入日志时,包含指定数据。

测试代码如下

package com.howtodoinjava.log4j2.examples;

import java.util.UUID;

import org.apache.logging.log4j.LogManager;

import org.apache.logging.log4j.Logger;

import org.apache.logging.log4j.ThreadContext;

public class Log4j2HelloWorldExample {

private static final Logger LOGGER = LogManager.getLogger(Log4j2HelloWorldExample.class.getName());

public static void main(String[] args) {

//Add context information

ThreadContext.put("id", UUID.randomUUID().toString());

ThreadContext.put("ipAddress", "192.168.21.9");

LOGGER.debug("Debug Message Logged !!");

LOGGER.info("Info Message Logged !!");

LOGGER.debug("Another Debug Message !!");

//Clear the map

ThreadContext.clearMap();

LOGGER.debug("Thread Context Cleaned up !!");

LOGGER.debug("Log message with no context information !!");

}

}

而后在 log4j.xml 中指定上述参数,

单独使用%X以包含地图的全部内容。

使用%X{key}包括指定的键。

使用%x包括堆栈的全部内容。

在实际应用时,一般是在过滤器、拦截器进行上述操作,方法之前,将数据绑定到线程中,方法完成后,清理线程数据。

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

项目名称-project.log

项目名称-project-error.log

项目名称-sql.log

补充知识

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

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

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

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

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

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 {

@Override

public 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.ThreadContext

ThreadContext.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毫秒

log4j 输入自定义参数

使用log4j、log4j2输入日志时,有时想追加打印自定义参数(比如客户端环境:手机型号、浏览器数据,request数据、用户数据等),以便于快速定位问题所在。

亦或在多线程环境中,快速定位哪些日志是由同一用户输出,便于其他工具进行日志分析。

log4j提供了ThreadContext 线程上下文类,用于存储自定义数据,以便在输入日志时,包含指定数据。

测试代码如下

package com.howtodoinjava.log4j2.examples;

import java.util.UUID;

import org.apache.logging.log4j.LogManager;

import org.apache.logging.log4j.Logger;

import org.apache.logging.log4j.ThreadContext;

public class Log4j2HelloWorldExample {

private static final Logger LOGGER = LogManager.getLogger(Log4j2HelloWorldExample.class.getName());

public static void main(String[] args) {

//Add context information

ThreadContext.put("id", UUID.randomUUID().toString());

ThreadContext.put("ipAddress", "192.168.21.9");

LOGGER.debug("Debug Message Logged !!");

LOGGER.info("Info Message Logged !!");

LOGGER.debug("Another Debug Message !!");

//Clear the map

ThreadContext.clearMap();

LOGGER.debug("Thread Context Cleaned up !!");

LOGGER.debug("Log message with no context information !!");

}

}

而后在 log4j.xml 中指定上述参数,

单独使用%X以包含地图的全部内容。

使用%X{key}包括指定的键。

使用%x包括堆栈的全部内容。

在实际应用时,一般是在过滤器、拦截器进行上述操作,方法之前,将数据绑定到线程中,方法完成后,清理线程数据。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:【值得推荐】5个最频繁使用的 AutoML 框架(最不经常使用)
下一篇:推荐 10 个好用到爆的 Jupyter Notebook 插件(推荐电影)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~