一、核心概念
| 术语 | 说明 |
|---|---|
ILog |
日志记录器接口,提供 Debug/Info/Warn/Error/Fatal 等方法 |
LogManager |
日志管理器,通过 GetLogger() 获取 ILog 实例 |
Appender |
日志输出目标(控制台、文件、数据库等),可叠加多个 |
Layout |
日志输出格式,常用 PatternLayout 自定义格式 |
Logger |
日志记录器名称,通常与类名对应,支持层级过滤 |
Root |
根 Logger,所有 Logger 的默认配置 |
Level |
日志级别:DEBUG < INFO < WARN < ERROR < FATAL |
二、安装与基础配置
1. 安装 NuGet 包
cs
# Package Manager
Install-Package log4net
# .NET CLI
dotnet add package log4net
2. App.config / Web.config 配置(.NET Framework)
cs
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<!-- 1. 声明 log4net 自定义配置节 -->
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<!-- 2. log4net 配置 -->
<log4net>
<!-- 文件输出 Appender -->
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="logs/myapp.log" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="5" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<!-- 根 Logger 配置 -->
<root>
<level value="ALL" />
<appender-ref ref="RollingFileAppender" />
</root>
</log4net>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>
3. .NET Core / .NET 5+ 配置(独立配置文件)
第一步: 创建 log4net.config 文件,设置属性为 复制到输出目录:
cs
<?xml version="1.0" encoding="utf-8"?>
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="logs/app.log" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyy-MM-dd" />
<staticLogFileName value="false" />
<encoding value="utf-8" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="RollingFileAppender" />
</root>
</log4net>
第二步: 在项目文件 .csproj 中配置自动复制:
cs
<ItemGroup>
<None Update="log4net.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
第三步: 初始化配置(二选一):
cs
// 方式1:AssemblyInfo.cs 中声明(推荐)
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]
// 方式2:Program.cs 中手动初始化(.NET 6+ 推荐)
var logRepository = log4net.LogManager.GetRepository(System.Reflection.Assembly.GetExecutingAssembly());
log4net.Config.XmlConfigurator.Configure(logRepository, new FileInfo("log4net.config"));
三、常用 Appender 分类
| Appender 类型 | 说明 | 常用场景 |
|---|---|---|
ConsoleAppender |
输出到控制台 | 开发调试 |
FileAppender |
输出到单个文件 | 简单日志 |
RollingFileAppender |
按大小/日期滚动文件 | 生产环境首选 |
AdoNetAppender |
输出到数据库 | 需要查询分析日志 |
EventLogAppender |
输出到 Windows 事件日志 | 系统级监控 |
SmtpAppender |
邮件发送日志 | 错误告警 |
UdpAppender |
UDP 远程发送 | 日志集中收集 |
RollingFileAppender 常用属性
| 属性 | 说明 | 示例值 |
|---|---|---|
file |
日志文件路径 | logs/app.log |
appendToFile |
是否追加写入 | true |
rollingStyle |
滚动方式 | Size / Date / Composite |
maxSizeRollBackups |
最大备份文件数 | 5 |
maximumFileSize |
单文件最大大小 | 10MB |
datePattern |
日期滚动格式 | yyyy-MM-dd |
staticLogFileName |
是否固定文件名 | true |
四、PatternLayout 格式化说明
conversionPattern 常用占位符:
| 占位符 | 简写 | 说明 | 示例输出 |
|---|---|---|---|
%date |
%d |
日志时间 | 2026-06-12 10:08:58,148 |
%thread |
%t |
线程ID | 1 |
%-5level |
%-5p |
日志级别(左对齐5字符) | INFO |
%logger |
%c |
Logger 名称 | loginfo |
%message |
%m |
日志内容 | 用户自定义消息 |
%newline |
%n |
换行符 | \r\n |
%exception |
- | 异常堆栈 | 完整异常信息 |
%type |
%C |
调用者类名 | MainFrm |
%method |
%M |
调用方法名 | Button_Click |
%file |
%F |
调用文件名 | MainFrm.cs |
%line |
%L |
调用行号 | 42 |
%property |
- | 线程属性 | 自定义值 |
%username |
- | 当前用户名 | DOMAIN\User |
性能警告 :
%type、%method、%file、%line等位置信息需要获取堆栈帧,会显著降低性能(约10倍),生产环境慎用!
推荐格式:
cs
<!-- 基础格式(推荐生产环境使用) -->
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
<!-- 详细格式(开发调试用,含异常堆栈) -->
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline%exception" />
<!-- 完整格式(仅开发环境,含调用位置) -->
<conversionPattern value="%date [%thread] %-5level %logger.%method:%line - %message%newline%exception" />
五、日志级别详解
| 级别 | 数值 | 用途 |
|---|---|---|
OFF |
2147483647 | 关闭所有日志 |
FATAL |
110000 | 致命错误,程序无法继续运行 |
ERROR |
70000 | 错误,但程序可继续运行 |
WARN |
40000 | 警告,潜在问题 |
INFO |
30000 | 一般信息,运行状态 |
DEBUG |
20000 | 调试信息,开发阶段使用 |
ALL |
-2147483648 | 开启所有日志 |
注意 :日志是否输出取决于 Root/Logger 配置的
level值,只有 >= 该级别的日志才会输出。
配置示例: 只记录 INFO 及以上级别
cs
<root>
<level value="INFO" />
<appender-ref ref="RollingFileAppender" />
</root>
六、LogHelper 封装(实战代码)
完整 LogHelper 工具类
cs
using System;
using System.IO;
using log4net;
namespace YourProject.Helper
{
/// <summary>
/// log4net 日志帮助类
/// </summary>
public static class LogHelper
{
/// <summary>
/// 信息日志记录器
/// </summary>
public static readonly ILog LogInfo = LogManager.GetLogger("loginfo");
/// <summary>
/// 错误日志记录器
/// </summary>
public static readonly ILog LogError = LogManager.GetLogger("logerror");
/// <summary>
/// 使用默认配置初始化(从 App.config/Web.config 读取)
/// </summary>
public static void SetConfig()
{
log4net.Config.XmlConfigurator.Configure();
}
/// <summary>
/// 使用指定配置文件初始化
/// </summary>
/// <param name="configFile">配置文件路径</param>
public static void SetConfig(FileInfo configFile)
{
log4net.Config.XmlConfigurator.Configure(configFile);
}
/// <summary>
/// 使用指定配置流初始化(适用于嵌入资源)
/// </summary>
/// <param name="configStream">配置文件流</param>
public static void SetConfig(Stream configStream)
{
log4net.Config.XmlConfigurator.Configure(configStream);
}
/// <summary>
/// 记录信息日志
/// </summary>
/// <param name="message">日志消息</param>
public static void WriteLog(string message)
{
if (LogInfo.IsInfoEnabled)
{
LogInfo.Info(message);
}
}
/// <summary>
/// 记录错误日志(含异常)
/// </summary>
/// <param name="message">日志消息</param>
/// <param name="ex">异常对象</param>
public static void WriteLog(string message, Exception ex)
{
if (LogError.IsErrorEnabled)
{
LogError.Error(message, ex);
}
}
/// <summary>
/// 记录调试日志
/// </summary>
/// <param name="message">日志消息</param>
public static void WriteDebug(string message)
{
if (LogInfo.IsDebugEnabled)
{
LogInfo.Debug(message);
}
}
/// <summary>
/// 记录警告日志
/// </summary>
/// <param name="message">日志消息</param>
public static void WriteWarn(string message)
{
if (LogInfo.IsWarnEnabled)
{
LogInfo.Warn(message);
}
}
/// <summary>
/// 记录致命错误日志
/// </summary>
/// <param name="message">日志消息</param>
/// <param name="ex">异常对象</param>
public static void WriteFatal(string message, Exception ex)
{
if (LogError.IsFatalEnabled)
{
LogError.Fatal(message, ex);
}
}
/// <summary>
/// 格式化记录信息日志
/// </summary>
/// <param name="format">格式化字符串</param>
/// <param name="args">参数</param>
public static void WriteLogFormat(string format, params object[] args)
{
if (LogInfo.IsInfoEnabled)
{
LogInfo.InfoFormat(format, args);
}
}
/// <summary>
/// 格式化记录错误日志
/// </summary>
/// <param name="format">格式化字符串</param>
/// <param name="args">参数</param>
public static void WriteErrorFormat(string format, params object[] args)
{
if (LogError.IsErrorEnabled)
{
LogError.ErrorFormat(format, args);
}
}
}
}
调用示例
cs
using YourProject.Helper;
// 1. 初始化配置(程序启动时调用一次)
// .NET Framework: 从 App.config 读取
LogHelper.SetConfig();
// .NET Core/5+: 指定配置文件
// var logRepository = LogManager.GetRepository(Assembly.GetExecutingAssembly());
// XmlConfigurator.Configure(logRepository, new FileInfo("log4net.config"));
// 2. 记录各类日志
LogHelper.WriteLog("程序启动成功");
LogHelper.WriteDebug("调试信息:变量 x = 100");
LogHelper.WriteWarn("警告:磁盘空间不足");
LogHelper.WriteLog("数据库连接失败", new Exception("连接超时"));
// 3. 格式化日志
LogHelper.WriteLogFormat("用户 {0} 登录成功,IP: {1}", "admin", "192.168.1.100");
LogHelper.WriteErrorFormat("请求 {0} 失败,状态码: {1}", "/api/user", 500);
WinForms 项目调用示例
cs
using log4net;
using YourProject.Helper;
public partial class MainFrm : Form
{
public MainFrm()
{
InitializeComponent();
// 窗体加载时初始化日志配置
LogHelper.SetConfig();
}
private void btnSearch_Click(object sender, EventArgs e)
{
try
{
LogHelper.WriteLog("开始查询数据");
// 业务逻辑...
LogHelper.WriteLog("查询完成");
}
catch (Exception ex)
{
LogHelper.WriteLog("查询失败", ex);
MessageBox.Show("查询出错,请查看日志");
}
}
private void button1_Click(object sender, EventArgs e)
{
// 测试各种日志级别
LogHelper.WriteDebug("调试信息");
LogHelper.WriteLog("一般信息");
LogHelper.WriteWarn("警告信息");
LogHelper.WriteLog("错误信息", new InvalidOperationException("测试异常"));
}
}
七、多 Logger 分类配置
按模块分离日志文件
cs
<log4net>
<!-- 系统日志 -->
<appender name="SystemAppender" type="log4net.Appender.RollingFileAppender">
<file value="logs/system.log" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyy-MM-dd" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level - %message%newline" />
</layout>
</appender>
<!-- 错误日志 -->
<appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender">
<file value="logs/error.log" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyy-MM-dd" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline%exception" />
</layout>
</appender>
<!-- 系统 Logger -->
<logger name="loginfo">
<level value="INFO" />
<appender-ref ref="SystemAppender" />
</logger>
<!-- 错误 Logger -->
<logger name="logerror">
<level value="ERROR" />
<appender-ref ref="ErrorAppender" />
</logger>
<!-- 根 Logger -->
<root>
<level value="ALL" />
<appender-ref ref="SystemAppender" />
</root>
</log4net>
八、常见问题排查
错误1:日志文件未生成
-
现象 :程序运行后
logs/目录下无日志文件 -
原因:未调用初始化配置 或 配置文件路径错误
-
解决:
cs
// 方式1:AssemblyInfo.cs 中声明(推荐,.NET Framework)
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]
// 方式2:代码中手动初始化
log4net.Config.XmlConfigurator.Configure(new FileInfo("log4net.config"));
// 方式3:.NET Core/5+ 推荐方式
var logRepository = LogManager.GetRepository(Assembly.GetExecutingAssembly());
XmlConfigurator.Configure(logRepository, new FileInfo("log4net.config"));
错误2:中文乱码
-
现象 :日志文件中中文显示为
????或乱码 -
原因:配置文件未指定编码
-
解决:
cs
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<encoding value="utf-8" />
<!-- 其他配置 -->
</appender>
错误3:日志未按日期滚动
-
现象:所有日志写入同一个文件
-
原因 :
rollingStyle和staticLogFileName配置错误 -
解决:
cs
<rollingStyle value="Date" />
<datePattern value="yyyy-MM-dd" />
<staticLogFileName value="false" />
错误4:configSections 报错
-
现象 :
ConfigurationErrorsException: 无法识别的配置节 log4net -
原因 :未在
configSections中声明(仅 .NET Framework 需要) -
解决:
cs
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
错误5:配置文件未复制到输出目录
-
现象:.NET Core 项目找不到配置文件
-
原因 :
log4net.config未复制到 bin 目录 -
解决:
cs
<!-- 在 .csproj 中添加 -->
<ItemGroup>
<None Update="log4net.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
错误6:日志写入性能问题
-
现象 :使用
%method、%file、%line后性能下降 -
原因:位置信息需要获取堆栈帧,开销大
-
解决:生产环境移除位置信息占位符
cs
<!-- 生产环境推荐 -->
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
<!-- 仅开发调试使用 -->
<conversionPattern value="%date [%thread] %-5level %logger.%method:%line - %message%newline" />
错误7:日志文件被锁定
-
现象:程序重启后无法写入日志
-
原因:FileAppender 默认锁定文件
-
解决 :使用
MinimalLock或切换到 RollingFileAppender
cs
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<!-- 其他配置 -->
</appender>
九、与现代日志框架对比
| 特性 | log4net | Serilog | NLog | Microsoft.Extensions.Logging |
|---|---|---|---|---|
| 维护状态 | 维护模式 | 活跃开发 | 活跃开发 | 官方支持 |
| 最新版本 | 3.x | 4.x | 5.x | 9.x |
| 结构化日志 | ❌ 不支持 | ✅ 原生支持 | ✅ 支持 | ✅ 支持 |
| .NET Core 支持 | ✅ 支持 | ✅ 原生 | ✅ 原生 | ✅ 原生 |
| 性能 | 良好 | 优秀 | 优秀 | 优秀 |
| 配置方式 | XML | 代码/JSON/XML | 代码/JSON/XML | 代码/JSON |
| 学习曲线 | 低 | 中 | 中 | 低 |
| 社区生态 | 成熟 | 活跃 | 活跃 | 官方生态 |
| 依赖注入集成 | ❌ 需适配 | ✅ 原生 | ✅ 原生 | ✅ 原生 |
选择建议:
-
旧项目维护:继续使用 log4net,迁移成本高
-
新项目推荐:Serilog(结构化日志)或 NLog(功能丰富)
-
ASP.NET Core 项目 :优先使用
Microsoft.Extensions.Logging+ Serilog/NLog 提供程序 -
快速上手:log4net 配置简单,适合小型桌面项目
总结
-
log4net 是 .NET 平台经典的日志框架,配置简单、输出灵活
-
核心三要素:
ILog(记录器)、Appender(输出目标)、Layout(格式) -
生产环境推荐
RollingFileAppender按大小/日期滚动 -
使用
LogHelper静态类封装,统一调用入口 -
中文环境务必配置
<encoding value="utf-8" /> -
避免在生产环境使用
%method、%file、%line等位置信息占位符 -
新项目建议评估 Serilog/NLog 作为替代方案
最佳实践速查表
| 场景 | 推荐配置 |
|---|---|
| 生产环境日志格式 | %date [%thread] %-5level %logger - %message%newline |
| 开发调试日志格式 | 添加 %exception 显示完整堆栈 |
| 日志文件滚动方式 | rollingStyle="Composite" + maxSizeRollBackups="10" |
| 日志文件大小限制 | maximumFileSize="50MB" |
| 日志文件编码 | <encoding value="utf-8" /> |
| 日志级别设置 | 生产环境 INFO,开发环境 DEBUG |
| 日志文件路径 | logs/app.log 或 logs/{appname}.log |