Spring Boot采用yml的方式配置 Log4j2 日志文件

从图中不难看出,在线程数为 2~16 之间,混合使用同步和异步的logger来打印日志,性能是最好的

 

 

1、选择Log4j2的理由是啥,为啥不用spring boot 默认的?

优化说明
执行速度Log4j 2.x 相对于 Log4j 1.x 和 Logback来说,具有更快的执行速度。一方面由于 重写了内部的实现,在某些特定的场景上面,甚至可以比之前的速度快上10倍。比如内部的消息队列采用了ArrayBlockingQueue,相对于原始的ArrayList和锁操作来说,管程类的消息队列拥有更好地性能。同时所需的内存更加少。这是因为Log4j 2.x 采用占位符的形式打印日志(类似于Slf4j门面日志的形式),会先判断一下日志的等级,然后再拼接要打印的内容。另一方面由于Log4j 2.x 充分利用Java 5的并发特性(主要是使用了一些concurrent包下锁),使得性能得到一定的改善,而Log4j 1.x和Logback很多地方还是用的重锁。
异步性能Asynchronous Loggers是Log4j2新增的日志器,异步日志器在其内部实现采用了LMAX Disruptor(一个无锁的线程间通信库)技术,Disruptor主要通过环形数组结构、元素位置定位和精巧的无锁设计(CAS)实现了在高并发情形下的高性能。而且Log4j 2.x中Asynchronous Appenders作为Asynchronous Loggers工作的一部分,效果进行了增强。每次写入磁盘时,都会进行flush操作,效果和配置“immediateFlush=true”一样。该异步Appender内部采用ArrayBlockingQueue的方式。RandomAccessFileAppender采用ByteBuffer+RandomAccessFile替代了BufferedOutputStream,官方给出的测试数据是它将速度提升了20-200%。
自动加载配置文件Log4j 2.x 和Logback都新增了自动加载日志配置文件的功能,又与Logback不同,配置发生改变时不会丢失任何日志事件。当Log4j 2.x中配置发生改变时,如果还有日志事件尚未处理,Log4j 2会继续处理,当处理完成后,Logger会重新指向新配置的LoggerConfig对象,并且删除无用的对象。
死锁问题的解决在Log4j 1.x中同步写日志的时候,在高并发情况下出现死锁导致cpu使用率异常飙升。其中的原因是当一个进程写日志的时候需要获取到Logger和Appender。org.apache.log4j.Logger类继承于org.apache.log4j.Category、Appender继承于org.apache.log4j.AppenderSkeleton。通过Log4j 1.x中Category源码和Appender源码可以知道,当多线程并发时,可能会因为相互持有Logger和Appender发生死锁。 而在log4j 2.x中充分利用Java5的并发支持,并且以最低级别执行锁定。

2、Maven 依赖 pom.xml配置

 

去掉默认日志,加载别的日志,spring boot提供log4j2的解决方案,如下配置

 <!-- 包含 mvc,aop 等jar资源 -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

<exclusions>

<!-- 切换log4j2日志读取 -->

<exclusion>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-logging</artifactId>

</exclusion>

</exclusions>

</dependency>

然后添加如下两个依赖

<!-- 配置 log4j2 -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-log4j2</artifactId>

</dependency>

<!-- 加上这个才能辨认到log4j2.yml文件 -->

<dependency>

<groupId>com.fasterxml.jackson.dataformat</groupId>

<artifactId>jackson-dataformat-yaml</artifactId>

</dependency>

3、配置文件添加log4j2.yml

文件存放resource目录下

# 共有8个级别,按照从低到高为:ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF。

Configuration:

status: warn

monitorInterval: 30

Properties: # 定义全局变量

Property: # 缺省配置(用于开发环境)。其他环境需要在VM参数中指定,如下:

#测试:-Dlog.level.console=warn -Dlog.level.xjj=trace

#生产:-Dlog.level.console=warn -Dlog.level.xjj=info

- name: log.level.console

value: info

- name: log.path

value: log

- name: project.name

value: opendoc

- name: log.pattern

value: "%d{yyyy-MM-dd HH:mm:ss.SSS} -%5p ${PID:-} [%15.15t] %-30.30C{1.} : %m%n"

Appenders:

Console: #输出到控制台

name: CONSOLE

target: SYSTEM_OUT

PatternLayout:

pattern: ${log.pattern}

# 启动日志

RollingFile:

- name: ROLLING_FILE

fileName: ${log.path}/${project.name}.log

filePattern: "${log.path}/historyRunLog/$${date:yyyy-MM}/${project.name}-%d{yyyy-MM-dd}-%i.log.gz"

PatternLayout:

pattern: ${log.pattern}

Filters:

# 一定要先去除不接受的日志级别,然后获取需要接受的日志级别

ThresholdFilter:

- level: error

onMatch: DENY

onMismatch: NEUTRAL

- level: info

onMatch: ACCEPT

onMismatch: DENY

Policies:

TimeBasedTriggeringPolicy: # 按天分类

modulate: true

interval: 1

DefaultRolloverStrategy: # 文件最多100个

max: 100

# 平台日志

- name: PLATFORM_ROLLING_FILE

ignoreExceptions: false

fileName: ${log.path}/platform/${project.name}_platform.log

filePattern: "${log.path}/platform/$${date:yyyy-MM}/${project.name}-%d{yyyy-MM-dd}-%i.log.gz"

PatternLayout:

pattern: ${log.pattern}

Policies:

TimeBasedTriggeringPolicy: # 按天分类

modulate: true

interval: 1

DefaultRolloverStrategy: # 文件最多100个

max: 100

# 业务日志

- name: BUSSINESS_ROLLING_FILE

ignoreExceptions: false

fileName: ${log.path}/bussiness/${project.name}_bussiness.log

filePattern: "${log.path}/bussiness/$${date:yyyy-MM}/${project.name}-%d{yyyy-MM-dd}-%i.log.gz"

PatternLayout:

pattern: ${log.pattern}

Policies:

TimeBasedTriggeringPolicy: # 按天分类

modulate: true

interval: 1

DefaultRolloverStrategy: # 文件最多100个

max: 100

# 错误日志

- name: EXCEPTION_ROLLING_FILE

ignoreExceptions: false

fileName: ${log.path}/exception/${project.name}_exception.log

filePattern: "${log.path}/exception/$${date:yyyy-MM}/${project.name}-%d{yyyy-MM-dd}-%i.log.gz"

ThresholdFilter:

level: error

onMatch: ACCEPT

onMismatch: DENY

PatternLayout:

pattern: ${log.pattern}

Policies:

TimeBasedTriggeringPolicy: # 按天分类

modulate: true

interval: 1

DefaultRolloverStrategy: # 文件最多100个

max: 100

# DB 日志

- name: DB_ROLLING_FILE

ignoreExceptions: false

fileName: ${log.path}/db/${project.name}_db.log

filePattern: "${log.path}/db/$${date:yyyy-MM}/${project.name}-%d{yyyy-MM-dd}-%i.log.gz"

PatternLayout:

pattern: ${log.pattern}

Policies:

TimeBasedTriggeringPolicy: # 按天分类

modulate: true

interval: 1

DefaultRolloverStrategy: # 文件最多100个

max: 100


Loggers:

Root:

level: info

AppenderRef:

- ref: CONSOLE

- ref: ROLLING_FILE

- ref: EXCEPTION_ROLLING_FILE

Logger:

- name: platform

level: info

additivity: false

AppenderRef:

- ref: CONSOLE

- ref: PLATFORM_ROLLING_FILE

- name: bussiness

level: info

additivity: false

AppenderRef:

- ref: BUSSINESS_ROLLING_FILE

- name: exception

level: debug

additivity: true

AppenderRef:

- ref: EXCEPTION_ROLLING_FILE

- name: db

level: info

additivity: false

AppenderRef:

- ref: DB_ROLLING_FILE


# 监听具体包下面的日志

# Logger: # 为com.xjj包配置特殊的Log级别,方便调试

# - name: com.xjj

# additivity: false

# level: ${sys:log.level.xjj}

# AppenderRef:

# - ref: CONSOLE

# - ref: ROLLING_FILE

4、引入配置文件

在application.yml引入

logging:

config: classpath:log4j2.yml 

5、不同日志工具类util编辑

由于配置了4个文件存放不同日志,分别为平台日志(${project.name}_platform.log)、 业务日志(${project.name}_bussiness.log)、错误日志(${project.name}_exception.log)、DB 日志(${project.name}_db.log),文件夹外面为运行日志,不同文件日志级别不一样,因此程序员在开发时候需要注意引入不同日志,也就是说开发出现的日志,程序员可以进行分类,分别调用公共方法即可。公共类编辑如下;

package com.open.util;

/**

* 本地日志枚举

* @author Administrator

*

*/

public enum LogEnum {


BUSSINESS("bussiness"),

PLATFORM("platform"),

DB("db"),

EXCEPTION("exception"),

;


private String category;


LogEnum(String category) {

this.category = category;

}

public String getCategory() {

return category;

}

public void setCategory(String category) {

this.category = category;

}

}
  1.  

package com.open.util;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

/**

* 本地日志参考类

* @author Administrator

*

*/

public class LogUtils {


/**

* 获取业务日志logger

*

* @return

*/

public static Logger getBussinessLogger() {

return LoggerFactory.getLogger(LogEnum.BUSSINESS.getCategory());

}

/**

* 获取平台日志logger

*

* @return

*/

public static Logger getPlatformLogger() {

return LoggerFactory.getLogger(LogEnum.PLATFORM.getCategory());

}

/**

* 获取数据库日志logger

*

* @return

*/

public static Logger getDBLogger() {

return LoggerFactory.getLogger(LogEnum.DB.getCategory());

}


/**

* 获取异常日志logger

*

* @return

*/

public static Logger getExceptionLogger() {

return LoggerFactory.getLogger(LogEnum.EXCEPTION.getCategory());

}


}

具体调用如下:

@GetMapping("/helloworld")

public String helloworld() throws Exception{

Logger log = LogUtils.getExceptionLogger();

Logger log1 = LogUtils.getBussinessLogger();

Logger log2 = LogUtils.getDBLogger();

userService.queryUser();

log.error("getExceptionLogger===日志测试");

log1.info("getBussinessLogger===日志测试");

log2.debug("getDBLogger===日志测试");

return "helloworld";

}

生成日志目录如下

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值