log.net配置不生效的首要原因是未调用XmlConfigurator.Configure();其次需检查logger和appender的level阈值是否匹配;多线程场景必须使用带锁的RollingFileAppender而非FileAppender。

log4net 配置不生效?先确认 XmlConfigurator.Configure() 是否调用
绝大多数日志写不出来的根本原因,是没触发 log4net 的配置加载。它不会自动读取 App.config 或 Web.config 里的 节点。
必须在程序启动早期(如 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。二者都必须允许当前日志级别。
常见错误配置:
-
会让INFO及以下日志直接被 appender 丢弃,即使 root level 是 INFO - 若想输出 INFO,把 appender 的
threshold改成DEBUG或INFO - 多个 appender(如同时写文件和控制台)需各自检查
threshold,一个不满足就看不到对应输出
多线程下日志错乱或丢失?优先用 RollingFileAppender 而非 FileAppender
FileAppender 默认不加锁,高并发写入时极易出现内容覆盖、截断甚至 IOException。生产环境必须避免。
推荐配置带锁和滚动策略的 RollingFileAppender:
-
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,减少抽象层干扰 - 若需在 Controller 或 Service 中用,仍建议用
LogManager.GetLogger(GetType())获取类型绑定 logger,避免静态字段跨类型污染 - 注意
ILog接口的Warnformat()、ErrorFormat()等方法已废弃,统一用Warn(String format, params Object[] args)
log4net 的坑不在语法,而在配置时机、层级过滤和并发模型。配错一处,整条链路就静默失效——尤其 XmlConfigurator.Configure() 忘调、appender threshold 设太高、或还在用 FileAppender,这三处最常让人对着空日志文件发呆。