Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Lesedauer 6 Min.

Loggingdaten-Einlaufstelle mit Komfortfunktionen

Die in Android implementierte Logging-Funktion ist ein leistungsfähiges Beispiel für moderne Logging-Systeme. Mit Serilog steht ein ähnliches System für .NET-Applikationen zur Verfügung, das allerdings einige weit über das große Vorbild hinausgehende Funktionen offeriert.
© EMGenie

Der Gedanke, Loggingdaten über einen zentralen Dienst zu sammeln und zur Weiterverarbeitung zur Verfügung zu stellen, war außerhalb von Echtzeitbetriebssystemen nur im akademischen Bereich verbreitet. Nach Android änderte sich dies, da das zentralisierte Verwalten erstens Aufwand einspart und zweitens verschiedene fortgeschrittene Logging-Methoden ermöglicht.

Serilog erlaubt Entwicklern erstens das Speichern „formalisierter“ Daten, in denen später gesucht werden kann. Zweitens ermöglicht die offene Architektur das Einbinden verschiedenster Erweiterungsmodule, die die Logging-Daten persistieren oder auf andere Weise weiterreichen können.

Von der Architektur des Logging-Systems

Serilog wurde von Anfang an als „offenes System“ aufgebaut: Alle eingezeichneten Elemente im vom Autor erstellten Flussdiagramm in Bild 1 lassen sich entweder erweitern oder zur Gänze neu implementieren.

Die Logging-Pipeline von Serilog ist durchaus kompliziert (Bild 1)
Die Logging-Pipeline von Serilog ist durchaus kompliziert (Bild 1) © Autor

Der Entwicklercode selbst interagiert mit dem Logger. Dabei handelt es sich um eine Klasse, die Logging-Nachrichten entgegennimmt und diese – unter anderem – durch zusätzliche Metainformationen erweitert, die von als Enricher bezeichneten Kompositoren angeliefert werden.

Im nächsten Schritt wandern diese vom Logger zusammengestellten Informationen in einen Filter und/oder in Unterlogger. Am Ende der Signalkette stehen dann als Sink bezeichnete Elemente, die sich um die Persistierung beziehungsweise Sichtbarmachung der angefallenen Protokollinformationen bemühen.

Hervorzuheben ist die Rolle der Filter-Instanzen. Die idiomatische Nutzung von Serilog setzt das Anliefern der Logging-Informationen in Form von Parametern voraus – von Haus aus werden dabei die in Bild 2 aufgelisteten Typen unterstützt.

SeriLog behandelt Parameter in Logging-Strings gesondert (Bild 2)
SeriLog behandelt Parameter in Logging-Strings gesondert (Bild 2) © GitHub

Bei idiomatisch korrekter Nutzung können die Filter dann mit diesen Informationen makeln. Durch Nutzung eines Unterloggers wäre es beispielsweise möglich, nur jene Informationen in einen Cloudspeicher zu schreiben, die einen gewissen „Wichtigkeitsgrad“ aufweisen.

Inbetriebnahme des Frameworks

Serilog funktioniert im Prinzip mit jeder Darbietungsform einer .NET-Applikation. Übungshalber wollen wir in den folgenden Schritten auf die Vorlage Konsolen-App setzen und den Projektnamen NMGSerilog vergeben. Als Framework-Version reicht die von Visual Studio 2022 als Default ausgegebene 8.0 aus.

Die Magie von NuGet erleichtert dann die Einbindung der benötigten Pakete. Da das Basispaket von Serilog nur die Interfaces, aber keine praktischen Implementierungen mitbringt, benötigen wir fürs Erste mindestens einen Konsolen-Sink. Das Markieren des Pakets Serilog.Sinks.Console als zu Deployen sorgt dafür, dass NuGet automatisch auch das Basispaket Serilog in die Solution einbindet.

Im nächsten Schritt wollen wir Serilog zunächst wie ein Analogon zu LogCat und Co. verwenden. Hierzu ist folgender Code erforderlich:

 

Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .CreateLogger();

Log.Information("Die Wefze Anna faucht mit 40 Dezibel");
Log.Warning("Lärm stört die innere Ruhe des Menschen und macht krank!");

 

Die erste Aktion ist dabei – man denke an das Flussdiagramm weiter oben – die Erzeugung eines Logger-Objekts. Die Methode WriteTo.Console() ist dabei dafür verantwortlich, die Konsolen-Ausgabe-Senke als Teil der Pipeline festzulegen. Im nächsten Schritt nutzen wir dann sowohl die Methoden Information als auch Warning, um gesundheitsfördernde Informationen in das Logging-System zu schreiben. Bild 3 zeigt das Ergebnis.

Die Logdaten erscheinen in der Kommandozeile (Bild 3)

Die Logdaten erscheinen in der Kommandozeile (Bild 3)

© Autor

Interessant ist hier unter anderem der in eckigen Klammern gesetzte Teil des Strings. Dabei handelt es sich um Informationen im Hinblick auf die Wichtigkeit – der mit Information abgesetzte Informations-Aufruf und die Warnung werden mit unterschiedlichen Präfixen dargestellt, um direkt eine visuelle Unterscheidung zu erleichtern.

Aus Serilog-idiomatischer Sicht ist der String ungünstig, weil er zwei filtrierbare Informationen enthält: einerseits den Namen der Quelle der Musik und andererseits die Intensität der erzeugten Lautstärke.

Durch Separierung dieser Felder könnten wir, wie weiter oben erwähnt, gezieltes Filtrieren ermöglichen. Hierzu ist es notwendig, den Aufruf der Information-Methode nach folgendem Schema anzupassen und die Templates als separate Variablen anzuliefern:

 

Log.Information("Die Wefze {Name} faucht mit {Lautheit} Dezibel", "Annette", 90);

 

Ob der Information-Aufruf korrekt parametriert ist, lässt sich dadurch verifizieren, dass die Parameter wie in der Bild 4 gezeigt farblich hervorgehoben angezeigt werden.

Parameter erscheinen farblich hervorgehoben (Bild 4)

Parameter erscheinen farblich hervorgehoben (Bild 4)

© Autor

Kulturelle Bereicherung für Logs

Beim Erzeugen von Protokollen gibt es Datenarten, die man immer wieder zu protokollieren sucht – ein Beispiel könnte der Name der Maschine sein, die für die Aufzeichnung des Ärgernisses verantwortlich war. Zur Lösung dieses Problems gibt es, wie weiter oben im Diagramm gezeigt, als Enricher bezeichnete Komponenten, die – nomen est omen – ihren Beitrag zum durch den Logger marschierenden Datenstrom leisten.

Aufgrund der weiten Verbreitung von Serilog bietet es sich an dieser Stelle an, in NuGet nach dem String Serilog.Enrich zu suchen. Bild 5 zeigt einen Auszug der zur Verfügung stehenden Fähigkeiten.

Serilog stellt Dutzende von Enrichern zur Verfügung (Bild 5)

Serilog stellt Dutzende von Enrichern zur Verfügung (Bild 5)

© Autor

In den folgenden Schritten wollen wir übungshalber den Maschinenamen persistieren, weshalb das Paket Serilog.Enrichers.Environment zur Solution hinzuzufügen ist. Angemerkt sei, dass dieses Paket nicht nur Maschinenname und Co. persistieren kann – es ist auch zum Aufzeichnen der in Umgebungsvariablen befindlichen Werte befähigt.

Für einen ersten, stupiden Versuch bietet sich dann nach folgendem Schema aufgebauter Code an:

 

Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
        .Enrich.WithMachineName()
    .CreateLogger();

 

Seine Ausführung führt allerdings nur zum weiter oben gezeigten Ergebnis. In der Serilog-Basisimplementierung steht mit der Methode WithProperty ein Basis-Enricher zur Verfügung, der „Konstanten“ in den Logger-Strom schreiben sollte. Auch hier bietet sich ein nach folgendem Schema aufgebauter naiver Versuch an, der allerdings ebenfalls fehlschlägt:

 

 

Log.Logger = new LoggerConfiguration()
            .Enrich.WithMachineName()
            .Enrich.WithEnvironmentUserName()
            .Enrich.WithProperty("Version", "1.0.0")
    .WriteTo.Console()
    .CreateLogger();

 

Der springende Punkt ist, dass die verschiedenen Logger im Allgemeinen ein Template erwarten, dass das Format die in der jeweiligen Sink abzulegenden Messages festlegt. Die Ausgabe des Maschinennamens funktioniert beispielsweise erst dann, wenn wir im Feld outputTemplate nach folgendem Schema das gewünschte Format festlegen:

 

  

.WriteTo.Console(outputTemplate: "[{Level}] ({MachineName}) {Message}{NewLine}")    
.CreateLogger();

 

Ergebnis der Programmausführung ist dann das in Bild 6 gezeigte Verhalten.

Der Maschinenname erscheint in der Ausgabe (Bild 6)
Der Maschinenname erscheint in der Ausgabe (Bild 6) © Autor

Filtern der Ereignisse

Das weiter oben erfolgende Hervorheben von Namen und Lautheit ist kein Selbstzweck. Als letztes „Husarenstück“ wollen wir unseren Logger an dieser Stelle um die Fähigkeit erweitern, nur besonders lästige Ausgaben zu persistieren.

Hierzu ist neben dem Hinzufügen weiterer Lästlinge die Nutzung eines Filters erforderlich:

 

 

Log.Logger = new LoggerConfiguration()
            .Enrich.WithMachineName()
            .Enrich.WithEnvironmentUserName()
            .Enrich.WithProperty("Version", "1.0.0")
            .Filter.ByExcluding(Matching.WithProperty<int>("Lautheit", p => p < 50))

    .WriteTo.Console(outputTemplate: "[{Level}] ({MachineName}) {Message}{NewLine}")
    .CreateLogger();

Log.Information("Die Wefze {Name} faucht mit {Lautheit} Dezibel", "Annette", 90);
Log.Information("Die Wefze {Name} faucht mit {Lautheit} Dezibel", "Batta", 20);
Log.Information("Die Wefze {Name} faucht mit {Lautheit} Dezibel", "Claire", 25);
Log.Warning("Lärm stört die innere Ruhe des Menschen und macht krank!");

 

Daraus resultiert, dass SeriLog fortan nur eine der drei Quellen von Lärm persistiert. Zu beachten ist, dass ByExcluding hier nur die Lautheit ausschließt – Meldungen ohne Lautheit kommen also prinzipiell in die Ausgabe.

Nur die Lästigsten kommen in das Log ... (Bild 7)

Nur die Lästigsten kommen in das Log ... (Bild 7)

© Autor

Fazit

Wer die eigenen Logging-Informationen über das Serilog-Framework zur Aberntung bereitstellt, erspart sich in der Praxis Unmengen von Code. Die aus Platzgründen nicht besprochenen diversen Cloud-Logger ermöglichen beispielsweise das direkte Hochladen der Logging-Ergebnisse in alle Arten von Clouddienst – ein immens wertvolles Feature, dessen Nützlichkeit auf keinen Fall unterschätzt werden sollte.

Neueste Beiträge

1 plus 1 macht 2 - Mendix Artificial Intelligence Assistant
Low Code verspricht die Vereinfachung der Softwareproduktion, künstliche Intelligenz die Steigerung der Developer Productivity. Was passiert, wenn man beide kombiniert?
16 Minuten
22. Okt 2025
Beyond the Code: KI verändert die Entwicklerrolle – wer sich jetzt anpasst, bleibt vorne dabei
Generative KI-Tools steigern Effizienz und beschleunigen Workflows – doch sie stellen auch neue Anforderungen an Entwicklerteams. Gefragt sind strategisches Denken, Kreativität und die Bereitschaft, sich laufend weiterzuentwickeln.
5 Minuten
15. Okt 2025
DDC hakt nach: Warum lohnt sich der Umstieg nach C#
Vom Sprachen-Frust zur C#-Lust: Alle Werkzeuge, die das Herz begehrt
5 Minuten
20. Okt 2025

Das könnte Dich auch interessieren

Erstellung von ZUGFeRD 2.3 mit .NET C# - Rechnungserstellung
ZUGFeRD 2.3 konforme Rechnungen mit TX Text Control .NET Server für ASP.NET erstellen.
3 Minuten
9. Jan 2025
Alternativen zu Swagger in ASP.NET 9 - Interface
In ASP.NET 9 wurde Swagger aus den Templates entfernt. Welche Alternativen es gibt, um interaktiv APIs zu erstellen und zu testen.
3 Minuten
24. Sep 2024
Wann wird die Unterstützung für das .NET Framework eingestellt? - .NET
Ein Blick auf die Lebenszyklus-Richtlinien von Microsoft zeigt, dass das .NET Framework weiterhin unterstützt wird, während sich die Community auf die neuesten Versionen konzentriert.
2 Minuten
28. Jan 2025
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige