ThreadContextプロパティはAdoNetAppenderに書き込みません
-
03-07-2019 - |
質問
log4net 1.2.10.0を使用しています。 ILogとLogManagerを拡張して、新しいレベル「AUDIT」を追加しました。 AdoNetAppender
を使用して、%message
をデータベースに記録します。他の情報を記録する必要があるので、 log4net.ThreadContext.Properties
を使用してみました。
コンテキストプロパティをSQLパラメーターの値として使用しようとすると、出力が得られません。
<log4net>
<level>
<name value="AUDIT" />
<value value="35000" />
</level>
<appender name="AdoNetAppender.Audit" type="log4net.Appender.AdoNetAppender">
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="AUDIT" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<connectionType value="System.Data.OracleClient.OracleConnection, System.Data.OracleClient, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="data source=db1;User ID=user;Password=pass" />
<commandText value="INSERT INTO table1 VALUES(:custom_prop, :message)" />
<parameter>
<parameterName value=":custom_prop" />
<dbType value="String" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{custom_prop}" />
</layout>
</parameter>
<parameter>
<parameterName value=":message" />
<dbType value="String" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="AdoNetAppender.Audit" />
</root>
</log4net>
実行中のコードは次のとおりです(log4netが初期化され、ロガー「log」が作成されていると仮定)。
log4net.ThreadContext.Properties["custom_prop"] = "value";
log.Audit("a message");
SQLパラメーターを使用する代わりに値をハードコーディングした場合、アペンダーはAUDITフィルターで動作します。
...
<commandText value="INSERT INTO table1 VALUES('value', :message)" />
...
INFOのような組み込みレベルでフィルタリングすると、アペンダーはコンテキストプロパティを処理します。
...
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="INFO" />
</filter>
...
A FileAppender
は、AUDITフィルターとコンテキストプロパティで機能します!
<appender name="FileAppender" type="log4net.Appender.FileAppender" >
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="AUDIT" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<file value="test.log" />
<layout type="log4net.Layout.PatternLayout" >
<conversionPattern value="%-5level [%property{custom_prop}] - %message%newline" />
</layout>
</appender>
結果
AUDIT [value] - a message
グローバルコンテキストプロパティの使用は、 AdoNetAppender
およびAUDITフィルターで機能します。しかし、スレッドコンテキストの解決が必要です。
log4net.GlobalContext.Properties["custom_prop"] = "value";
log.Audit("a message");
結果
table1
custom_prop message
=========== =======
value a message
だから、それが AdoNetAppender
の問題なのか、拡張クラスの問題なのか、構成に問題なのかわかりません。
解決
この問題は、フォアグラウンドスレッドの早期中断によって発生しました。 log4netは非同期操作を実行していたと思います。テストアプリの最後でスリープ状態にすると、問題が修正されました
...
log4net.ThreadContext.Properties["custom_prop"] = "value";
log.Audit("a message");
...
Thread.Sleep(1000);
または、別のスレッドの場合、それに参加する
Thread t = new Thread(new ThreadStart(delegate
{
log4net.ThreadContext.Properties["custom_prop"] = "value";
log.Audit("a message");
}));
t.Start();
...
t.Join();
通常の操作では、log4netには最新のAUDIT呼び出しから実行終了までの間に十分な時間が必要です。