日誌就會寫入資料庫

  • 檔案日誌:需要登入伺服器,下載並開啟文字檔案檢視,內容檢索不易;
  • 資料庫日誌:可於後台開發專用的日誌管理頁面,支援 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記錄器名稱(完整類別名)
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)

重要提醒:截圖往往只顯示前兩個 parameter,設定務必補齊全部六組參數,否則啟動就會報錯!

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)

日誌就會寫入資料庫

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *