ThreadContext Eigenschaft schreibt nicht auf AdoNetAppender
-
03-07-2019 - |
Frage
Ich verwende log4net 1.2.10.0. Ich habe ILog und LogManager erweitert, um eine neue Ebene zu schließen, ‚Audit‘. Ich mag eine AdoNetAppender
verwenden, um den %message
auf eine Datenbank zu protokollieren. Ich brauche andere Informationen protokolliert und ich versuchte log4net.ThreadContext.Properties
verwenden.
Ich bekomme keine Ausgabe, wenn ich versuche, eine Kontexteigenschaft als Wert für einen SQL-Parameter zu verwenden.
<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>
Die Ausführung von Code ist (unter der Annahme log4net init'ed und einen Logger wurde, 'log', erstellt wurde).
log4net.ThreadContext.Properties["custom_prop"] = "value";
log.Audit("a message");
Die appender arbeitet mit dem AUDIT-Filter, wenn ich hart Code ein Wert stattdessen einen SQL-Parameter verwendet wird.
...
<commandText value="INSERT INTO table1 VALUES('value', :message)" />
...
Die appender arbeiten mit der Kontexteigenschaft, wenn ich auf einem integrierten Level-Filter, wie INFO.
...
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="INFO" />
</filter>
...
Ein FileAppender
arbeitet mit der AUDIT-Filter und Kontexteigenschaft!
<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>
Was zu
AUDIT [value] - a message
eine globale Kontexteigenschaft Mit arbeitet mit den AdoNetAppender
und AUDIT-Filter. Aber, ich brauche Kontextauflösung fädeln.
log4net.GlobalContext.Properties["custom_prop"] = "value";
log.Audit("a message");
Was zu
table1
custom_prop message
=========== =======
value a message
Also, ich weiß nicht, ob es ein Problem mit den AdoNetAppender
oder meinen erweiterten Klassen oder meiner Konfiguration ist.
Lösung
Das Problem wurde von den frühen Abbruch des Vordergrundthread verursacht. Ich denke, log4net eine Asynchron-Operation ausgeführt wurde. Putting ein Schlaf am Ende der Test-App das Problem behoben
...
log4net.ThreadContext.Properties["custom_prop"] = "value";
log.Audit("a message");
...
Thread.Sleep(1000);
oder, wenn sie in einem separaten Thread, auf sie Füge
Thread t = new Thread(new ThreadStart(delegate
{
log4net.ThreadContext.Properties["custom_prop"] = "value";
log.Audit("a message");
}));
t.Start();
...
t.Join();
Im Normalbetrieb log4net sollte genügend Zeit zwischen dem letzten AUDIT Ruf hat und Ende der Ausführung.