問題常發生在無偵錯環境的使用者機器上。.NET 內建 System.Diagnostics 命名空間提供完整診斷框架,支援執行期/組態檔動態配置,應優先使用而非自寫。
Debug:受 DEBUG 符號控制,通常僅偵錯建置啟用;Trace:受 TRACE 符號控制,預設偵錯/發行建置皆啟用,適合生產環境;EventLog:寫入 Windows 事件日誌,無執行期配置,可自行封裝統一介面。定義 TraceSwitch,在組態檔設定層級(0=Off, 1=Error, 2=Warning, 3=Info, 4=Verbose):
// 程式碼
static TraceSwitch librarySwitch = new TraceSwitch("MyAssembly", "此組件的開關");
Trace.WriteLineIf(librarySwitch.Level >= TraceLevel.Info, "進入 Method1", "MyAssembly");
// 組態檔
<system.diagnostics>
<switches>
<add name="MyAssembly" value="3" /> <!-- Info 級 -->
</switches>
</system.diagnostics>
修改組態檔即時生效,無需重新編譯部署。
預設 DefaultTraceListener 僅輸出至偵錯器。生產環境應加入 TextWriterTraceListener:
<system.diagnostics>
<trace autoflush="true" indentsize="0">
<listeners>
<add name="MyListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="MyListener.log" />
</listeners>
</trace>
</system.diagnostics>
所有 Trace.WriteLine 內容自動寫入 MyListener.log。
internal class MyAssemblyDiagnostics {
static TraceSwitch mySwitch = new TraceSwitch("MyAssembly", "...");
static TraceSwitch globalSwitch = new TraceSwitch("Global", "...");
internal static void Msg(TraceLevel level, string msg) {
Trace.WriteLineIf(mySwitch.Level >= level || globalSwitch.Level >= level, msg, "MyAssembly");
}
}
全域開關控制整體輸出層級,組件開關精準定位問題模組。
public void Method1() {
MyAssemblyDiagnostics.Msg(TraceLevel.Info, "Entering Method1");
if (!DoMoreWork())
MyAssemblyDiagnostics.Msg(TraceLevel.Warning, "DoMoreWork Failed");
MyAssemblyDiagnostics.Msg(TraceLevel.Info, "Exiting Method1");
}
.NET 診斷框架已解決核心難題:分級開關、多目標輸出、組態檔動態調整。開發者只需在關鍵點植入 Trace.WriteLineIf,即可在生產環境零成本獲得可觀測性。勿重複造輪子,善用內建工具。