
log4j2 中自定义日志级别(如 bsharing_log)无法写入目标文件仅输出到控制台,根本原因是 appender 缺少精准的日志级别过滤机制,需通过 levelrangefilter 显式控制日志流向。
log4j2 中自定义日志级别(如 bsharing_log)无法写入目标文件仅输出到控制台,根本原因是 appender 缺少精准的日志级别过滤机制,需通过 levelrangefilter 显式控制日志流向。
在 Spring Boot 3.x(基于 Log4j2)项目中,为自定义日志级别(如 BSHARING_LOG)单独路由到指定文件(如 bsharing.log),不能仅依赖 配置的 level 属性——因为该属性仅控制该 Logger 实例是否接受该级别日志事件,并不保证日志一定被其引用的 Appender 处理;更关键的是,Appender 本身默认接收所有传入的日志事件,缺乏级别筛选逻辑。
原始配置中, 确实会捕获 BSHARING_LOG 级别日志,但问题在于:
-
bsharingLogAppender没有过滤器,它会接收所有发给它的日志(包括 INFO、WARN 等),而实际你只希望它处理BSHARING_LOG; - 同时,
appLogAppender 也未排除BSHARING_LOG,导致该级别日志可能被“误收”进application.log(尤其当additivity="true"或 Root Logger 覆盖时); - 更重要的是,你创建的 Logger 是
LogManager.getLogger(this.getClass())(即类名CustomSecurityFilter),而非"bsharinglogger"——这意味着日志根本没路由到,而是由 Root Logger 处理,最终只走 Console 和 appLog。
✅ 正确解法是:放弃专用 Logger 命名路由,改用 Root Logger 统一派发,并为每个 Appender 配置精准的 LevelRangeFilter,确保日志按级别分流:
<appenders><console name="Console" target="SYSTEM_OUT"><patternlayout pattern="${LOG_PATTERN}"></patternlayout></console><!-- application.log:接收 INFO 及以上,但明确排除 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}"></patternlayout><!-- 关键:拒绝 BSHARING_LOG,其余放行 --><levelrangefilter minlevel="INFO" maxlevel="FATAL" onmatch="ACCEPT" onmismatch="DENY"></levelrangefilter><levelrangefilter minlevel="BSHARING_LOG" maxlevel="BSHARING_LOG" onmatch="DENY" onmismatch="ACCEPT"></levelrangefilter><policies><sizebasedtriggeringpolicy size="19500KB"></sizebasedtriggeringpolicy></policies><defaultrolloverstrategy max="1"></defaultrolloverstrategy></rollingfile><!-- bsharing.log:仅接收且仅接收 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}"></patternlayout><!-- 关键:只接受 BSHARING_LOG,其余全部拒绝 --><levelrangefilter minlevel="BSHARING_LOG" maxlevel="BSHARING_LOG" onmatch="ACCEPT" onmismatch="DENY"></levelrangefilter><policies><sizebasedtriggeringpolicy size="19500KB"></sizebasedtriggeringpolicy></policies><defaultrolloverstrategy max="1"></defaultrolloverstrategy></rollingfile></appenders><loggers><root level="info"><appenderref ref="Console"></appenderref><appenderref ref="appLog"></appenderref><appenderref ref="bsharingLogAppender"></appenderref></root></loggers>
? 注意事项:
-
无需声明
:避免命名不匹配导致路由失效;统一由 Root Logger 分发更可靠。 -
LevelRangeFilter必须显式配置:onMatch="ACCEPT"/"DENY"与onMismatch="ACCEPT"/"DENY"需成对设计,确保逻辑无歧义(推荐优先用onMismatch="DENY"实现白名单式精确控制)。 -
日志调用保持简洁:代码中仍可使用
log.log(Level.forName("BSHARING_LOG", 350), "message"),无需更改 Logger 获取方式。 -
验证日志级别有效性:可在应用启动后,通过
Level.getLevel("BSHARING_LOG")打印其intLevel,确认与CustomLevel中定义一致(350)。 -
权限与路径检查:确保
logs/目录存在且应用有写权限,否则文件可能创建失败或为空。
通过此方案,BSHARING_LOG 日志将严格只写入 bsharing.log,其他级别日志则进入 application.log 和控制台,实现清晰、可控的日志分离。










