Layout 決定日誌事件最終輸出的文本格式。每個 Appender 僅能關聯一個 Layout。自訂 Layout 需繼承 log4net.Layout.LayoutSkeleton 並實作 ILayout。
| Layout | 特點 | 適用場景 |
|---|---|---|
PatternLayout | 靈活模式字串,效能最佳 | 90% 生產環境首選 |
XmlLayout / XmlLayoutSchemaLog4j | 輸出結構化 XML,便於工具解析 | ELK、Splunk、日誌分析平台 |
SimpleLayout | 極簡格式:`Level - Message` | 快速調試、控制台輸出 |
RawTimeStampLayout | 僅輸出時間戳 | 特殊時間同步需求 |
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
| 模式 | 含義 | 範例輸出 |
|---|---|---|
%m / %message | 日誌消息 | User login successful |
%n / %newline | 平台相關換行符 | \r\n (Windows) |
%d / %date | 時間戳,可指定格式 `%d{yyyy-MM-dd HH:mm:ss.fff}` | 2024-01-15 14:30:45.123 |
%r | 應用啟動至今毫秒數 | 12345 |
%t / %thread | 線程名/ID | MainThread / 12 |
%p / %level | 日誌級別 | DEBUG / ERROR |
%c / %logger | Logger 名稱(通常為類全名) | MyApp.Services.UserService |
%C / %class | 調用類名(效能較差,慎用) | UserService |
%M / %method | 調用方法名(效能較差,慎用) | LoginAsync |
%F / %file | 源文件名(需 PDB,慎用) | UserService.cs |
%L / %line | 源代碼行號(需 PDB,慎用) | 42 |
%x / %ndc | 巢狀診斷上下文 | UserId=123 |
%X{key} / %mdc{key} | 映射診斷上下文鍵值 | TraceId=abc-123 |
%-5level | 左對齊,寬度 5,不足填空格 | `DEBUG ` / `ERROR ` |
Filter 掛載在 Appender 之下,按定義順序鏈式過濾。常用內建 Filter:
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="INFO" />
<param name="LevelMax" value="WARN" />
</filter>
僅允許 `INFO`、`WARN` 通過,`DEBUG` 被丟棄,`ERROR`/`FATAL` 也被丟棄(因超出 Max)。
<filter type="log4net.Filter.LevelMatchFilter">
<param name="LevelToMatch" value="ERROR" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" /> <!-- 關鍵:拒絕所有其他 -->
組合 `DenyAllFilter` 實現「僅記錄 ERROR」效果。
<filter type="log4net.Filter.StringMatchFilter">
<param name="StringToMatch" value="Password" />
<param name="AcceptOnMatch" value="false" /> <!-- 包含密碼的日誌直接丟棄 -->
</filter>
基於 MDC/NDC 屬性或 Logger 名稱過濾,支援多租戶、多模塊日誌路由。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="log4net"
type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<!-- 根 Logger:所有 Logger 的最終 fallback -->
<root>
<level value="WARN" /> <!-- 根級別閾值 -->
<appender-ref ref="FileAppender" />
<appender-ref ref="ConsoleAppender" />
</root>
<!-- 特定 Logger:覆蓋根配置 -->
<logger name="MyApp.Data" additivity="false"> <!-- additivity=false 斷開向根傳遞 -->
<level value="DEBUG" />
<appender-ref ref="SqlAppender" />
</logger>
<!-- Appender 定義 -->
<appender name="FileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="logs/app.log" />
<param name="AppendToFile" value="true" />
<param name="RollingStyle" value="Composite" /> <!-- 按大小+日期滾動 -->
<param name="MaxSizeRollBackups" value="10" />
<param name="MaximumFileSize" value="10MB" />
<param name="DatePattern" value="yyyyMMdd" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="INFO" />
<param name="LevelMax" value="FATAL" />
</filter>
</appender>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
</layout>
</appender>
</log4net>
</configuration>
additivity="false":阻斷該 Logger 向祖先(根)傳遞日誌事件,避免重複寫入。RollingFileAppender 參數:`RollingStyle` 可為 `Size`、`Date`、`Composite`、`Once`。LevelMin/Max:包含邊界,即 `Min ≤ Level ≤ Max` 通過。[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]
// 放在 AssemblyInfo.cs 或 Program.cs 頂部
Watch=true:啟用 `FileSystemWatcher`,配置文件變更自動重載,**無需重啟應用**。ConfigFile 與 ConfigFileExtension 二擇一。var repo = LogManager.GetRepository(Assembly.GetEntryAssembly());
XmlConfigurator.Configure(repo, new FileInfo("config/log4net.prod.xml"));
// 或監視變更
XmlConfigurator.ConfigureAndWatch(repo, new FileInfo("config/log4net.xml"));
// 單一 Appender + PatternLayout
BasicConfigurator.Configure(
new RollingFileAppender {
File = "app.log",
AppendToFile = true,
RollingStyle = RollingFileAppender.RollingMode.Composite,
MaxSizeRollBackups = 5,
MaximumFileSize = "5MB",
Layout = new PatternLayout("%d [%t] %-5p %c - %m%n")
}
);
// 僅控制台輸出
BasicConfigurator.Configure(new ConsoleAppender {
Layout = new PatternLayout("%d [%t] %-5p %c - %m%n")
});
限制:程式化配置僅作用於根 Logger,無法精細控制各模塊級別。
public class OrderService {
// 靜態唯讀,按類名建立 Logger,層級結構自動對應配置
private static readonly ILog Log = LogManager.GetLogger(typeof(OrderService));
public void PlaceOrder(Order order) {
// 1. 級別檢查避免字串構建開銷(高頻調用關鍵)
if (Log.IsDebugEnabled)
Log.Debug($"訂單詳情:{JsonSerializer.Serialize(order)}");
try {
_repository.Save(order);
Log.Info($"訂單建立成功:{order.Id}");
}
catch (Exception ex) {
// 2. 結構化異常記錄,保留堆疊
Log.Error($"建立訂單失敗:{order.Id}", ex);
throw;
}
}
}
WARN,業務模塊 Logger 覆蓋為 INFO/DEBUG。LevelRangeFilter,錯誤日誌單獨寫入錯誤檔,便於告警掃描。AsyncAppender(緩衝隊列 + 專用線程寫入),降低業務線程阻塞。