Ich versuche herauszufinden, was das richtige Muster und die richtige Verwendung von log4net mit einem Abhängigkeitsinjektionsframework ist.
Log4Net verwendet die ILog-Schnittstelle, erfordert jedoch einen Anruf
LogManager.GetLogger(Reflection.MethodBase.GetCurrentMethod().DeclaringType)
in jeder Klasse oder Methode, in der ich Informationen protokollieren muss. Dies scheint gegen die IoC-Prinzipien zu verstoßen und verbindet mich mit der Verwendung von Log4Net.
Sollte ich irgendwo eine andere Abstraktionsebene einfügen?
Außerdem muss ich benutzerdefinierte Eigenschaften wie den aktuellen Benutzernamen wie folgt protokollieren:
log4net.ThreadContext.Properties["userName"] = ApplicationCache.CurrentUserName;
Wie kann ich dies kapseln, damit ich nicht jedes Mal daran denken muss, es zu tun, und trotzdem die aktuelle Protokollierungsmethode beibehalten muss? soll ich so etwas machen oder verpasse ich die Marke total?
public static class Logger
{
public static void LogException(Type declaringType, string message, Exception ex)
{
log4net.ThreadContext.Properties["userName"] = ApplicationCache.CurrentUserName;
ILog log = LogManager.GetLogger(declaringType);
log.Error(message, ex);
}
}
Antworten:
Ich glaube, Sie sehen hier nicht den Wald vor lauter Bäumen. ILog und LogManager sind eine leichte Fassade, die fast 1: 1 der Apache-Commons-Protokollierung entspricht und Ihren Code nicht mit dem Rest von log4net koppelt.
<rant>
Ich habe auch festgestellt, dass fast immer, wenn jemand einen MyCompanyLogger-Wrapper um log4net erstellt, er den Punkt stark verfehlt und entweder wichtige und nützliche Funktionen des Frameworks verliert, nützliche Informationen wegwirft oder die möglichen Leistungssteigerungen verliert, die selbst über die vereinfachte ILog-Oberfläche möglich sind. oder alle oben genannten. Mit anderen Worten, das Umschließen von log4net, um eine Kopplung mit log4net zu vermeiden, ist ein Anti-Pattern .
</rant>
Wenn Sie das Bedürfnis haben, es zu injizieren, machen Sie Ihre Logger-Instanz über eine Eigenschaft zugänglich, um die Injektion zu aktivieren, aber erstellen Sie eine Standardinstanz auf die altmodische Weise.
Um den Kontextstatus in jede Protokollnachricht aufzunehmen, müssen Sie eine globale Eigenschaft hinzufügen, deren
ToString()
Auflösung dem entspricht, wonach Sie suchen. Als Beispiel für die aktuelle Heap-Größe:So schließen Sie es beim Start an:
quelle
Ich habe meine eigene Schnittstelle erstellt und eine Klasse diese Schnittstelle implementieren lassen, die Log4Net verwendet, und diese Klasse injiziert. Auf diese Weise sind Sie nicht an Log4Net gebunden. Sie können einfach eine weitere Klasse für einen neuen Logger erstellen und diese Klasse einfügen.
quelle
Wenn Sie wirklich Bedenken haben, mehrere Protokollierer zu haben, können Sie jederzeit einen globalen Protokollierer deklarieren und diesen für alle Ihre Protokollierungsanforderungen aufrufen. Der Nachteil dabei ist, dass Sie die integrierte Fähigkeit verlieren, die Klasse zu identifizieren, von der das Protokoll ausgegeben wurde. Sie können jedoch auch Ihre eigene benutzerdefinierte Nachricht in das Protokoll einfügen, um die Klasse zu identifizieren.
Dies hängt davon ab, wie robust die Protokollierung sein soll. Sie können den Logger auch einfach in die Hauptklasse stellen und alle nicht behandelten Ausnahmen zur Protokollierung in die Luft sprudeln lassen.
quelle
Eine andere Möglichkeit besteht darin, die Registrierungssequenz für den log4net ILog-Schnittstellencontainer wie folgt zu verkabeln: (unter Verwendung von Castle in einem ASP.NET-Kontext unten als Beispiel)
und einfach ILog konstruieren, wann immer Sie es brauchen.
quelle
Component.For<ILog>().UsingFactoryMethod((kernel, model, cc) => LogManager.GetLogger(cc.Handler.ComponentModel.Implementation))