商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > c#如何使用Log4Net_c#Log4Net完整教程与代码实例

c#如何使用Log4Net_c#Log4Net完整教程与代码实例

  发布于2026-07-20 阅读(0)

扫一扫,手机访问

Log4Net 在 .NET Framework 项目中依然常见,但一个关键信息需要明确:它已于 2023 年正式进入维护模式,不再开发新功能,并且不支持 .NET 6+ 的原生 Microsoft.Extensions.Logging 抽象。如果你正在启动新项目,直接使用 Microsoft.Extensions.Logging 搭配 ConsoleFile 提供程序,是更稳妥也更现代的选择。不过,如果你必须对接遗留系统,或者手头已有成熟的 Log4Net 配置,那么掌握它的正确用法就至关重要了——尤其是那些容易踩坑的细节。

如何正确初始化 Log4Net(避免“Logger is null”)

Log4Net 不会自动扫描配置文件,你必须显式调用初始化方法,而且这一步只能执行一次。多次调用虽然不会报错,但会导致配置丢失或行为异常,得不偿失。

  • XmlConfigurator.Configure() 只加载 App.config 或 Web.config 中的 节点,前提是配置节已在 configSections 中注册。
  • 更推荐的做法是使用 XmlConfigurator.Configure(Assembly.GetCallingAssembly(), new FileInfo("log4net.config")) 加载外部 XML 文件,这样配置更独立,也更容易维护和替换。
  • 务必在调用 LogManager.GetLogger() 之前完成初始化。典型的位置是 Program.cs(.NET Framework)或 Global.asax Application_Start
  • 在 ASP.NET Core 中无法直接使用这种方式,因为 LogManager 依赖 AppDomain,而 Core 采用的是 HostBuilder 模型。

为什么 GetLogger(typeof(T)) 和 GetLogger("name") 行为不同

Log4Net 的 Logger 实例本质上是按名称查找的。GetLogger(typeof(T)) 等价于 GetLogger(typeof(T).FullName),而 GetLogger("MyApp.Service") 则创建了一个独立命名空间下的 Logger。两者在日志级别和 Appender 绑定上是完全独立的——即使你在配置中写了 ,也不会匹配 typeof(MyApp.Service.UserService) 生成的 Logger 名称。

层级匹配依赖于点号(.)分隔。例如,MyApp.ServiceMyApp 的子 Logger,可以继承父级的 Level 和 Appender,但需要通过 additivity="false" 来控制是否叠加。调试时,可以使用 LogManager.GetCurrentLoggers() 来查看当前所有已创建的 Logger 名称,避免拼写错误或层级误解。

FileAppender 写入失败的常见原因

日志文件打不开、没内容、权限报错——这些问题 90% 都出在 FileAppender 的配置环节上。

  • File 路径如果写的是相对路径(比如 "logs/app.log"),实际路径会基于 AppDomain.CurrentDomain.BaseDirectory,而不是 exe 所在目录。尤其是在 IIS 部署时,BaseDirectory 是 w3wp.exe 的路径,很容易搞错。
  • 如果没有设置 AppendToFile="true",每次启动都会覆盖日志。另外,若未设置 LockingModel type="log4net.Appender.FileAppender+MinimalLock",多进程或多 AppDomain 下写入会直接抛出 IOException
  • 在 Windows 环境下,如果路径包含中文或空格,记得用双引号包裹 XML 中的路径,同时确保应用有对应目录的写入权限(IIS 应用池标识用户需要授权)。
  • 建议改用 RollingFileAppender,配合 MaximumFileSizeMaxSizeRollBackups,避免单个文件过大或磁盘被占满。

与 ASP.NET Core 共存的现实路径

不能直接把 Log4Net 当作 .NET Core 的日志提供程序注入,但可以通过桥接方式保留旧的日志逻辑。

  • 使用 Microsoft.Extensions.Logging.Log4NetProvider NuGet 包(非官方,比如 Microsoft.Extensions.Logging.Log4Net.AspNetCore),它会把 ILogger 的调用转译为 Log4Net 的 ILog 调用。
  • 这个 Provider 只负责转发日志事件,并不接管配置——你仍然需要手动调用 XmlConfigurator.Configure() 来初始化 Log4Net。
  • 注意:Log4Net 的 PatternLayout 格式符(如 %date %level %logger - %message)不会自动解析 Microsoft.Extensions.Logging 的结构化日志参数。比如 logger.LogInformation("User {Id} logged in", userId) 中的 {Id} 会被原样输出为字符串,而不是被替换为实际值。
  • 如果你需要结构化日志,建议放弃 Log4Net,改用 SerilogNLog,它们原生支持 Microsoft.Extensions.Logging 的 message template 解析。

Log4Net 的核心陷阱不在语法,而在于生命周期管理——初始化遗漏、多线程争抢配置、路径权限误判,以及对 .NET Core 运行模型的误用。一旦在生产环境出现日志静默,优先检查 LogManager.GetCurrentLoggers() 返回是否为空,再确认 XmlConfigurator 是否真的被执行过,而不是翻来覆去地排查配置文件格式。

本文转载于:https://www.php.cn/faq/2324936.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注