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

2018年06月03日 14:45:22 贤和兄 阅读数:15425

Spring Boot采用yml的方式配置 Log4j2 日志文件_第1张图片

从图中不难看出,在线程数为 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的解决方案,如下配置

 

 
  1.                 

  2. org.springframework.boot

  3. spring-boot-starter-web

  4. org.springframework.boot

  5. spring-boot-starter-logging

然后添加如下两个依赖

 
  1.                 

  2. org.springframework.boot

  3. spring-boot-starter-log4j2

  4. com.fasterxml.jackson.dataformat

  5. jackson-dataformat-yaml

 

 

3、配置文件添加log4j2.yml

文件存放resource目录下

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

  2.  
  3. Configuration:

  4. status: warn

  5. monitorInterval: 30

  6.  
  7. Properties: # 定义全局变量

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

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

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

  11. - name: log.level.console

  12. value: info

  13. - name: log.path

  14. value: log

  15. - name: project.name

  16. value: opendoc

  17. - name: log.pattern

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

  19.  
  20. Appenders:

  21. Console: #输出到控制台

  22. name: CONSOLE

  23. target: SYSTEM_OUT

  24. PatternLayout:

  25. pattern: ${log.pattern}

  26. # 启动日志

  27. RollingFile:

  28. - name: ROLLING_FILE

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

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

  31. PatternLayout:

  32. pattern: ${log.pattern}

  33. Filters:

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

  35. ThresholdFilter:

  36. - level: error

  37. onMatch: DENY

  38. onMismatch: NEUTRAL

  39. - level: info

  40. onMatch: ACCEPT

  41. onMismatch: DENY

  42. Policies:

  43. TimeBasedTriggeringPolicy: # 按天分类

  44. modulate: true

  45. interval: 1

  46. DefaultRolloverStrategy: # 文件最多100个

  47. max: 100

  48. # 平台日志

  49. - name: PLATFORM_ROLLING_FILE

  50. ignoreExceptions: false

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

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

  53. PatternLayout:

  54. pattern: ${log.pattern}

  55. Policies:

  56. TimeBasedTriggeringPolicy: # 按天分类

  57. modulate: true

  58. interval: 1

  59. DefaultRolloverStrategy: # 文件最多100个

  60. max: 100

  61. # 业务日志

  62. - name: BUSSINESS_ROLLING_FILE

  63. ignoreExceptions: false

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

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

  66. PatternLayout:

  67. pattern: ${log.pattern}

  68. Policies:

  69. TimeBasedTriggeringPolicy: # 按天分类

  70. modulate: true

  71. interval: 1

  72. DefaultRolloverStrategy: # 文件最多100个

  73. max: 100

  74. # 错误日志

  75. - name: EXCEPTION_ROLLING_FILE

  76. ignoreExceptions: false

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

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

  79. ThresholdFilter:

  80. level: error

  81. onMatch: ACCEPT

  82. onMismatch: DENY

  83. PatternLayout:

  84. pattern: ${log.pattern}

  85. Policies:

  86. TimeBasedTriggeringPolicy: # 按天分类

  87. modulate: true

  88. interval: 1

  89. DefaultRolloverStrategy: # 文件最多100个

  90. max: 100

  91. # DB 日志

  92. - name: DB_ROLLING_FILE

  93. ignoreExceptions: false

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

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

  96. PatternLayout:

  97. pattern: ${log.pattern}

  98. Policies:

  99. TimeBasedTriggeringPolicy: # 按天分类

  100. modulate: true

  101. interval: 1

  102. DefaultRolloverStrategy: # 文件最多100个

  103. max: 100

  104.  
  105.  
  106. Loggers:

  107. Root:

  108. level: info

  109. AppenderRef:

  110. - ref: CONSOLE

  111. - ref: ROLLING_FILE

  112. - ref: EXCEPTION_ROLLING_FILE

  113. Logger:

  114. - name: platform

  115. level: info

  116. additivity: false

  117. AppenderRef:

  118. - ref: CONSOLE

  119. - ref: PLATFORM_ROLLING_FILE

  120.  
  121. - name: bussiness

  122. level: info

  123. additivity: false

  124. AppenderRef:

  125. - ref: BUSSINESS_ROLLING_FILE

  126.  
  127. - name: exception

  128. level: debug

  129. additivity: true

  130. AppenderRef:

  131. - ref: EXCEPTION_ROLLING_FILE

  132.  
  133. - name: db

  134. level: info

  135. additivity: false

  136. AppenderRef:

  137. - ref: DB_ROLLING_FILE

  138.  
  139.  
  140. # 监听具体包下面的日志

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

  142. # - name: com.xjj

  143. # additivity: false

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

  145. # AppenderRef:

  146. # - ref: CONSOLE

  147. # - ref: ROLLING_FILE

  148.  
  149.  

4、引入配置文件

在application.yml引入

 
  1. logging:

  2. config: classpath:log4j2.yml

 

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

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

 
  1. package com.open.util;

  2. /**

  3. * 本地日志枚举

  4. * @author Administrator

  5. *

  6. */

  7. public enum LogEnum {

  8.  
  9.  
  10. BUSSINESS("bussiness"),

  11.  
  12. PLATFORM("platform"),

  13.  
  14. DB("db"),

  15.  
  16. EXCEPTION("exception"),

  17.  
  18. ;

  19.  
  20.  
  21. private String category;

  22.  
  23.  
  24. LogEnum(String category) {

  25. this.category = category;

  26. }

  27.  
  28. public String getCategory() {

  29. return category;

  30. }

  31.  
  32. public void setCategory(String category) {

  33. this.category = category;

  34. }

  35. }

 
  1. package com.open.util;

  2.  
  3. import org.slf4j.Logger;

  4. import org.slf4j.LoggerFactory;

  5. /**

  6. * 本地日志参考类

  7. * @author Administrator

  8. *

  9. */

  10. public class LogUtils {

  11.  
  12.  
  13. /**

  14. * 获取业务日志logger

  15. *

  16. * @return

  17. */

  18. public static Logger getBussinessLogger() {

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

  20. }

  21.  
  22. /**

  23. * 获取平台日志logger

  24. *

  25. * @return

  26. */

  27. public static Logger getPlatformLogger() {

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

  29. }

  30.  
  31. /**

  32. * 获取数据库日志logger

  33. *

  34. * @return

  35. */

  36. public static Logger getDBLogger() {

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

  38. }

  39.  
  40.  
  41. /**

  42. * 获取异常日志logger

  43. *

  44. * @return

  45. */

  46. public static Logger getExceptionLogger() {

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

  48. }

  49.  
  50.  
  51. }

 

具体调用如下:

 
  1. @GetMapping("/helloworld")

  2. public String helloworld() throws Exception{

  3. Logger log = LogUtils.getExceptionLogger();

  4. Logger log1 = LogUtils.getBussinessLogger();

  5. Logger log2 = LogUtils.getDBLogger();

  6. userService.queryUser();

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

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

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

  10. return "helloworld";

  11. }

 

生成日志目录如下

Spring Boot采用yml的方式配置 Log4j2 日志文件_第2张图片

你可能感兴趣的:(JAVA)