Log4j2 快速入门

log4j 2.x 版本提供了更多的功能和更加简便的使用方式,和1.X版本相比使用过程有些不同,其中比较大的改动是

  1. 取消了 log4j.propelog配置文件,使用 xml,json,jsn 格式作为配置文件,
  2. 修改了部分对象的调用过程,如 Logger 对象等

系统选择配置文件的优先级(从先到后)如下:

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

    使用示例

    在官方下载log4j2,下载地址:https://logging.apache.org/log4j/2.x/download.html
    将以下的 jar 包导入到项目依赖 lib 中:

  • log4j-core-xx.jar

  • log4j-api-xx.jar

也可以通过 在 Maven 项目的 pom.xml 引入:

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.apache.logging.log4j</groupId>
  4. <artifactId>log4j-api</artifactId>
  5. <version>2.x</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.apache.logging.log4j</groupId>
  9. <artifactId>log4j-core</artifactId>
  10. <version>2.x</version>
  11. </dependency>
  12. </dependencies>

之后在项目工程的 src 目录下创建一个 log4j2.xml ,里面写入:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <Configuration status="WARN">
  3. <Appenders>
  4. <Console name="Console" target="SYSTEM_OUT">
  5. <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
  6. </Console>
  7. </Appenders>
  8. <Loggers>
  9. <Root level="debug">
  10. <AppenderRef ref="Console" />
  11. </Root>
  12. </Loggers>
  13. </Configuration>

之后在工程里就可以使用 log4j 记录日志了,以下是简单的测试代码

  1. import org.apache.logging.log4j.LogManager;
  2. import org.apache.logging.log4j.Logger;
  3. public class TestLog4j {
  4. private static final Logger log = LogManager.getLogger();
  5. public static void main(String[] args){
  6. log.debug("test debug message"); //Logger的各种记录方法;
  7. log.info("test info message");
  8. log.warn("test warn message");
  9. log.error("test error message");
  10. log.fatal("test fatal message");
  11. }
  12. }

以上代码在控制台输出

  1. 20:35:28.181 [main] INFO demo.TestLog4j - test info message
  2. 20:35:28.181 [main] WARN demo.TestLog4j - test warn message
  3. 20:35:28.181 [main] ERROR demo.TestLog4j - test error message
  4. 20:35:28.181 [main] FATAL demo.TestLog4j - test fatal message

以上就是 Log4j2 的快速使用过程

绑定Slf4j 与 Log4j2

  1. <!--用于与slf4j保持桥接-->
  2. <dependency>
  3. <groupId>org.apache.logging.log4j</groupId>
  4. <artifactId>log4j-slf4j-impl</artifactId>
  5. <version>2.9.1</version>
  6. </dependency>
  7. <!-- slf4j核心包-->
  8. <dependency>
  9. <groupId>org.slf4j</groupId>
  10. <artifactId>slf4j-api</artifactId>
  11. <version>1.7.25</version>
  12. </dependency>
  13. <!-- log4j2 -->
  14. <dependency>
  15. <groupId>org.apache.logging.log4j</groupId>
  16. <artifactId>log4j-api</artifactId>
  17. <version>${log4j.api.version}</version>
  18. </dependency>
  19. <dependency>
  20. <groupId>org.apache.logging.log4j</groupId>
  21. <artifactId>log4j-core</artifactId>
  22. <version>${log4j.core.version}</version>
  23. </dependency>
  24. <!-- lombok for slf4j -->
  25. <dependency>
  26. <groupId>org.projectlombok</groupId>
  27. <artifactId>lombok</artifactId>
  28. <version>1.16.16</version>
  29. </dependency>

铲除项目中,所有的 log4j1

配置文件引用POM文件变量

pom.xml

  1. <!-- 配置不同环境的变量 -->
  2. <profiles>
  3. <!-- 本地环境 -->
  4. <profile>
  5. <id>local</id>
  6. <activation>
  7. <activeByDefault>true</activeByDefault>
  8. </activation>
  9. <properties>
  10. <profileActive>local</profileActive>
  11. <logLocation>LocalFile</logLocation>
  12. </properties>
  13. </profile>
  14. <!-- 生产环境 -->
  15. <profile>
  16. <id>prod</id>
  17. <properties>
  18. <profileActive>prod</profileActive>
  19. <logLocation>File</logLocation>
  20. </properties>
  21. </profile>
  22. <!-- 沙箱测试环境 -->
  23. <profile>
  24. <id>sandbox</id>
  25. <properties>
  26. <profileActive>sandbox</profileActive>
  27. <logLocation>File</logLocation>
  28. </properties>
  29. </profile>
  30. </profiles>
  31. <!-- 打包所有的配置文件,并进行配置文件中的变量替代 -->
  32. <build>
  33. <resources>
  34. <resource>
  35. <directory>src/main/resources</directory>
  36. <!-- 启用过滤,即该资源中的变量将会被过滤器中的值替换 -->
  37. <filtering>true</filtering>
  38. <includes>
  39. <include>**/*</include>
  40. </includes>
  41. </resource>
  42. <resource>
  43. <directory>src/main/resources/${env}/</directory>
  44. <filtering>true</filtering>
  45. <includes>
  46. <include>commons.cfg</include>
  47. </includes>
  48. </resource>
  49. </resources>
  50. </build>

log4j2.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <Configuration status="WARN">
  3. <!-- 日志输出配置 -->
  4. <Appenders>
  5. <!-- 控制台输出 -->
  6. <Console name="Console" target="SYSTEM_OUT">
  7. <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
  8. </Console>
  9. <!-- 文件输出 生产环境输出到公司统一规定的位置,测试输出到D:/logs/... -->
  10. <File name="File" fileName="@user.home@/logs/ds-phoenix-radar-script-hh-kol/ds-phoenix-radar-script-hh-kol-@profileActive@.log">
  11. <PatternLayout>
  12. <pattern>%d{yyyy-MM-dd_HH:mm:ss} [%t] %p %c{2}:%L: %m%n</pattern>
  13. </PatternLayout>
  14. </File>
  15. <File name="LocalFile" fileName="D:/logs/ds-phoenix-radar-kol-type-titan/ds-phoenix-radar-kol-type-titan-@profileActive@.log">
  16. <PatternLayout>
  17. <pattern>%d{yyyy-MM-dd_HH:mm:ss} [%t] %p %c{2}:%L: %m%n</pattern>
  18. </PatternLayout>
  19. </File>
  20. </Appenders>
  21. <!-- 日志采集 -->
  22. <Loggers>
  23. <!-- 默认采集器 -->
  24. <Root level="info">
  25. <!-- 日志输出 -->
  26. <AppenderRef ref="Console" />
  27. <AppenderRef ref="@logLocation@"/>
  28. </Root>
  29. </Loggers>
  30. </Configuration>

日志记录的级别

log4j 的日志记录级别由低到高如下表:

trace 栈追踪级别,细粒度最低的级别,一般很少使用;
debug 调试级别,在调试过程中很最经常使用,一般在工程中会以debug最为最低级别,主要用于代替Eclipse和IDEA的debug功能,用于输出调试信息;
info 用于输出程序运行中重要或感兴趣的信息,在生产环境中最经常使用;
warn 指定潜在的警告信息,类似于java中的@warn注解
error 指定错误信息,但仍然允许程序继续运行,常用在记录catch捕获到的异常信息;
fatal 指定重大错误信息,这种等级的错误可能会导致程序中止;
off 最高等级,这个参数只是为了关闭日志记录

这些级别的等级排布:trace < debug < info < warn < error < fatal
这些级别之间的包含的关系,比如将日志级别设置为 debug,那么大于等于这个级别的日志都会输出,即输出 debug,info,warn,error,fatal 等级的日志;

配置文件说明

一般会把配置文件命名为 log4j2.xml同时放置在项目src的目录下,关于log4j2调用配置文件的顺序,可以参考官方说明:
https://logging.apache.org/log4j/2.x/manual/configuration.html#AutomaticConfiguration
一个典型的配置文件如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <Configuration status="WARN">
  3. <Appenders>
  4. <Console name="myConsole" target="SYSTEM_OUT">
  5. <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
  6. </Console>
  7. </Appenders>
  8. <Loggers>
  9. <Root level="debug">
  10. <AppenderRef ref="myConsole" />
  11. </Root>
  12. </Loggers>
  13. </Configuration>

这里补充Log4j的3个主要的对象介绍:

  • Logger: 负责捕获记录信息
  • Appender : 负责发布日志信息,同时决定日志的发送目的地
  • Layouter: 负责格式化不同风格的日志信息

    <Configuration>

    log4j2.xml 的根节点,内部包含、等多种节点;
    status 属性指定默认的优先级(即在内部logger没有指定优先级的情况下,为其指定的优先级);
    monitorInterval 指定每隔多少秒重新读取配置文件,可以在不重启的情况下读取该配置文件;

    <Appenders>

    定义各种 Appender 输出器,包含各个appender,有各种种类的appender标签
    其中有2种比较常用的标签:<Console><File>,分别代表控制台输出文件输出

    <Console>

    控制台输出类型 appender,其中 name 属性为该appender的标识名,traget 指定输出目的地

    <PatternLayout>

    用于appender输出的格式化,pattern属性为一个输出格式的字符串;
    %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n 中的含义如下:

  • %d{HH:mm:ss.SSS}:表示输出到毫秒的时间

  • %t:输出当前线程名称(t / thread
  • p / le / level:输出日志级别。
  • %-5level:输出日志级别,-5表示左对齐并且固定输出5个字符
  • %logger:输出logger名称,如果Logger没有名称,则不输出
  • %logger{36}:表示logger名字最长36个字符,否则按照句点分割
  • %msg:输出日志文本(m / msg / message
  • %n:换行
  • %F:输出所在的类文件名,如Client.java
  • %L:输出行号
  • %M:输出所在方法名

输出以下格式的文本:
20:35:28.181 [main] INFO demo.TestLog4j - test info message
以下是一个在debug常用的格式字符串,用于输出debug的详细信息:
%d{yyyy.MM.dd HH:mm:ss.SSS} [%t] %-5level %logger{36} %F:%M(line:%L) - %msg%n
输出格式如下
2017.07.27 14:30:21.889 [main] DEBUG demo.TestLog4j TestLog4j.java:main(line:17) - test debug message
logger{length} 输出日志的logger名,可有一个整形参数,功能是缩短logger名,设置为0表示只输入logger最右边

Conversion specifier Logger name Result
%logger mainPackage.sub.sample.Bar mainPackage.sub.sample.Bar
%logger{0} mainPackage.sub.sample.Bar Bar
%logger{5} mainPackage.sub.sample.Bar m.s.s.Bar
%logger{10} mainPackage.sub.sample.Bar m.s.s.Bar
%logger{15} mainPackage.sub.sample.Bar m.s.sample.Bar
%logger{16} mainPackage.sub.sample.Bar m.sub.sample.Bar
%logger{26} mainPackage.sub.sample.Bar mainPackage.sub.sample.Bar

%d{HH:mm:ss.SSS} 输出日志的打印日志,模式语法与 java.text.SimpleDateFormat 兼容。看上去 %d 就已经够好了

Conversion Pattern Result
%d 2006-10-20 14:06:49,812
%date 2006-10-20 14:06:49,812
%date{ISO8601} 2006-10-20 14:06:49,812
%date{HH:mm:ss.SSS} 14:06:49.812
%date{dd MMM yyyy ;HH:mm:ss.SSS} 20 oct. 2006;14:06:49.812

可选的格式修饰符位于“%”和转换符之间。第一个可选修饰符是左对齐 标志,符号是减号“-”;
接着是可选的最小宽度 修饰符,用十进制数表示。如果字符小于最小宽度,则左填充或右填充,默认是左填充(即右对齐),填充符为空格。
如果字符大于最小宽度,字符永远不会被截断。

<Loggers>

定义各种loggers,包含 <Root><Logger> 2种标签
<Root>为根logger,即在代码中 LogManager.getlogger() 没有指定参数的情况下委派的默认 logger,这些logger会包含一个 <AppenderRef> 用于指定该 logger 的 appender,在其 ref 属性表示该 append的 name 标识;

指定Logger

在代码Logger logger = LogManager.getLogger() 中,如果不指定Logger name,那么lg4j会直接调用<Root>的Logger,在使用 %logger 会输出所调用类的 class 名
如以上示例例子会输出“demo.Log4jTest”
如果要指定一个 Logger 来处理该日志收集,可以如下设置:

  • 调用 ```java private static final Logger log = LogManager.getLogger(“mylogger”);

public static void main(String[] args){ log.debug(“test debug message”); log.info(“test info message”); log.warn(“test warn message”); log.error(“test error message”); log.fatal(“test fatal message”); }

  1. - log4j2.xml
  2. ```xml
  3. <Configuration status="WARN" monitorInterval="300">
  4. <Appenders>
  5. <Console name="myConsole" target="SYSTEM_OUT">
  6. <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
  7. </Console>
  8. </Appenders>
  9. <Loggers>
  10. <Logger name="mylogger" level="debug" additivity="false">
  11. <AppenderRef ref="myConsole" />
  12. </Logger>
  13. <Root level="debug">
  14. <AppenderRef ref="myConsole" />
  15. </Root>
  16. </Loggers>
  17. </Configuration>

<Logger> 中 additivity=”false” 表示在该logger中输出的日志不会再延伸到父层 logger,这里如果改为true,则会延伸到Root Logger,即Root Logger的配置也会输出一次。

指定Appender

通过Appender可以指定输出的目的地和格式,常用的有输出到控制台和文件,即 <Console><File>
以下示例者两种输出形式

  1. <Configuration status="WARN" monitorInterval="300">
  2. <Appenders>
  3. <Console name="Console" target="SYSTEM_OUT">
  4. <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
  5. </Console>
  6. <File name="myfile" fileName="D:/logs/app.log">
  7. <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
  8. </File>
  9. </Appenders>
  10. <Loggers>
  11. <Logger name="mylog" level="debug" additivity="false">
  12. <AppenderRef ref="myfile" />
  13. </Logger>
  14. <Root level="error">
  15. <AppenderRef ref="Console" />
  16. </Root>
  17. </Loggers>
  18. </Configuration>

更多关于 Log4j2 的用法和概念参见官方的说明文档

参考文献

Log4j2 日志按级别输出到不同文件

在生产环境中,可以按日志信息级别,输出到不同的文件中,如生成 info.log,warn.log,error.log 等;也可以按照自定义的功能方式进行分类。比如接口API调用日志,定时任务日志等等。
这样的功能可以通过在 log4j2.xml 中配置 Filter 来实现;

示例代码(一)

log4j2.xml

  • 默认 Logger 对象的日志信息输出到 4 个 AppenderRef
  • 然后每个 AppenderRef 对传过来的日志信息进行过滤, 只留下指定等级的信息

    1. <Configuration status="WARN" monitorInterval="500">
    2. <!--定义日志储存文件目录-->
    3. <properties>
    4. <property name="LOG_HOME">user/logs</property>
    5. </properties>
    6. <Appenders>
    7. <!--控制台输出所有日志-->
    8. <Console name="Console" target="SYSTEM_OUT">
    9. <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
    10. </Console>
    11. <!--Info级别日志输出-->
    12. <RollingRandomAccessFile name="InfoFile"
    13. fileName="${LOG_HOME}/info/info.log"
    14. filePattern="${LOG_HOME}/info-%d{yyyy-MM-dd}-%i.log">
    15. <Filters>
    16. <ThresholdFilter level="warn" onMatch="DENY" onMismatch="NEUTRAL" />
    17. <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY" />
    18. </Filters>
    19. <PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n" />
    20. <Policies>
    21. <TimeBasedTriggeringPolicy />
    22. <SizeBasedTriggeringPolicy size="10 MB" />
    23. </Policies>
    24. <DefaultRolloverStrategy max="20" />
    25. </RollingRandomAccessFile>
    26. <!--Error级别日志输出-->
    27. <RollingRandomAccessFile name="ErrorFile"
    28. fileName="${LOG_HOME}/error/error.log"
    29. filePattern="${LOG_HOME}/error-%d{yyyy-MM-dd}-%i.log">
    30. <Filters>
    31. <ThresholdFilter level="fatal" onMatch="DENY" onMismatch="NEUTRAL" />
    32. <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY" />
    33. </Filters>
    34. <PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n" />
    35. <Policies>
    36. <TimeBasedTriggeringPolicy />
    37. <SizeBasedTriggeringPolicy size="10 MB" />
    38. </Policies>
    39. <DefaultRolloverStrategy max="20" />
    40. </RollingRandomAccessFile>
    41. <!--Fatal级别日志输出-->
    42. <RollingRandomAccessFile name="FatalFile"
    43. fileName="${LOG_HOME}/fatal/fatal.log"
    44. filePattern="${LOG_HOME}/fatal-%d{yyyy-MM-dd}-%i.log">
    45. <Filters>
    46. <ThresholdFilter level="fatal" onMatch="ACCEPT" onMismatch="DENY" />
    47. </Filters>
    48. <PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n" />
    49. <Policies>
    50. <TimeBasedTriggeringPolicy />
    51. <SizeBasedTriggeringPolicy size="10 MB" />
    52. </Policies>
    53. <DefaultRolloverStrategy max="20" />
    54. </RollingRandomAccessFile>
    55. </Appenders>
    56. <Loggers>
    57. <Root level="Debug">
    58. <AppenderRef ref="Console" />
    59. <AppenderRef ref="InfoFile" />
    60. <AppenderRef ref="ErrorFile" />
    61. <AppenderRef ref="FatalFile" />
    62. </Root>
    63. </Loggers>
    64. </Configuration>

    示例二

    ```java <?xml version=”1.0” encoding=”UTF-8”?>

    1. <!--这个输出控制台的配置-->
    2. <Console name="Console" target="SYSTEM_OUT">
    3. <PatternLayout charset="UTF-8" pattern="[%t] %d{yyyy-MM-dd HH:mm:ss,SSS a} [%p] %l - %msg%n"/>
    4. </Console>
    5. <!-- 日常info输出-->
    6. <RollingFile name="XmasLogFile" fileName="${sys:catalina.home}/logs/xmas.log" filePattern="${sys:catalina.home}/logs/xmas-%d{yyyy-MM-dd}.log" append="true">
    7. <!--日志格式-->
    8. <PatternLayout charset="UTF-8" pattern="[%t] %d{yyyy-MM-dd HH:mm:ss,SSS a} [%p] %l - %msg%n"/>
    9. <!-- 设置间隔时间 -->
    10. <Policies>
    11. <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
    12. </Policies>
    13. <DefaultRolloverStrategy max="10"/>
    14. </RollingFile>
    15. <!-- 日常error输出-->
    16. <RollingFile name="XmasErrorFile" fileName="${sys:catalina.home}/logs/xmas-error.log" filePattern="${sys:catalina.home}/logs/xmas-error-%d{yyyy-MM-dd}.log" append="true">
    17. <PatternLayout charset="UTF-8" pattern="[%t] %d{yyyy-MM-dd HH:mm:ss,SSS a} [%p] %l - %msg%n"/>
    18. <Policies>
    19. <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
    20. </Policies>
    21. <DefaultRolloverStrategy max="10"/>
    22. </RollingFile>
  1. <!--Quartz定时任务日志-->
  2. <RollingFile name="XmasQuartzLogFile" fileName="${sys:catalina.home}/logs/xmas-quartz.log" filePattern="${sys:catalina.home}/logs/xmas-quartz-%d{yyyy-MM-dd}.log" append="true">
  3. <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss.SSS z} [%t] %-5level - %msg%n"/>
  4. <Policies>
  5. <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
  6. </Policies>
  7. </RollingFile>
  8. <!--api接口请求-->
  9. <RollingFile name="XmasApiLogFile" fileName="${sys:catalina.home}/logs/xmas-api.log" filePattern="${sys:catalina.home}/logs/xmas-api-%d{yyyy-MM-dd}.log" append="true">
  10. <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss.SSS z} [%t] %-5level - %msg%n"/>
  11. <Policies>
  12. <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
  13. </Policies>
  14. </RollingFile>
  15. <!--日志统计-->
  16. <RollingFile name="XmasAnalyzeLogFile" fileName="${sys:catalina.home}/logs/analyze-xmas.log" filePattern="${sys:catalina.home}/logs/analyze-xmas-%d{yyyy-MM-dd}.log" append="true">
  17. <PatternLayout charset="UTF-8" pattern="%msg%n"/>
  18. <Policies>
  19. <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
  20. </Policies>
  21. </RollingFile>
  22. </Appenders>
  23. <Loggers>
  24. <logger name="com.chengxumiao.xmas.interceptor.TimeInterceptor" level="info" additivity="false">
  25. <appender-ref ref="XmasApiLogFile"/>
  26. </logger>
  27. <logger name="com.chengxumiao.xmas.logAnalyzer.TimelogAnalyzer" level="info" additivity="false">
  28. <appender-ref ref="XmasAnalyzeLogFile"/>
  29. </logger>
  30. <logger name="com.chengxumiao.xmas.quartz" level="info" additivity="false">
  31. <appender-ref ref="XmasQuartzLogFile"/>
  32. </logger>
  33. <Logger name="com.chengxumiao.xmas" level="trace" additivity="false">
  34. <appender-ref ref="Console"/>
  35. <appender-ref ref="XmasLogFile"/>
  36. <appender-ref ref="xmasErrorFile"/>
  37. </Logger>
  38. <Root level="warn"/>
  39. </Loggers>

  1. 一般项目中其他 jar 包引用的是 log4j.properties 文件,比如tomcat启动时候等一些日志,所以可以配置 log4j2.xml log4j.properties 两个文件共存,这样所有的日志都能记录下来了,我习惯于 log4j2.xml 按照功能,类别拆分,log4j.properties只输出一些控制台打印
  2. ```bash
  3. log4j.rootLogger=info, stdout
  4. # Console
  5. log4j.appender.stdout=org.apache.log4j.ConsoleAppender
  6. log4j.appender.stdout.Target=System.out
  7. log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
  8. log4j.appender.stdout.layout.ConversionPattern = [%t] %d{yyyy-MM-dd HH:mm:ss,SSS} [%p]:%l - %m%n

定期生成日志文件

Log4j2 对于生成日志文件时,可以通过对中的进行设置,来完整日志文件各种生成方案
log4j2.xml

  1. <Configuration status="WARN" monitorInterval="300">
  2. <properties>
  3. <property name="LOG_HOME">user/logs</property>
  4. </properties>
  5. <Appenders>
  6. <RollingRandomAccessFile name="logfile" fileName="${LOG_HOME}/app.log"
  7. filePattern="${LOG_HOME}/app-%d{yyyy-MM-dd}.log">
  8. <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
  9. <Policies>
  10. <TimeBasedTriggeringPolicy interval="1" modulate="true" />
  11. </Policies>
  12. </RollingRandomAccessFile>
  13. <DefaultRolloverStrategy max="20"/>
  14. </Appenders>
  15. <Loggers>
  16. <Root level="debug">
  17. <AppenderRef ref="logfile" />
  18. </Root>
  19. </Loggers>
  20. </Configuration>

此时日志按天数产生,及每天产生一个新的日志文件
关键的地方在于 <RollingRandomAccessFile> filepattern属性和 <TimeBasedTriggeringPolicy> 的设置

  • <RollingRandomAccessFile > filepattern 中的日期格式精确位数决定了生成日志的日期单位,
  • <TimeBasedTriggeringPolicy> interval 决定该单位下的间隔数,如果在上面例子中 interval 设置为 5,那么就是5天生成一个日志

如果按月生成日志,那么 filePath 修改为 ${LOG_HOME}/app-%d{yyyy-MM}.log
按小时生成日志,filePath = ${LOG_HOME}/app-%d{yyyy-MM-dd-HH-mm}.log
上面例子中的<DefaultRolloverStrategy max="20"/> 用于设置符合同个filePath的日志文件的最大数量,超过这个数量时,新产生的日志文件会覆盖旧的日志文件,没有设置时,默认值为7;

定大小生成日志文件

log4j2.xml

  1. <Configuration status="WARN" monitorInterval="300">
  2. <properties>
  3. <property name="LOG_HOME">user/logs</property>
  4. </properties>
  5. <Appenders>
  6. <RollingRandomAccessFile name="logfile" fileName="${LOG_HOME}/app.log"
  7. filePattern="${LOG_HOME}/error-%i.log">
  8. <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
  9. <Policies>
  10. <SizeBasedTriggeringPolicy size="10 MB" />
  11. </Policies>
  12. </RollingRandomAccessFile>
  13. <DefaultRolloverStrategy max="20"/>
  14. </Appenders>
  15. <Loggers>
  16. <Root level="debug">
  17. <AppenderRef ref="logfile" />
  18. </Root>
  19. </Loggers>
  20. </Configuration>
  • <SizeBasedTriggeringPolicy size="10 MB" /> 用于设置单个日志文件的大小上限
  • <RollingRandomAccessFile> filepattern 中的 “%i” 输出文件的次序
  • <DefaultRolloverStrategy> 设置设置符合同个filePath的日志文件的最大数量

    不同线程写入不同文件

    https://www.haoyizebo.com/posts/a29ac0/
  1. 新建一个实现类, 实现log4j2的 StrLookup 接口
  2. log4j2.xml文件中配置多线程的路由输出路径
  3. 之后可实现代码无入侵实现该需求

    1. @Plugin(name = "thread", category = StrLookup.CATEGORY)
    2. public class ThreadLookup implements StrLookup {
    3. @Override
    4. public String lookup(String s) {
    5. return Thread.currentThread().getName();
    6. }
    7. @Override
    8. public String lookup(LogEvent logEvent, String s) {
    9. return logEvent.getThreadName() == null ? Thread.currentThread().getName()
    10. : logEvent.getThreadName();
    11. }
    12. }

    配置文件示例

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <Configuration status="OFF">
    3. <Appenders>
    4. <Routing name="Routing">
    5. <Routes pattern="$${thread:threadName}">
    6. <Route>
    7. <RollingFile name="logFile-${thread:threadName}"
    8. fileName="logs/concurrent-${thread:threadName}.log"
    9. filePattern="logs/concurrent-${thread:threadName}-%d{MM-dd-yyyy}-%i.log">
    10. <PatternLayout pattern="%d %-5p [%t] %C{2} - %m%n"/>
    11. <Policies>
    12. <SizeBasedTriggeringPolicy size="50 MB"/>
    13. </Policies>
    14. <DefaultRolloverStrategy max="100"/>
    15. </RollingFile>
    16. </Route>
    17. </Routes>
    18. </Routing>
    19. <Async name="async" bufferSize="1000" includeLocation="true">
    20. <AppenderRef ref="Routing"/>
    21. </Async>
    22. <!-- 很直白,Console 指定了结果输出到控制台 -->
    23. <Console name="ConsolePrint" target="SYSTEM_OUT">
    24. <PatternLayout pattern="%d{yyyy.MM.dd HH:mm:ss z} %t %-5level %class{36} %L %M - %msg%xEx%n"/>
    25. </Console>
    26. </Appenders>
    27. <Loggers>
    28. <Root level="info" includeLocation="true">
    29. <AppenderRef ref="async"/>
    30. <AppenderRef ref="ConsolePrint"/>
    31. </Root>
    32. </Loggers>
    33. </Configuration>

    示例 ```java @Log4j2 public class TestThreadLog { // private static final Logger log = LogManager.getLogger(TestThreadLog.class);

    @Test void test001ThreadLog() {

    1. new Thread(() -> {
    2. Thread.currentThread().setName("线程1-1");
    3. log.info("info");
    4. log.debug("debug");
    5. log.error("error");
    6. }).start();
    7. new Thread(() -> {
    8. Thread.currentThread().setName("线程1-2");
    9. log.info("info");
    10. log.debug("debug");
    11. log.error("error");
    12. }).start();

    }

}

  1. <a name="fTgQi"></a>
  2. ## 日志写入数据库
  3. 新建一张表
  4. ```sql
  5. CREATE TABLE `t_bde_etl_log` (
  6. `id` int(11) NOT NULL AUTO_INCREMENT COMMENT "唯一标识",
  7. `log_level` varchar(100) NOT NULL COMMENT "日志等级",
  8. `log_location` varchar(1000) DEFAULT NULL COMMENT "日志位置",
  9. `log_date` varchar(1000) DEFAULT NULL COMMENT "日志日期",
  10. `log_message` varchar(1000) NOT NULL COMMENT "日志信息",
  11. PRIMARY KEY (`id`)
  12. ) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4;

配置文件中配置一个写入数据库的Appender, 注意指定连接池的类

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <Configuration status="WARN">
  3. <!--定义日志储存文件目录-->
  4. <properties>
  5. <property name="LOG_HOME">${user.home}/logs</property>
  6. </properties>
  7. <!-- 设定输出的地方, 可以设定多个, 然后让Logger去挑选 -->
  8. <Appenders>
  9. <!-- 输出到控制台 -->
  10. <Console name="console" target="SYSTEM_OUT">
  11. <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
  12. </Console>
  13. <!-- 输出到文件 -->
  14. <File name="file" fileName="D:/logs/app.log">
  15. <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
  16. </File>
  17. <!-- 输出到数据库, 表名为: t_bde_etl_log, 需获取数据库连接池 -->
  18. <JDBC name="databaseAppender" tableName="t_bde_etl_log">
  19. <ConnectionFactory class="com.datastory.radar.serv.base.ConnectionFactory" method="getDatabaseConnection"/>
  20. <!-- pattern中填写标准的log4j2参数即可 %msg %d 等 -->
  21. <Column name="log_level" pattern="%level"/>
  22. <Column name="log_location" pattern="%ogger{36}"/>
  23. <Column name="log_date" pattern="%d{yyyy-MM-dd hh:mm:ss}"/>
  24. <Column name="log_message" pattern="%m"/>
  25. </JDBC>
  26. </Appenders>
  27. <!-- 日志样式, 这里有两个, 一个是默认的, 一个是DBLogger -->
  28. <Loggers>
  29. <Logger name="DBLogger" level="Debug" additivity="false">
  30. <!-- 指定使用的追加器 -->
  31. <AppenderRef ref="console" />
  32. <AppenderRef ref="file" />
  33. <AppenderRef ref="databaseAppender" />
  34. </Logger>
  35. <Root level="debug">
  36. <AppenderRef ref="console" />
  37. </Root>
  38. </Loggers>
  39. </Configuration>

获取druid连接池

  1. package com.datastory.radar.serv.base;
  2. import com.alibaba.druid.pool.DruidDataSource;
  3. import com.alibaba.druid.pool.DruidDataSourceFactory;
  4. import java.sql.Connection;
  5. import java.sql.SQLException;
  6. import java.util.Properties;
  7. public class ConnectionFactory{
  8. private DruidDataSource dataSource;
  9. private static ConnectionFactory connectionFactory;
  10. private Connection getConnection() throws SQLException {
  11. Properties properties = new Properties();
  12. String user = "mondelez";
  13. String password = "akT9d9FhSvtBTbuN";
  14. String url = "jdbc:mysql://dev.mysql.proxy.hdp:3001/db_datastory_mondelez?useUnicode=true&characterEncoding=utf-8";
  15. String driverClassName = "com.mysql.jdbc.Driver";
  16. properties.put("driverClassName",driverClassName);
  17. properties.put("url",url);
  18. properties.put("username",user);
  19. properties.put("password",password);
  20. try {
  21. dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
  22. } catch (Exception e) {
  23. try {
  24. init();
  25. } catch (Exception e2) {
  26. e2.printStackTrace();
  27. }
  28. }
  29. return dataSource.getConnection();
  30. }
  31. public static Connection getDatabaseConnection() throws SQLException {
  32. if(connectionFactory == null){
  33. connectionFactory = new ConnectionFactory();
  34. }
  35. return connectionFactory.getConnection();
  36. }
  37. public void init(){
  38. try {
  39. if (dataSource != null)
  40. dataSource.close();
  41. } catch (Exception e) {
  42. e.printStackTrace();
  43. }
  44. }
  45. }

使用

  1. // 输出到数据库的日志对象
  2. private static final Logger dbLogger = LogManager.getLogger("DBLogger");