log4net 配置不生效?先确认 XmlConfigurator.Configure()
是否调用
绝大多数日志写不出来的根本原因,是没触发 log4net 的配置加载。它不会自动读取
App.config或
Web.config里的
<log4net></log4net>节点。
必须在程序启动早期(如
Program.cs的
Main方法开头,或
Global.asax.cs的
Application_Start)显式调用:
log4net.Config.XmlConfigurator.Configure();
如果配置文件不是默认的
App.config,而是单独的
log4net.config,则传入路径:
log4net.Config.XmlConfigurator.Configure(new FileInfo("log4net.config"));
ASP.NET Core 项目中,Configure()必须在
WebHostBuilder构建前调用,否则
ILogger已初始化,log4net 不会接管 未调用该方法时,
LogManager.GetLogger(typeof(XXX))返回的 logger 实际是空壳,
IsDebugEnabled恒为
false,所有
Debug()/
Info()调用静默失败
logger.Info() 没输出?检查 level
和 appender
是否匹配
log4net 的日志能否写出,取决于两层过滤:Logger 自身的
level(如
INFO),以及每个
appender的
threshold。二者都必须允许当前日志级别。
常见错误配置:
<log4net>
<root>
<level value="INFO" />
<appender-ref ref="FileAppender" />
</root>
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<threshold value="WARN" /> <!-- 这里卡死了 INFO -->
<file value="logs/app.log" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
</log4net>
<threshold value="WARN"></threshold>会让
INFO及以下日志直接被 appender 丢弃,即使 root level 是 INFO 若想输出 INFO,把 appender 的
threshold改成
DEBUG或
INFO多个 appender(如同时写文件和控制台)需各自检查
threshold,一个不满足就看不到对应输出
多线程下日志错乱或丢失?优先用 RollingFileAppender
而非 FileAppender
FileAppender默认不加锁,高并发写入时极易出现内容覆盖、截断甚至 IOException。生产环境必须避免。
推荐配置带锁和滚动策略的
RollingFileAppender:
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<file value="logs/app.log" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
MinimalLock是轻量级文件锁,比
ExclusiveLock性能更好,且能避免进程崩溃后锁残留
rollingStyle="Size"+
maximumFileSize可防止单个日志文件无限膨胀 不要设
staticLogFileName="false"(即动态文件名),否则多进程时可能竞争创建同名文件
ASP.NET Core 中集成 log4net?绕过 ILogger
直接用原生 API
log4net 和 Microsoft.Extensions.Logging 是两套体系。强行包装成
ILoggerProvider容易引入线程上下文丢失(如
%property{User})、异步写入延迟等问题。
更稳的做法是:在 Startup 或 Program 中完成
XmlConfigurator.Configure(),然后在任意类中直接使用:
private static readonly ILog log = LogManager.GetLogger(typeof(Program));
// ...
log.Info("Application started");
不需要注册服务、不需要注入 ILogger<t></t>,减少抽象层干扰 若需在 Controller 或 Service 中用,仍建议用
LogManager.GetLogger(GetType())获取类型绑定 logger,避免静态字段跨类型污染 注意
ILog接口的
WarnFormat()、
ErrorFormat()等方法已废弃,统一用
Warn(string format, params object[] args)
log4net 的坑不在语法,而在配置时机、层级过滤和并发模型。配错一处,整条链路就静默失效——尤其
XmlConfigurator.Configure()忘调、appender
threshold设太高、或还在用
FileAppender,这三处最常让人对着空日志文件发呆。
