log4net 实战指南:老牌 .NET 日志框架的使用与维护

log4net 中文实战指南:Appender 与 Hierarchy 概念、代码与 XML 两种配置方式、五个日志级别、PatternLayout 模式字符串、RollingFileAppender 轮转、维护现状与迁移建议,以及观测云 DataKit 采集落地方案。

最佳实践
log4net 实战指南:老牌 .NET 日志框架的使用与维护技术指南封面

log4net 是 Apache log4j 的 .NET 移植,是 .NET 平台历史最悠久的日志框架之一,至今仍运行在大量企业存量系统中。本文讲解 log4net 的配置与用法、维护现状评估,以及存量系统的日志集中采集方法。

核心要点速览

  • log4net 三大件:Logger(产生日志)、Appender(决定去向)、Layout(决定格式),组合灵活但概念偏老。
  • 按版本评估维护与安全:核对实际版本、官方公告和依赖,不以项目年龄或更新频率推断安全。
  • RollingFileAppender 内建轮转:按大小/日期归档,运维友好。
  • 集中采集:保留现有文件输出,用解析脚本统一时间、级别和请求标识。

快速上手:代码配置方式

using System;
using log4net;
using log4net.Config;
using log4net.Appender;
using log4net.Layout;
using log4net.Repository.Hierarchy;

var hierarchy = (Hierarchy)LogManager.GetRepository();

var consoleAppender = new ConsoleAppender
{
    Layout = new PatternLayout("%date [%thread] %-5level %logger - %message%newline")
};
((PatternLayout)consoleAppender.Layout).ActivateOptions();
consoleAppender.ActivateOptions();
hierarchy.Root.Level = log4net.Core.Level.Info;
BasicConfigurator.Configure(hierarchy, consoleAppender);

var logger = LogManager.GetLogger(typeof(Program));
logger.Debug("Debug message");   // 不输出(级别 Info)
logger.Info("应用启动");
logger.Warn("配置缺失");
logger.Error("数据库连接失败", new InvalidOperationException("示例异常"));   // 第二个参数传异常;实际捕获的异常可包含堆栈
logger.Fatal("系统级故障");

五个级别:Debug → Info → Warn → Error → Fatal。

XML 配置方式(主流)

log4net 更常见的是 XML 声明式配置:

<log4net>
  <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
    <file value="logs/app.log" />
    <appendToFile value="true" />
    <rollingStyle value="Size" />
    <maxSizeRollBackups value="10" />
    <maximumFileSize value="100MB" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
    </layout>
  </appender>
  <root>
    <level value="INFO" />
    <appender-ref ref="RollingFile" />
  </root>
</log4net>

独立 log4net.config 文件须复制到输出目录并显式加载:XmlConfigurator.Configure(LogManager.GetRepository(), new System.IO.FileInfo(System.IO.Path.Combine(AppContext.BaseDirectory, "log4net.config")));无参数 Configure 不会自动猜测任意 XML 文件。RollingFileAppender 支持按大小、按日期或混合轮转——运维侧无需再依赖系统 logrotate。

PatternLayout 常用占位符

占位符 含义
%date 时间戳(%date{ISO8601} 指定格式)
%-5level 级别(左对齐占 5 字符)
%logger logger 名
%message 消息
%exception 异常堆栈
%property{key} MDC/属性上下文值

上下文与结构化

现代代码可用 LogicalThreadContext.Properties["user"] = name 提供逻辑上下文属性,并在 finally 中恢复原值或移除,避免请求间泄漏,经 %property{user} 输出。它不是现代意义的结构化 JSON——存量系统要 JSON 输出,可换用 log4net.Ext.Json 等扩展布局,再按实际输出配置解析脚本。

现状评估与迁移建议

  • 优点:文档与社区资料丰富、Appender 生态全、配置灵活、稳定可靠;
  • 短板:是否支持所需 JSON 形态需核对具体版本和布局、无消息模板;
  • 建议:存量系统按版本与安全公告维护(JSON 扩展需另审兼容与维护);新系统选 Serilog 或内置 ILogger + Provider 体系;迁移可用"适配器先行"——业务代码面向 ILogger 抽象编程,底层实现随时替换。

采集并查询 log4net 日志

  1. 应用侧:可保留现有布局并解析;需要时选择经过版本兼容审查的 JSON 布局扩展,输出时间、级别、logger、消息、异常与属性字段,写滚动文件或控制台。
  2. DataKit 采集:按文件日志采集文档设置 logfiles、source 与 service。保留 PatternLayout 时,可用 Pipeline提取字段;改为 JSON 时同样先用样本验证字段和类型。
  3. Pipeline 标准化:级别映射标准 status,时间字段解析为 time;%property 中的 trace_id 提取为顶层字段。
  4. 检索告警:在日志查看器按服务查询 Error/Fatal 样本,确认堆栈完整,再配置日志检测。
  5. 留存:用索引规则区分调试与审计日志,并分别设置保留策略。

常见问题(FAQ)

log4net 还安全吗?

不能给“继续使用没有已知风险”的笼统保证,需核对安装版本和最新官方安全公告,不从更新频率推断漏洞响应。关注官方公告,核心系统建议规划向 Serilog/ILogger 的演进路线。

为什么我的 log4net 完全没输出?

最常见的三个原因:XmlConfigurator.Configure() 没执行;配置文件没复制到输出目录;root level 设置高于日志级别。log4net 静默失败的特性让这些坑只能靠检查内部调试输出(log4net.Util.LogLog.InternalDebugging = true)定位。

log4net 能多线程/多进程写同一文件吗?

线程内协调不等于多进程轮转安全;MinimalLock 也不能保证多个进程共享 RollingFileAppender 正确轮转,优先按进程分文件或统一日志接收。IIS 多实例场景尤其注意。

存量 log4net 系统值得迁 Serilog 吗?

看收益:需要结构化 JSON、消息模板、丰富 Sink 时值得。渐进式做法:新代码用 ILogger 抽象 + Serilog Provider,老代码保留 log4net,两者输出统一到同一目录,由 DataKit 一并采集。

系列阅读


获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台