c# 如何写日志 log4net

来源:这里教程网 时间:2026-02-21 17:40:08 作者:

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
,这三处最常让人对着空日志文件发呆。

相关推荐