Spring Boot集成Log4j2时自定义日志级别无法写入指定文件仅输出到控制台的问题排查
咱们先直奔核心问题——你配置里的Logger和代码里实际使用的Logger根本没对上!
先看你的代码:
private final Logger log = LogManager.getLogger(this.getClass());
这里获取的Logger名称是ru.bozza.Sharing.CustomSecurityFilter(也就是当前类的全限定名),但你在log4j2.xml里配置的Logger是:
<Logger name="bsharinglogger" level="BSHARING_LOG" additivity="false"> <AppenderRef ref="Console" /> <AppenderRef ref="bsharingLogAppender" /> </Logger>
这个Logger的名字是"bsharinglogger",和代码里的Logger名称完全不匹配,所以这个配置根本没生效!你的自定义级别日志实际上是由Root Logger在处理,而Root里默认只关联了Console和appLog两个Appender,自然不会输出到bsharing.log。当你把bsharingLogAppender加到Root里,Root就会把所有符合级别要求的日志(包括你的BSHARING_LOG)输出到这个文件,所以此时能看到内容,但这显然不是你想要的单独隔离的效果。
接下来给你两个可行的解决方案:
方案一:让代码使用配置中定义的Logger名称
直接修改代码里的Logger获取方式,明确指定使用"bsharinglogger"这个Logger:
private final Logger log = LogManager.getLogger("bsharinglogger");
这样你的自定义级别日志就会走配置好的Logger,自动输出到Console和bsharing.log,同时因为additivity设为false,不会再被Root重复处理。
方案二:修改Logger配置匹配代码中的Logger名称
如果你想让整个ru.bozza.Sharing包下的类都用这个自定义日志配置,可以把Logger的name改成包名(或者类的全限定名),同时合并原有的同名Logger配置(避免冲突):
<Logger name="ru.bozza.Sharing" level="BSHARING_LOG" additivity="false"> <AppenderRef ref="appLog" /> <!-- 保留原有输出到application.log的需求 --> <AppenderRef ref="Console" /> <!-- 保留控制台输出 --> <AppenderRef ref="bsharingLogAppender" /> <!-- 添加自定义日志文件输出 --> </Logger>
如果想让自定义级别日志只输出到bsharing.log,而其他级别日志输出到application.log,可以给两个Appender加上级别过滤:
给appLog添加过滤,排除BSHARING_LOG级别
<RollingFile name="appLog" fileName="${APP_LOG_ROOT}/application.log" filePattern="${APP_LOG_ROOT}/application-%d{yyyy-MM-dd}-%i.log"> <PatternLayout pattern="${LOG_PATTERN}" /> <!-- 新增过滤器:拒绝BSHARING_LOG级别,接受其他 --> <Filters> <ThresholdFilter level="BSHARING_LOG" onMatch="DENY" onMismatch="ACCEPT"/> </Filters> <Policies> <SizeBasedTriggeringPolicy size="19500KB" /> </Policies> <DefaultRolloverStrategy max="1" /> </RollingFile>
给bsharingLogAppender添加过滤,只接受BSHARING_LOG级别
<RollingFile name="bsharingLogAppender" fileName="${APP_LOG_ROOT}/bsharing.log" filePattern="${APP_LOG_ROOT}/bsharing-%d{yyyy-MM-dd}-%i.log"> <PatternLayout pattern="${LOG_PATTERN}" /> <!-- 新增过滤器:接受BSHARING_LOG级别,拒绝其他 --> <Filters> <ThresholdFilter level="BSHARING_LOG" onMatch="ACCEPT" onMismatch="DENY"/> </Filters> <Policies> <SizeBasedTriggeringPolicy size="19500KB" /> </Policies> <DefaultRolloverStrategy max="1" /> </RollingFile>
这样配置后,ru.bozza.Sharing包下的日志会自动分流:BSHARING_LOG级别只到bsharing.log和控制台,其他级别到application.log和控制台,完全符合你的需求。
最后再确认下你的自定义级别定义是正确的,<CustomLevel name="BSHARING_LOG" intLevel="350" />的数值介于WARN(300)和INFO(400)之间,代码里的Level.forName或Level.getLevel调用也没问题,不用调整。
备注:内容来源于stack exchange,提问作者Marvin

