これは、セットアップがかなり簡単な Enterprise Library を使用する 1 つのアプローチです。アクティビティ トレースを使用してグローバル コンテキストを保存し、拡張プロパティを使用してローカル コンテキストを保存できます。
例として、ラッパー クラスを使用せずにサービス ロケーターを使用してアプローチを示します。
var traceManager = EnterpriseLibraryContainer.Current.GetInstance<TraceManager>();
using (var tracer1 = traceManager.StartTrace("MyRequestId=" + GetRequestId().ToString()))
using (var tracer2 = traceManager.StartTrace("ClientID=" + clientId))
{
DoSomething();
}
static void DoSomething()
{
var logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
logWriter.Write("doing something", "General");
DoSomethingElse("ABC.txt");
}
static void DoSomethingElse(string fileName)
{
var logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
// Oops need to log
LogEntry logEntry = new LogEntry()
{
Categories = new string[] { "General" },
Message = "requested file not found",
ExtendedProperties = new Dictionary<string, object>() { { "filename", fileName } }
};
logWriter.Write(logEntry);
}
構成は次のようになります。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
</configSections>
<loggingConfiguration name="" tracingEnabled="true" defaultCategory="General"
logWarningsWhenNoCategoriesMatch="false">
<listeners>
<add name="Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
fileName="trace.log" formatter="Text Formatter" traceOutputOptions="LogicalOperationStack" />
</listeners>
<formatters>
<add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
template="Timestamp: {timestamp}
Message: {message}
ActivityID: {activity}
Context: {category}
Priority: {priority}
EventId: {eventid}
Severity: {severity}
Title:{title}
Machine: {localMachine}
App Domain: {localAppDomain}
ProcessId: {localProcessId}
Process Name: {localProcessName}
Thread Name: {threadName}
Win32 ThreadId:{win32ThreadId}
Local Context: {dictionary({key} - {value}{newline})}"
name="Text Formatter" />
</formatters>
<categorySources>
<add switchValue="All" name="General">
<listeners>
<add name="Flat File Trace Listener" />
</listeners>
</add>
</categorySources>
<specialSources>
<allEvents switchValue="All" name="All Events" />
<notProcessed switchValue="All" name="Unprocessed Category" />
<errors switchValue="All" name="Logging Errors & Warnings" />
</specialSources>
</loggingConfiguration>
</configuration>
これにより、次のような出力が得られます。
----------------------------------------
Timestamp: 1/16/2013 3:50:11 PM
Message: doing something
ActivityID: 5b765d8c-935a-445c-b9fb-bde4db73124f
Context: General, ClientID=123456, MyRequestId=8f2828be-44bf-436c-9e24-9641963db09a
Priority: -1
EventId: 1
Severity: Information
Title:
Machine: MACHINE
App Domain: LoggingTracerNDC.exe
ProcessId: 5320
Process Name: LoggingTracerNDC.exe
Thread Name:
Win32 ThreadId:8472
Local Context:
----------------------------------------
----------------------------------------
Timestamp: 1/16/2013 3:50:11 PM
Message: requested file not found
ActivityID: 5b765d8c-935a-445c-b9fb-bde4db73124f
Context: General, ClientID=123456, MyRequestId=8f2828be-44bf-436c-9e24-9641963db09a
Priority: -1
EventId: 0
Severity: Information
Title:
Machine: MACHINE
App Domain: LoggingTracerNDC.exe
ProcessId: 5320
Process Name: LoggingTracerNDC.exe
Thread Name:
Win32 ThreadId:8472
Local Context: filename - ABC.txt
----------------------------------------
注意事項:
- トレースを使用しているため、アクティビティの関連付けに使用できる .NET アクティビティ ID を無料で取得できます。もちろん、独自のコンテキスト情報 (カスタム リクエスト ID、クライアント ID など) も使用できます。
- Enterprise Library はトレースの「操作名」をカテゴリとして使用するため、logWarningsWhenNoCategoriesMatch="false" を設定する必要があります。そうしないと、警告メッセージが次々と表示されます。
- このアプローチの欠点は、パフォーマンスかもしれません (しかし、私は測定していません)。
グローバル コンテキスト (この実装ではトレース) を無効にする場合は、構成ファイルを編集して、tracingEnabled="false" を設定するだけです。
これは、組み込みの Enterprise Library 機能を使用して目的を達成するためのかなり簡単な方法のようです。
考慮すべき他のアプローチは、非常に洗練された何らかのインターセプト (カスタム LogCallHandler) を潜在的に使用することです (ただし、それは既存の設計に依存する可能性があります)。
カスタム実装を使用してコンテキストを収集および管理する場合は、スレッド コンテキストごとにTrace.CorrelationManagerを使用することを検討できます。IExtraInformationProvider
を作成して拡張プロパティ ディクショナリ を作成することも検討できます(例については、 Enterprise Library 3.1 Logging Formatter Template - Include URL Requestを参照してください)。