<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web-services</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> <!-- 排除默认的logback日志,使用log4j--> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!-- 排除默认的logback日志,使用log4j--> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency> <dependency> <!-- 引入log4j2依赖 --> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
logging.config=classpath:log4j2.xml
(1)简单使用,输出到文件,可以回滚
<?xml version="1.0" encoding="UTF-8"?> <!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出--> <!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数--> <configuration monitorInterval="5"> <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --> <Properties> <property name="LOG_PATTERN">"%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"</property> <property name="FILE_PATH">logs</property> </Properties> <appenders> <console name="Console" target="SYSTEM_OUT"> <!--输出日志的格式--> <PatternLayout pattern="${LOG_PATTERN}"/> <!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> </console> <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用--> <File name="Filelog" fileName="${FILE_PATH}/test.log" append="false"> <PatternLayout pattern="${LOG_PATTERN}"/> </File> <!-- 这个会打印出所有的error及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--> <RollingFile name="RollingFile" fileName="${FILE_PATH}/test.log" filePattern="${FILE_PATH}/test-%d{yyyy-MM-dd}_%i.log.gz"> <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="${LOG_PATTERN}"/> <Policies> <!--interval属性用来指定多久滚动一次,默认是1 hour--> <TimeBasedTriggeringPolicy interval="1"/> <SizeBasedTriggeringPolicy size="20MB"/> </Policies> <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖--> <DefaultRolloverStrategy max="15"/> </RollingFile> </appenders> <!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。--> <!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效--> <loggers> <root level="info"> <appender-ref ref="Console"/> <appender-ref ref="Filelog"/> <appender-ref ref="RollingFile"/> </root> </loggers> </configuration>
可以看到输出到了根目录logs/test.log
(2)不同的包生成到不同的日志
<?xml version="1.0" encoding="UTF-8"?> <!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出--> <!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数--> <configuration monitorInterval="5"> <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --> <Properties> <property name="LOG_PATTERN">"%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"</property> <property name="FILE_PATH">logs</property> </Properties> <appenders> <console name="Console" target="SYSTEM_OUT"> <!--输出日志的格式--> <PatternLayout pattern="${LOG_PATTERN}"/> <!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> </console> <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用--> <File name="Filelog" fileName="${FILE_PATH}/test.log" append="false"> <PatternLayout pattern="${LOG_PATTERN}"/> </File> // 指定logPackage1的路径 <File name="Filelog1" fileName="${FILE_PATH}/test1.log" append="false"> <PatternLayout pattern="${LOG_PATTERN}"/> </File> // 指定logPackage2的路径 <File name="Filelog2" fileName="${FILE_PATH}/test2.log" append="false"> <PatternLayout pattern="${LOG_PATTERN}"/> </File> <!-- 这个会打印出所有的error及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--> <RollingFile name="RollingFile" fileName="${FILE_PATH}/test.log" filePattern="${FILE_PATH}/test-%d{yyyy-MM-dd}_%i.log.gz"> <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="${LOG_PATTERN}"/> <Policies> <!--interval属性用来指定多久滚动一次,默认是1 hour--> <TimeBasedTriggeringPolicy interval="1"/> <SizeBasedTriggeringPolicy size="20MB"/> </Policies> <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖--> <DefaultRolloverStrategy max="15"/> </RollingFile> </appenders> <!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。--> <!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效--> <loggers> // 指定logPackage1的路径 <Logger name="com.example.demo.logPackage1" level="info" additivity="false"> <AppenderRef ref="Console"/> <appender-ref ref="Filelog1"/> </Logger> // 指定logPackage2的路径 <Logger name="com.example.demo.logPackage2" level="info" additivity="false"> <AppenderRef ref="Console"/> <appender-ref ref="Filelog2"/> </Logger> // 指定logPackage3的路径,但是并没有设置Filelog3,日志将无法记录 <Logger name="com.example.demo.logPackage3" level="info" additivity="false"> <AppenderRef ref="Console"/> <appender-ref ref="Filelog3"/> </Logger> <root level="info"> <appender-ref ref="Console"/> <appender-ref ref="Filelog"/> <appender-ref ref="RollingFile"/> </root> </loggers> </configuration>
可以看到仅生成了test1.log和test2.log,因为特意没有设置test3.log的File Appender
(2)不同线程使用不同的日志文件
log4j2.xml配置
<?xml version="1.0" encoding="UTF-8"?> <!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出--> <!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数--> <configuration monitorInterval="5"> <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --> <Properties> <property name="LOG_PATTERN">"%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"</property> <property name="FILE_PATH">logs</property> </Properties> <appenders> <console name="Console" target="SYSTEM_OUT"> <!--输出日志的格式--> <PatternLayout pattern="${LOG_PATTERN}"/> <!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> </console> <Routing name="Routing"> <Routes pattern="$${thread:threadName}"> <Route> <RollingFile name="logFile-${thread:threadName}" fileName="logs/concurrent-${thread:threadName}.log" filePattern="logs/concurrent-${thread:threadName}-%d{MM-dd-yyyy}-%i.log"> <PatternLayout pattern="%d %-5p [%t] %C{2} - %m%n" /> <Policies> <SizeBasedTriggeringPolicy size="50 MB" /> </Policies> <DefaultRolloverStrategy max="100" /> </RollingFile> </Route> </Routes> </Routing> <Async name="async" bufferSize="1000" includeLocation="true"> <AppenderRef ref="Routing" /> </Async> </appenders> <!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。--> <!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效--> <loggers> <Logger name="com.example.demo.logPackage3" level="info" additivity="false"> <AppenderRef ref="Console"/> <AppenderRef ref="async" /> </Logger> <root name="root" level="info"> <appender-ref ref="Console"/> <appender-ref ref="Filelog"/> <appender-ref ref="RollingFile"/> </root> </loggers> </configuration>
java 配置
package com.example.demo.logPackage3; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.config.plugins.Plugin; import org.apache.logging.log4j.core.lookup.StrLookup; /** * @author Administrator * @since 2021/7/13 23:47 */ @Plugin(name = "thread", category = StrLookup.CATEGORY) public class ThreadLookup implements StrLookup { @Override public String lookup(String key) { return Thread.currentThread().getName(); } @Override public String lookup(LogEvent event, String key) { return event.getThreadName() == null ? Thread.currentThread().getName() : event.getThreadName(); } }
(1)SLF4J: Class path contains multiple SLF4J bindings
SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/C:/Users/Administrator/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/C:/Users/Administrator/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.13.3/log4j-slf4j-impl-2.13.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
可以看到还是logback和sl4j2冲突了,我们生成依赖树,可以看到到logback只有Spring-boot-stater,然而到Spring-boot-stater的有两条路,为Spring-boot-stater-test和spring-boot-stater-web,查看Spring-boot-test依赖可以看到,确实依赖了logback,将test的logback也排除后,解决问题:
http://logging.apache.org/log4j/2.x/manual/lookups.html log4j2官网文档
https://www.docs4dev.com/docs/zh/log4j2/2.x/all/manual-appenders.html 中文翻译文档