Logback配置问题:无法将不同日志级别写入独立文件
问题分析与解决方案
错误原因
你遇到的Could not find an AppenderAttachable错误,本质是**<appender-ref>标签的嵌套位置错误**——Logback要求<appender-ref>必须放在<logger>或<root>这类支持附加Appender的节点内部,你之前的配置里把<appender-ref>放在了错误的层级(比如直接在<configuration>节点下,或者logger节点的外部),导致Logback找不到对应的容器来关联Appender,最终这些Appender无法生效。
正确配置示例
以下是实现「不同级别日志写入独立文件」的完整logback.xml配置,你可以直接参考替换:
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="30 seconds"> <!-- 控制台输出Appender --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <!-- INFO级别日志文件Appender --> <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/info.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern>logs/info.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <maxFileSize>100MB</maxFileSize> <maxHistory>30</maxHistory> <totalSizeCap>1GB</totalSizeCap> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> <!-- 只保留INFO级别日志 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>INFO</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- ERROR级别日志文件Appender --> <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/error.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern>logs/error.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <maxFileSize>100MB</maxFileSize> <maxHistory>30</maxHistory> <totalSizeCap>1GB</totalSizeCap> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> <!-- 只保留ERROR级别日志 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- WARN级别日志文件Appender --> <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/warn.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern>logs/warn.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <maxFileSize>100MB</maxFileSize> <maxHistory>30</maxHistory> <totalSizeCap>1GB</totalSizeCap> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> <!-- 只保留WARN级别日志 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>WARN</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- DEBUG级别日志文件Appender --> <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/debug.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern>logs/debug.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <maxFileSize>100MB</maxFileSize> <maxHistory>30</maxHistory> <totalSizeCap>1GB</totalSizeCap> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> <!-- 只保留DEBUG级别日志 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>DEBUG</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- Root Logger:关联所有Appender,设置最低级别为DEBUG以接收所有级别日志 --> <root level="DEBUG"> <appender-ref ref="STDOUT"/> <appender-ref ref="INFO_FILE"/> <appender-ref ref="ERROR_FILE"/> <appender-ref ref="WARN_FILE"/> <appender-ref ref="DEBUG_FILE"/> </root> </configuration>
关键配置要点
- Appender的LevelFilter:每个文件Appender通过
LevelFilter精准过滤对应级别日志,onMatch=ACCEPT表示匹配该级别时保留,onMismatch=DENY表示不匹配时直接丢弃,确保单个文件只写入对应级别日志。 - Root Logger级别设置:将root的级别设为你需要的最低级别(比如
DEBUG),确保所有级别的日志都能被root接收,再分发给各个Appender过滤处理。 <appender-ref>的嵌套:所有<appender-ref>必须放在<root>或<logger>节点内部,这是解决你之前错误的核心——Logback只有在这些节点下才能识别并关联Appender。
额外说明
如果你需要针对特定包的日志单独处理,可以添加独立的<logger>节点,例如:
<logger name="com.yourpackage" level="TRACE" additivity="false"> <appender-ref ref="DEBUG_FILE"/> </logger>
这里的additivity="false"表示该logger的日志不会再传递给root logger,避免重复输出。
内容的提问来源于stack exchange,提问作者MinionAttack
相关产品推荐
相关产品推荐

