Log4net多Appender异常:移除滚动文件Appender后数据库Appender才正常
这种情况我之前踩过类似的坑,大概率是日志级别关联问题或者数据库Appender的缓冲区策略导致的,给你几个实用的排查和解决方向:
1. 确保两个Appender都被正确关联到Logger
很多时候是根Logger或者自定义Logger只绑定了文件Appender,导致数据库Appender根本没收到日志请求。检查你的配置里,Logger节点有没有同时引用两个Appender:
正确的根Logger配置示例:
<root> <level value="DEBUG" /> <!-- 必须同时引用两个Appender --> <appender-ref ref="RollingFileAppender" /> <appender-ref ref="AdoNetAppender" /> </root>
如果是自定义命名空间的Logger,也要确保同时关联两个Appender:
<logger name="YourProject.Namespace"> <level value="INFO" /> <appender-ref ref="RollingFileAppender" /> <appender-ref ref="AdoNetAppender" /> </logger>
2. 调整Ado Net Appender的缓冲区/即时刷新设置
默认情况下,Ado Net Appender会用缓冲区批量写日志(默认BufferSize是100),如果缓冲区没满,日志不会立刻写入数据库。而文件Appender通常是即时刷新的,当你去掉文件Appender后,程序退出时log4net会强制刷新所有缓冲区,所以数据库能看到日志。
可以临时把数据库Appender改成即时刷新,验证是否是这个问题:
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender"> <!-- 开启即时刷新 --> <immediateFlush value="true" /> <!-- 缓冲区设为1,每条日志都写入 --> <bufferSize value="1" /> <!-- 你的连接字符串、SQL命令等其他配置 --> </appender>
确认问题后,生产环境可以再调大BufferSize来提升性能。
3. 检查日志级别是否一致
如果文件Appender的级别范围比数据库的宽,或者根Logger的级别设置过高,也会导致数据库Appender收不到日志。比如根Logger设为ERROR,但你只打了INFO级别的日志,那两个Appender都不会记录,但如果文件Appender单独设了更低的级别,就会出现文件有日志、数据库没有的情况。
确保两个Appender的级别配置是匹配的,或者数据库Appender的级别范围包含你要记录的日志类型。
4. 开启Log4net内部调试排查错误
如果上面的方法都没解决,开启log4net的内部调试,看看有没有隐藏的错误。在app.config里添加:
<appSettings> <add key="log4net.Internal.Debug" value="true" /> </appSettings> <system.diagnostics> <trace autoflush="true"> <listeners> <add name="log4netDebugListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="log4net_debug.log" /> </listeners> </trace> </system.diagnostics>
运行程序后查看生成的log4net_debug.log,里面会有详细的初始化过程、Appender加载情况和日志写入的错误信息,能直接帮你定位问题。
5. 排查过滤规则冲突
有没有给其中一个Appender加了Filter规则?比如文件Appender加了LevelRangeFilter只记录DEBUG到WARN的日志,而数据库Appender的Filter规则只允许ERROR以上,但你打的日志都是INFO,就会出现文件有日志、数据库没有的情况。
检查两个Appender的Filter配置,确保数据库Appender能接收到你要记录的日志类型。
内容的提问来源于stack exchange,提问作者Novica Josifovski

