log4net 作為 log4j 的 .NET 移植版,成熟穩定、配置靈活。搭配 SQL Server 集中儲存日誌,便於跨伺服器查詢、報表分析與告警整合。本文記錄在 ASP.NET 2.0 / VS2005 環境下,採用非侵入式獨立配置檔的完整部署步驟。
log4net.dll,確保目標框架一致。MainWeb.csproj)加入參考;若為純 ASPX 無 Code-behind,則在共用基底專案(如 Common.Web.csproj)引用並初始化。// Global.asax.cs
protected void Application_Start(Object sender, EventArgs e)
{
log4net.Config.XmlConfigurator.Configure(
new System.IO.FileInfo("log4net.config"));
}
在 AssemblyInfo.cs 加入組件屬性,啟用檔案監視自動重載:
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]
放置於網站根目錄(與 web.config 同層),採用 ADONetAppender 直接寫入 SQL Server:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<appender name="ADONetAppender" type="log4net.Appender.ADONetAppender">
<bufferSize value="10" /> <!-- 批次寫入緩衝,除錯改 1,正式建議 100 -->
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="Data Source=myserver;Initial Catalog=DBErrorLogs;User ID=user;Password=pwdpwd;Connect Timeout=15;" />
<commandText value="INSERT INTO ErrorLog ([dtDate],[sThread],[sLevel],[sLogger],[sMessage],[sException]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)" />
<parameter>
<parameterName value="@log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value="@thread" />
<dbType value="String" />
<size value="100" />
<layout type="log4net.Layout.PatternLayout"><conversionPattern value="%t" /></layout>
</parameter>
<parameter>
<parameterName value="@log_level" />
<dbType value="String" />
<size value="200" />
<layout type="log4net.Layout.PatternLayout"><conversionPattern value="%p" /></layout>
</parameter>
<parameter>
<parameterName value="@logger" />
<dbType value="String" />
<size value="500" />
<layout type="log4net.Layout.PatternLayout"><conversionPattern value="%logger" /></layout>
</parameter>
<parameter>
<parameterName value="@message" />
<dbType value="String" />
<size value="3000" />
<layout type="log4net.Layout.PatternLayout"><conversionPattern value="%m" /></layout>
</parameter>
<parameter>
<parameterName value="@exception" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
</appender>
<root>
<level value="INFO" /> <!-- 僅保留單一 level,依需求調整 DEBUG/WARN/ERROR -->
<appender-ref ref="ADONetAppender" />
</root>
<logger name="iNotes">
<level value="DEBUG" />
<appender-ref ref="ADONetAppender" />
</logger>
<logger name="StellaLogger">
<level value="ALL" />
<appender-ref ref="ADONetAppender" />
</logger>
</log4net>
</configuration>
SET ANSI_NULLS ON; SET QUOTED_IDENTIFIER ON; SET ANSI_PADDING ON;
GO
CREATE TABLE [dbo].[ErrorLog](
[nId] [bigint] IDENTITY(1,1) NOT NULL,
[dtDate] [datetime] NOT NULL DEFAULT (GETDATE()),
[sThread] [varchar](100) NOT NULL,
[sLevel] [varchar](200) NOT NULL,
[sLogger] [varchar](500) NOT NULL,
[sMessage] [varchar](3000) NOT NULL,
[sException] [varchar](4000) NULL,
CONSTRAINT [PK_ErrorLog] PRIMARY KEY CLUSTERED ([nId] ASC)
) ON [PRIMARY];
GO
// 每個類別靜態實例,自動取得完整型別名稱作為 logger name
private static readonly log4net.ILog log =
log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
// 使用範例
try
{
// 業務邏輯
}
catch (Exception ex)
{
string loginId = GetCurrentUserLoginId(); // 取得使用者識別
log.Error($"User:{loginId} 發生業務異常", ex); // 同時記錄訊息與完整堆疊
}
| nId | dtDate | sThread | sLevel | sLogger | sMessage | sException |
|---|---|---|---|---|---|---|
| 1 | 2008-11-21 11:03:20.470 | 1904 | ERROR | Agronet.Product.Web.UI.Controls.Vegnet.Detail | 10.103.33.10 | System.OverflowException: 值對於 Int16 太大或太小。... 完整堆疊追蹤 ... |
1 即時寫入;正式環境建議 100 以上,減少資料庫連線頻率。Connect Timeout 避免長時間封鎖。root 設定預設等級(如 INFO),特定 logger 可覆蓋為 DEBUG/ALL,避免產生過量日誌。ExceptionLayout 會完整序列化堆疊,配合 @exception VARCHAR(4000),超長截斷可考慮 MAX 或分表。log4net SDK 文件 - 涵蓋所有 Appender、Layout、Filter 進階用法。