log4net LogicalThreadContext funktioniert nicht

8

Ich habe entweder einen Fehler in log4net oder ein Missverständnis meinerseits.

Ich versuche, LogicalThreadContext zu verwenden, um einige Daten einem Aufrufkontext zuzuordnen und sie an alle Protokollanweisungen weiterzugeben, die von einem beliebigen Thread in diesem Kontext erstellt wurden. Das ist der angebliche Vorteil von LogicalThreadContext über ThreadContext .

Ich war nicht in der Lage, die Ausbreitung zur Arbeit zu bringen, also stellte ich einen einfachen Komponententest zusammen, um zu sehen, ob es funktionieren würde, und es nicht tut. Hier ist es:

%Vor%

Meine log4net-Konfiguration sieht so aus:

%Vor%

Und meine Ausgabe sieht so aus:

%Vor%

Wie Sie sehen, sind die Daten, die ich auf den LTC-Stack drücke, nur in den Logging-Anweisungen vorhanden, die auf demselben Thread gemacht wurden. Der Protokollanweisung, die von dem Hintergrundthread erstellt wird, fehlen die Kontextdaten. Debugging durch den Test konnte ich sehen, dass tatsächlich LogicalThreadContext.Stacks.Count ist Null auf dem Hintergrund-Thread.

Als ich in die log4net-Quelle eintauchte, fand ich sie unter Verwendung der CallContext Klasse. Diese Klasse tut, was sie sagt - sie ermöglicht es, den Kontext für den aktuellen "Anruf" zu speichern und abzurufen. Wie es das auf einem niedrigen Niveau macht, habe ich keine Ahnung.

CallContext verfügt über zwei Arten von Methoden, mit denen Kontextinformationen gespeichert und abgerufen werden können: GetData / SetData und LogicalGetData / LogicalSetData . Die Dokumentation behandelt sehr detailliert die Unterschiede zwischen diesen beiden Methoden, aber die Beispiele verwenden GetData / SetData . Und das gilt auch für log4net LogicalThreadContext .

Ein schneller Test zeigte, dass GetData / SetData das gleiche Problem aufweist - Daten werden nicht über Threads verteilt. Ich dachte, ich würde stattdessen LogicalGetData / LogicalSetData geben:

%Vor%

Dieser Test ist erfolgreich - Kontextinformationen werden erfolgreich über Threads verteilt, wenn LogicalGetData / LogicalSetData verwendet wird.

Also meine Frage ist: hat log4net das falsch verstanden? Oder fehlt mir etwas?

UPDATE: Ich habe auch versucht, einen benutzerdefinierten Build von log4net zu erstellen, dessen LogicalThreadContextProperties -Klasse gemäß meinen obigen Ergebnissen geändert wurde. Ich habe meinen ersten Test erneut durchgeführt und es hat funktioniert. Das erscheint mir einfach als ein zu offensichtliches Problem für ein Produkt, das von so vielen Leuten benutzt wird, also muss ich annehmen, dass ich etwas vermisse.

    
Kent Boogaart 04.08.2011, 09:29
quelle

1 Antwort

5

Hier ist eine Frage, die ich etwas zurück gefragt habe, was der Unterschied zwischen ThreadContext und LogicalThreadContext ist:

Was ist der Unterschied zwischen log4net.ThreadContext und log4net.LogicalThreadContext?

Es gibt einen Link zu einem Beitrag von Nicko Cadell, einem der log4net-Autoren, über die Funktionsweise von LogicalThreadContext. Er spricht über im CallContext gespeicherte Elemente, die ILogicalThreadAffinative unterstützen, die automatisch an untergeordnete Threads weitergegeben werden, aber das log4net nicht ILogicalThreadAffinative verwendet. Er erwähnt nichts über die Verwendung von CallContext.LogicalSetData, die, wie Sie gefunden haben, CallContext-Daten automatisch an untergeordnete Threads weitergegeben werden, ohne ILogicalThreadAffinative implementieren zu müssen.

Zusammenfassend glaube ich nicht, dass Sie etwas verpassen. Ich denke, dass log4net es falsch verstanden hat.

Ich stelle fest, dass Sie keinen Code angefordert haben, aber hier ist eine Arbeit, die ich vor ein paar Monaten gemacht habe, als ich in log4net, CallContext, PatternLayoutConverter, etc.

gesucht habe

Zuerst ein "logisches Thread-Kontext" -Objekt, das ich vor einigen Monaten zusammengeschmuggelt habe. Ich habe es geschrieben, um die Logging-Kontext-Abstraktionen der Castle-Logging-Anlage nachzuahmen.

%Vor%

Hier ist ein log4net PatternLayoutConverter (der zu einem anderen Zeitpunkt geschrieben wurde, hauptsächlich als Experiment, um mehr über log4net und den CallContext zu erfahren). Es erwartet, dass die Option -Eigenschaft einen bestimmten benannten Wert aus dem logischen Aufrufkontext angibt. Es wäre nicht schwer, einen ähnlichen PatternLayoutConverter zu schreiben, der das Dictionary aus dem logischen Kontext basierend auf dem obigen Namen abruft, und dann den Parameter Option zum Indizieren in das Dictionary verwendet hat.

%Vor%

Um das Wörterbuchschema wie im ersten Codebeispiel zu verwenden, sieht der PatternLayoutConverter möglicherweise so aus (nicht kompiliert und nicht getestet):

%Vor%

Viel Glück!

    
wageoghe 04.08.2011, 14:11
quelle

Tags und Links