
Teilen Sie:
Ehemaliger .NET Developer Advocate @Vonage, polyglotter Software-Ingenieur, AI/ML
Adaptive Bibliotheksprotokollierung mit Microsoft.Extensions.Logging
Wie ich lernte, mich nicht mehr zu sorgen und das Loggen zu lieben
In meiner beruflichen Laufbahn habe ich an einigen verschiedenen mittleren bis großen .NET-Projekten gearbeitet. Bei jedem Projekt sah ich eine andere Art von Logger, und in der Regel alle von ihnen verwendet mehr als ein Logger!
Normalerweise geht die Geschichte in etwa so: "In den ersten Tagen konnten wir uns nicht entscheiden, welchen Logger wir verwenden wollten, also haben wir unseren eigenen gebaut. Dann stellten wir fest, dass die Art und Weise, wie wir die Protokollierung implementiert hatten, nicht die effizienteste war, also wechselten wir zu X Logger, als die App skalierte. Wir wollten nicht zurückgehen und den alten Logger entfernen, weil wir dann jede Datei in unserer Lösung anfassen müssten, also haben wir ihn nur an den Stellen entfernt, an denen der alte Logger Probleme verursachte, und von nun an werden wir nur noch X Logger für alles verwenden."
Wie ich schon sagte, ist dies ein überraschend häufiges Problem - und eines, das wir umgehen können, indem wir den Logger von der Protokollierung abstrahieren.
Einloggen in die Nexmo .NET Bibliothek
Kürzlich habe ich einen Blick auf Nexmo's .NET Server SDK und habe einige Dinge aufgeräumt. Dabei ist mir aufgefallen, dass unser Logging-Framework LibLog veraltet ist.
Dieses Tool war großartig, da es den Logger von der Protokollierung abstrahierte. Es erlaubte jedem, der mit unserem SDK entwickelt, seinen eigenen Logger mitzubringen. Solange Ihr Logger unterstützt wurde, konnten Sie den Logger des SDK huckepack mit dem Logger Ihrer Wahl verwenden, ohne dass Sie eingreifen mussten (was realistisch betrachtet ein Vor- oder Nachteil sein kann, je nachdem, wie Sie es betrachten).
Da LibLog veraltet ist, war ich gezwungen, mich nach einem anderen Protokollierungstool umzusehen, das unsere Anforderungen erfüllt. Glücklicherweise brauchte ich nicht weit zu suchen.
Vorwärtskommen mit Microsoft.Extensions.Logging
Die (relativ) neue Microsoft.Extensions.Logging Paket hat mit seiner Funktionalität den Nagel auf den Kopf getroffen. Mit dem Erweiterungspaket können Sie einfach das NuGet-Paket zusammen mit dem von Ihnen gewählten Logging-Framework installieren, eine Factory einrichten und den Logger erstellen.
Das passt zu unserem Anwendungsfall, da wir nicht unbedingt wollen, dass unsere Protokolle automatisch in die Protokolle unserer Benutzer einfließen - und gleichzeitig wollen wir unseren Benutzern nicht vorschreiben, wo, wie und in welchem Rahmen die Protokolle erfasst werden sollen.
Mit unserer nächsten Hauptversion, 5.0.0, werden Sie in der Lage sein, jede beliebige Ebene oder Kategorie innerhalb des SDK dynamisch zu aktivieren, indem Sie einfach die Logger Factory im SDK austauschen.
Erstellung von Loggern mit Microsoft.Extensions.Logging
Erstellen Sie den Log-Provider
Zwei Komponenten liegen Microsoft.Extensions.Logging zugrunde: ILoggerFactory und ILogger. Die Fabrik erzeugt die Logger und der Logger führt die Protokollierung durch.
Diese beiden Komponenten werden in der Klasse LogProvider verwendet, damit wir einen vollständig dynamischen, erweiterbaren Logger für die Bibliothek erstellen können, der es dem Entwickler ermöglicht, seinen eigenen Logger mitzubringen.
public static class LogProvider
{
private static IDictionary<string, ILogger> _loggers = new Dictionary<string, ILogger>();
private static ILoggerFactory _loggerFactory = new LoggerFactory();
public static void SetLogFactory(ILoggerFactory factory)
{
_loggerFactory?.Dispose();
_loggerFactory = factory;
_loggers.Clear();
}
public static ILogger GetLogger(string category)
{
if (!_loggers.ContainsKey(category))
{
_loggers[category] = _loggerFactory?.CreateLogger(category)?? NullLogger.Instance;
}
return _loggers[category];
}
}In unserem Modell erstellen wir eine statische Klasse namens LogProvider mit zwei Feldern: _loggers, ein Wörterbuch, das den Logger für jede Kategorie enthält, und _loggerFactory, die die Logger erstellt.
Außerdem gibt es zwei Methoden: SetLogFactory, die die alte LogFactory entsorgt und die Log-Factory auf die neue übergebene Log-Factory setzt, und GetLogger, die die _loggers überprüft, um zu sehen, ob der Logger dieser Kategorie bereits erstellt wurde, und einen erstellt, wenn dies nicht der Fall ist.
Verwendung des Log-Providers
Nun müssen wir zu Beginn jeder Methode, die wir protokollieren wollen, einfach GetLogger mit der entsprechenden Kategorie aufrufen:
var logger = Api.Logger.LogProvider.GetLogger(LOGGER_CATEGORY); Protokollierung
Von hier aus müssen wir den Logger einfach wie jeden anderen Logger verwenden, den wir bereits kennen. Zum Beispiel:
logger.LogInformation("Available authentication: {0}", string.Join(",", authCapabilities));Damit werden die verfügbaren Authentifizierungsmöglichkeiten in dem Format, das Sie Ihrem Logger zur Verfügung gestellt haben, als Informationen aufgezeichnet.
Konfigurieren von adaptiven Loggern
Nachdem wir uns nun mit der Erstellung und Verwendung der Logger beschäftigt haben, wollen wir uns nun mit der Konfiguration der Logger befassen.
Wählen Sie Ihren Log-Anbieter
Das Schöne an Microsoft.Extensions.Logging ist, dass es sich an den von Ihnen verwendeten Protokollanbieter anpasst. Solange der Log-Provider die Schnittstelle implementiert ILogProvider Schnittstelle implementiert, kann er sein, was er will. Und aus der Sicht des Entwicklers, der versucht, es zu nutzen, ist es sogar noch einfacher. Die meisten der großen Log-Anbieter, die Sie wahrscheinlich verwenden werden (z. B. Log4Net, Serilog, NLog usw.), haben Erweiterungspakete, die das Hinzufügen des gewünschten Loggers vereinfachen.
Protokollierung auf der Konsole mit Serilog
Um zu demonstrieren, wie wir diese Logger erstellen können, nehmen wir das Beispiel der Protokollierung der Konsole mit Serilog. Hierfür benötigen Sie die folgenden NuGet-Pakete:
Microsoft.Erweiterungen.Protokollierung
Serilog.Erweiterungen.Protokollierung
Serilog.Sinks.Console
Sie gehen dann wie folgt vor:
Erstellen Sie eine neue LoggerFactory, die wir für die Erstellung von
Erstellen Sie eine neue LoggerConfiguration, die die Serilog-Konfiguration festlegt
Aufruf der Funktion AddSerilog in der Fabrik
Einen Logger der Kategorie 'test' erstellen
Abmelden
Zusammengekettet sieht das wie folgt aus:
var log = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console(outputTemplate: "{Timestamp:HH:mm} [{Level}] ({Name:l}) {Message}\n")
.CreateLogger();
var factory = new LoggerFactory();
factory.AddSerilog(log);
ILogger logger = factory.CreateLogger("test");
logger.LogInformation("Hello world");Sehr sauber und einfach.
Um mit dem Nexmo SDK zu interagieren, müssen Sie nicht erst einen Logger erstellen, nachdem Sie die Factory konfiguriert haben. Setzen Sie einfach die LogFactory im Log Provider auf die Log Factory, die Sie erstellt und zu der Sie Serilog hinzugefügt haben, und Sie werden sehen, dass das Logging vom SDK kommt.
var log = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console(outputTemplate: "{Timestamp:HH:mm} [{Level}] ({Name:l}) {Message}\n")
.CreateLogger();
var factory = new LoggerFactory();
factory.AddSerilog(log);
LogProvider.SetLogFactory(factory);Et Voila - unser eigener, hochgradig konfigurierbarer Library Logger.
Vorteile
Microsoft.Extensions.Logging ermöglicht es uns, das Albtraumszenario zu vermeiden, dass wir ein Projekt mit einem Logger beginnen und dann, aus welchen Gründen auch immer, zu einem anderen wechseln müssen.
Wenn Sie Ihren eigenen Logger verwenden möchten, steht Ihnen das auch bei Verwendung der Logging Extensions frei. Alles, was Sie tun müssen, ist die ILogProvider-Schnittstelle mit dem Logger zu implementieren, den Sie verwenden möchten, und ihn zur Factory hinzuzufügen.