日志写入数据库

  • 文件日志:需要登录服务器、下载/打开文本文件查看,检索困难;
  • 数据库日志:可直接在后台开发日志管理页面,支持SQL条件检索、筛选、分页查询;
  1. 便于统一运维、日志审计、异常追踪。

缺点:高频日志场景会增加数据库压力,生产可结合缓冲写入、分表、定期清理旧日志优化。

1 创建日志表(SQL Server)

-- 日志表 Log
create table Log (
    Id bigint identity,
    AddTime datetime not null,
    Thread nvarchar(100) not null,
    Level nvarchar(200) not null,
    Logger nvarchar(500) not null,
    Message nvarchar(3000) not null,
    Exception nvarchar(4000) null,
    constraint PK_LOG primary key (Id)
)
go

-- ========== 字段注释(可选,方便数据库查看) ==========
declare @CurrentUser sysname
select @CurrentUser = user_name()
execute sp_addextendedproperty 'MS_Description',
'Log4net日志表',
'user', @CurrentUser, 'table', 'Log'
go

declare @CurrentUser sysname
select @CurrentUser = user_name()
execute sp_addextendedproperty 'MS_Description',
'日志主键',
'user', @CurrentUser, 'table', 'Log', 'column', 'Id'
go

declare @CurrentUser sysname
select @CurrentUser = user_name()
execute sp_addextendedproperty 'MS_Description',
'添加时间',
'user', @CurrentUser, 'table', 'Log', 'column', 'AddTime'
go

declare @CurrentUser sysname
select @CurrentUser = user_name()
execute sp_addextendedproperty 'MS_Description',
'所在线程',
'user', @CurrentUser, 'table', 'Log', 'column', 'Thread'
go

declare @CurrentUser sysname
select @CurrentUser = user_name()
execute sp_addextendedproperty 'MS_Description',
'日志级别(Info/Debug/Error等)',
'user', @CurrentUser, 'table', 'Log', 'column', 'Level'
go

declare @CurrentUser sysname
select @CurrentUser = user_name()
execute sp_addextendedproperty 'MS_Description',
'日志记录器名称',
'user', @CurrentUser, 'table', 'Log', 'column', 'Logger'
go

declare @CurrentUser sysname
select @CurrentUser = user_name()
execute sp_addextendedproperty 'MS_Description',
'日志消息内容',
'user', @CurrentUser, 'table', 'Log', 'column', 'Message'
go

declare @CurrentUser sysname
select @CurrentUser = user_name()
execute sp_addextendedproperty 'MS_Description',
'异常信息',
'user', @CurrentUser, 'table', 'Log', 'column', 'Exception'
goCode language: PHP (php)

字段说明:

字段说明
Id自增主键
AddTime日志发生时间
Thread触发日志的线程名
Level日志等级:DEBUG/INFO/WARN/ERROR/FATAL
Logger当前Logger名称(类全名)
Message普通日志文本
Exception异常堆栈信息,无异常时为空

2 NuGet 安装包

Install-Package log4net

.NET Framework 直接使用;.NET Core/.NET5+/ASP.NET Core 同样兼容。

3 完整 log4net 配置(App.config / Web.config)

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- 注册log4net配置节点 -->
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>

  <log4net>
    <!-- ADONetAppender:数据库写入附加器 -->
    <appender name="ADONetAppender" type="log4net.Appender.ADONetAppender">
      <!-- bufferSize=1:不缓冲,实时写入;调大可以批量写入降低数据库压力 -->
      <bufferSize value="1" />

      <!-- SqlServer 连接驱动类型 -->
      <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

      <!-- 数据库连接字符串,自行修改库名、账号密码 -->
      <connectionString value="DATABASE=log4netdemo;SERVER=.;UID=sa;PWD=pwdpwd;Connect Timeout=15;" />

      <!-- 插入SQL,字段必须和数据表、参数一一对应 -->
      <commandText value="INSERT INTO Log ([AddTime],[Thread],[Level],[Logger],[Message],[Exception])
VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)" />

      <!-- 参数1:日志时间 -->
      <parameter>
        <parameterName value="@log_date" />
        <dbType value="DateTime" />
        <layout type="log4net.Layout.RawTimeStampLayout" />
      </parameter>

      <!-- 参数2:线程名称 -->
      <parameter>
        <parameterName value="@thread" />
        <dbType value="String" />
        <size value="100" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%t" />
        </layout>
      </parameter>

      <!-- 参数3:日志级别 -->
      <parameter>
        <parameterName value="@log_level" />
        <dbType value="String" />
        <size value="200" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%p" />
        </layout>
      </parameter>

      <!-- 参数4:Logger名称 -->
      <parameter>
        <parameterName value="@logger" />
        <dbType value="String" />
        <size value="500" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%c" />
        </layout>
      </parameter>

      <!-- 参数5:日志消息 -->
      <parameter>
        <parameterName value="@message" />
        <dbType value="String" />
        <size value="3000" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%m" />
        </layout>
      </parameter>

      <!-- 参数6:异常信息 -->
      <parameter>
        <parameterName value="@exception" />
        <dbType value="String" />
        <size value="4000" />
        <layout type="log4net.Layout.ExceptionLayout" />
      </parameter>
    </appender>

    <!-- 根日志器,启用数据库输出 -->
    <root>
      <level value="Info" />
      <appender-ref ref="ADONetAppender" />
      <!-- 可以同时追加文件日志,双输出:<appender-ref ref="文件附加器名称"/> -->
    </root>
  </log4net>
</configuration>Code language: HTML, XML (xml)

重要补充:截图里只展示了前2个parameter,完整配置需要补齐所有6个参数,否则启动报错!

4 代码启用 log4net

1. .NET Framework Web项目(Global.asax)
protected void Application_Start(object sender, EventArgs e)
{
    // 加载log4net配置
    log4net.Config.XmlConfigurator.Configure();
}Code language: JavaScript (javascript)
2. 控制台 / WinForms

Program.cs Main方法第一行:

log4net.Config.XmlConfigurator.Configure();Code language: CSS (css)
3. 日常使用代码
// 获取日志实例
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

// 打印普通日志
log.Info("系统启动成功");

// 打印异常日志
try
{
    int a = 1 / 0;
}
catch (Exception ex)
{
    log.Error("发生运算异常", ex);
}Code language: PHP (php)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注