目录
在 .NET Core 项目中使用 Log4Net 做日志记录,具有很多优势。尽管 .NET Core 自带了 ILogger
接口(如使用内置的 ConsoleLogger
、DebugLogger
等),但 Log4Net 提供了更强大、灵活和可配置的日志功能,尤其适合企业级应用或需要精细控制日志输出的场景。
1.添加包
添加 log4net 和 Microsoft.Extensions.Logging.Log4Net.AspNetCore 包。

2.新建公用类
创建 LogHelper 公共静态类。
using log4net;
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
namespace Frame5_LibraryLogger.LogHelper
{
/// <summary>
/// 日志类-记录调用名称
/// </summary>
public static class LogHelper
{
// 缓存 ILog 对象(线程安全)
private static readonly ConcurrentDictionary<string, ILog> _loggerCache = new ConcurrentDictionary<string, ILog>();
// 获取 ILog 实例(确保只初始化一次)
private static ILog GetLogger([CallerMemberName] string caller = "")
{
return _loggerCache.GetOrAdd(caller, LogManager.GetLogger);
}
/// <summary>
/// 记录 DEBUG 级别日志
/// </summary>
public static void Debug(string message, [CallerMemberName] string caller = "")
{
var logger = GetLogger(caller);
if (logger.IsDebugEnabled)
logger.Debug(message);
}
/// <summary>
/// 记录 INFO 级别日志
/// </summary>
public static void Info(string message, [CallerMemberName] string caller = "")
{
var logger = GetLogger(caller);
if (logger.IsInfoEnabled)
logger.Info(message);
}
/// <summary>
/// 记录 WARN 级别日志
/// </summary>
public static void Warn(string message, [CallerMemberName] string caller = "")
{
GetLogger(caller).Warn(message);
}
/// <summary>
/// 记录 ERROR 级别日志
/// </summary>
public static void Error(string message, Exception ex = null, [CallerMemberName] string caller = "")
{
var logger = GetLogger(caller);
if (ex != null)
logger.Error(message, ex);
else
logger.Error(message);
}
/// <summary>
/// 记录 FATAL 级别日志
/// </summary>
public static void Fatal(string message, Exception ex = null, [CallerMemberName] string caller = "")
{
var logger = GetLogger(caller);
if (ex != null)
logger.Fatal(message, ex);
else
logger.Fatal(message);
}
}
}
案例如下

3.新建配置
新建 log4net.config 应用程序配置文件
点击所需项目 → 添加 → 新建项目 → 右上角搜索 应用程序配置文件
<?xml version="1.0" encoding="utf-8"?>
<!-- XML文件声明,版本1.0,UTF-8编码 -->
<log4net>
<!-- 开始log4net配置 -->
<!-- 关闭所有Microsoft开头的命名空间日志 -->
<logger name="Microsoft">
<level value="OFF" />
</logger>
<!-- 关闭System开头的命名空间日志 -->
<logger name="System">
<level value="OFF" />
</logger>
<!-- INFO级别日志配置开始 -->
<appender name="InfoFileAppender" type="log4net.Appender.RollingFileAppender">
<!-- 定义一个名为InfoFileAppender的appender,使用滚动文件类型 -->
<file type="log4net.Util.PatternString" value="logs/INFO/INFO_" />
<!-- 日志文件路径模板,使用PatternString支持动态路径 -->
<datePattern value="yyyy-MM-dd'.txt'" />
<!-- 日期模式,用于文件滚动命名,每天生成一个新文件 -->
<staticLogFileName value="false" />
<!-- 不使用静态文件名,允许根据日期模式变化 -->
<appendToFile value="true" />
<!-- 以追加模式写入文件,不清空原有内容 -->
<rollingStyle value="Date" />
<!-- 滚动策略:按日期滚动 -->
<layout type="log4net.Layout.PatternLayout">
<!-- 定义日志输出布局为模式布局 -->
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
<!-- 日志格式:
%date - 日期时间
[%thread] - 线程ID
%-5level - 日志级别(左对齐,5字符宽度)
%logger - 记录器名称
%message - 日志消息
%newline - 换行符
-->
</layout>
<filter type="log4net.Filter.LevelMatchFilter">
<!-- 添加级别匹配过滤器 -->
<levelToMatch value="INFO" />
<!-- 只匹配INFO级别日志 -->
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<!-- 拒绝所有不匹配的日志 -->
</appender>
<!-- DEBUG级别日志配置开始 -->
<appender name="DebugFileAppender" type="log4net.Appender.RollingFileAppender">
<!-- 定义DEBUG级别appender -->
<file type="log4net.Util.PatternString" value="logs/DEBUG/DEBUG_" />
<!-- DEBUG日志文件路径 -->
<datePattern value="yyyy-MM-dd'.txt'" />
<!-- 日期格式 -->
<staticLogFileName value="false" />
<!-- 动态文件名 -->
<appendToFile value="true" />
<!-- 追加模式 -->
<rollingStyle value="Date" />
<!-- 按日期滚动 -->
<layout type="log4net.Layout.PatternLayout">
<!-- 布局配置 -->
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
<!-- 同INFO格式 -->
</layout>
<filter type="log4net.Filter.LevelMatchFilter">
<!-- DEBUG级别过滤器 -->
<levelToMatch value="DEBUG" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<!-- 拒绝其他级别 -->
</appender>
<!-- WARN级别日志配置开始 -->
<appender name="WarnFileAppender" type="log4net.Appender.RollingFileAppender">
<!-- WARN级别appender定义 -->
<file type="log4net.Util.PatternString" value="logs/WARN/WARN_" />
<!-- WARN日志路径 -->
<datePattern value="yyyy-MM-dd'.txt'" />
<!-- 日期格式 -->
<staticLogFileName value="false" />
<!-- 动态文件名 -->
<appendToFile value="true" />
<!-- 追加模式 -->
<rollingStyle value="Date" />
<!-- 按日期滚动 -->
<layout type="log4net.Layout.PatternLayout">
<!-- 布局配置 -->
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelMatchFilter">
<!-- WARN级别过滤器 -->
<levelToMatch value="WARN" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<!-- 拒绝其他级别 -->
</appender>
<!-- ERROR级别日志配置开始 -->
<appender name="ErrorFileAppender" type="log4net.Appender.RollingFileAppender">
<!-- ERROR级别appender -->
<file type="log4net.Util.PatternString" value="logs/ERROR/ERROR_" />
<!-- ERROR日志路径 -->
<datePattern value="yyyy-MM-dd'.txt'" />
<!-- 日期格式 -->
<staticLogFileName value="false" />
<!-- 动态文件名 -->
<appendToFile value="true" />
<!-- 追加模式 -->
<rollingStyle value="Date" />
<!-- 按日期滚动 -->
<layout type="log4net.Layout.PatternLayout">
<!-- 布局配置 -->
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelMatchFilter">
<!-- ERROR级别过滤器 -->
<levelToMatch value="ERROR" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<!-- 拒绝其他级别 -->
</appender>
<!-- FATAL级别日志配置开始 -->
<appender name="FatalFileAppender" type="log4net.Appender.RollingFileAppender">
<!-- FATAL级别appender -->
<file type="log4net.Util.PatternString" value="logs/FATAL/FATAL_" />
<!-- FATAL日志路径 -->
<datePattern value="yyyy-MM-dd'.txt'" />
<!-- 日期格式 -->
<staticLogFileName value="false" />
<!-- 动态文件名 -->
<appendToFile value="true" />
<!-- 追加模式 -->
<rollingStyle value="Date" />
<!-- 按日期滚动 -->
<layout type="log4net.Layout.PatternLayout">
<!-- 布局配置 -->
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelMatchFilter">
<!-- FATAL级别过滤器 -->
<levelToMatch value="FATAL" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<!-- 拒绝其他级别 -->
</appender>
<!-- 根记录器配置开始 -->
<root>
<!-- 根日志记录器配置 -->
<level value="ALL" />
<!-- 记录所有级别的日志 -->
<appender-ref ref="InfoFileAppender" />
<!-- 引用INFO appender -->
<appender-ref ref="DebugFileAppender" />
<!-- 引用DEBUG appender -->
<appender-ref ref="WarnFileAppender" />
<!-- 引用WARN appender -->
<appender-ref ref="ErrorFileAppender" />
<!-- 引用ERROR appender -->
<appender-ref ref="FatalFileAppender" />
<!-- 引用FATAL appender -->
</root>
</log4net>
<!-- log4net配置结束 -->
案例如下

4.注册
在 Program 或 Startup 中注册日志。
//构建 log4net 配置文件的完整路径
var configFilePath = Path.Combine(AppContext.BaseDirectory, "log4net.config");
//将 log4net 集成到 .NET Core 的统一日志系统中
builder.Logging.AddLog4Net(configFilePath);
案例如下

4.1.类库项目设置
如果是类库项目,需设置 log4net.config 文件属性
点击到文件 → 属性 → 设置
复制到输出目录:始终赋值 / 如果较新则复制
生成操作: 内容

5.使用
在需要的地方可以随意使用。
using Frame4_LibraryCore.BaseConfig;
using Frame5_LibraryLogger.LogHelper;
using Microsoft.AspNetCore.Mvc;
namespace DemoAPI.Controllers
{
/// <summary>
/// 日志测试控制器
/// </summary>
//[Authorize]// 保护整个控制器
[Route("api/[controller]/[action]")]//标记路由地址规格
[ApiController] // 标记该类为 API 控制器,启用一些默认的行为,如模型绑定、输入验证等
[ApiExplorerSettings(GroupName = nameof(ApiVersionInfo.V1))]//设置控制器的API版本
public class LoggerController : BaseController
{
/// <summary>
/// 测试日志
/// </summary>
/// <returns></returns>
[HttpGet]
public bool InsertLogAsync()
{
//测试日志
LogHelper.Info("Info");
LogHelper.Error("Error");
LogHelper.Debug("Debug");
LogHelper.Fatal("Fatal");
LogHelper.Warn("Warn");
return true;
}
}
}
案例如下
