Java-Protokollierungshandbuch: Die Grundlagen
Arfan Sharif – 13. Februar 2023
Die Protokollierung hilft Ihnen zu verstehen, wie eine Anwendung funktioniert oder was schief gelaufen ist, wenn etwas fehlschlägt. Diese Informationen können für Debugging- und Prüfzwecke von entscheidender Bedeutung sein. Protokolle zeichnen jedes Ereignis während der Ausführung eines Programms auf und stellen diese Aufzeichnungen für eine spätere Analyse zur Verfügung.
Eine effektive Protokollierung erfolgt jedoch nicht automatisch. Anwendungsentwickler müssen sicherstellen, dass eine Anwendung wichtige Details systematisch in einem einfach zu verarbeitenden Format protokolliert.
Der rudimentärste Ansatz zur Protokollierung ist die einfache Verwendung von print-Anweisungen zur Anzeige gewünschter Anwendungsdetails. Natürlich ist dies aus folgenden Gründen kein idealer Ansatz:
Aus all diesen Gründen enthalten viele Programmiersprachen wie Java dedizierte Protokollierungs-APIs und Frameworks. In dieser Übersicht – dem ersten Teil der Serie – stellen wir die grundlegenden Protokollierungskonzepte für Java-Anwendungen vor. Wir werden uns die Protokollierungsoptionen ansehen und dann mehrere verfügbare Protokollierungs-Frameworks und ihre unterstützten Konfigurationen betrachten.
Entdecken Sie die komplette Java Logging Guide-Reihe:
Wie alles andere in seiner Architektur verfolgt Java einen erweiterbaren und anpassbaren Ansatz für die Protokollierung. Das java.util.logging-Framework ist die Standardoption für alle protokollierungsbezogenen Funktionen. Dieses Framework bietet alle grundlegenden Funktionen, die für die Protokollierung erforderlich sind, und ermöglicht gleichzeitig die Erweiterung dieser Funktionen durch Frameworks von Drittanbietern.
Dieses Protokollierungsframework umfasst drei Hauptmodule:
Ein weiteres erwähnenswertes Konzept ist der Filter. Mithilfe von Filtern kann der Entwickler einen LogRecord abfangen und entscheiden, welcher Handler verwendet werden soll. Obwohl Filter für die einfache Protokollierung unnötig sind, können sie dabei helfen, komplexe Protokollierungsanforderungen zu erfüllen.
Für das Protokollierungsframework von Java ist der Standardausgabeort das Home-Verzeichnis des Benutzers.
Während das Protokollierungsframework von Java alle grundlegenden Funktionen bereitstellt, können Frameworks von Drittanbietern durch die Kombination von Loggern, Handlern und Formatierern einiges leisten. Log4j 2 und Logback sind zwei beliebte Protokollierungs-Frameworks, jedes mit seinen eigenen Stärken.
Da für Java mehrere Frameworks verfügbar sind und sich ihre Funktionssätze ständig weiterentwickeln, möchten Entwickler oft etwas anderes ausprobieren. Hier kommen Protokollierungsabstraktoren ins Spiel. Mit Abstractoren können Entwickler mithilfe einer Standardfunktionsspezifikation schnell zwischen Protokollierungsframeworks wechseln. Simple Logging Facade for Java (SLF4J) ist ein beliebter Logging-Abstraktor, der das Standard-Framework Log4j 2 und Logback unterstützt. Apache Commons-Logging ist ein weiterer solcher Abstraktor.
Es ist jedoch wichtig zu beachten, dass ungepatchte Versionen von Log4j 2 ein kritisches Sicherheitsrisiko darstellen (CVE-2021-44228). Obwohl weniger schwerwiegend, bestehen auch erhebliche Sicherheitsrisiken für Log4j 1.x (CVE-2021-4104) und Logback (CVE-2021-42550). Da die Verwendung von Abstraktoren immer noch von diesen zugrunde liegenden Frameworks abhängt, ist es für eine sichere Verwendung unbedingt erforderlich, dass diese anfälligen Bibliotheken ordnungsgemäß aktualisiert und gepatcht werden.
Das Standard-Framework verwendet eine Konfigurationsdatei, um die Details von Appendern, Loggern und Layouts zu definieren. Standardmäßig befindet sich diese Datei im lib-Ordner des Java-Installationsverzeichnisses, es handelt sich jedoch um eine globale Konfigurationsdatei.
Es empfiehlt sich, eine anwendungsspezifische Konfigurationsdatei zu definieren. Sie können dies tun, indem Sie beim Starten der Anwendung den Namen der Eigenschaftendatei angeben, wie unten gezeigt:
Eine einfache Konfigurationsdatei sieht folgendermaßen aus:
Hier protokolliert die Konfiguration Anwendungsereignisse in einer Datei, die sie im Home-Verzeichnis des Benutzers erstellt. Der Wert %h bezeichnet das Home-Verzeichnis und %u bezeichnet eine beliebige eindeutige Nummer, die Java zur Unterscheidung zwischen Protokolldateien festlegt.
Um nun eine neue Protokolldatei aus einer neuen Klasse zu erstellen, können Sie den folgenden Codeausschnitt verwenden:
Wann und was protokolliert werden soll, liegt ganz beim Anwendungsentwickler und hängt von der vom Anwendungsteam gewählten Protokollierungsstrategie ab. Sobald der Entwickler entscheidet, welche Ereignisse protokolliert werden sollen, ist für die Protokollierung lediglich eine einzige Codezeile erforderlich. Hier ist ein Beispiel:
Hier verwendet das Snippet die Methode logger.log, um ein Protokollereignis beizubehalten. Die Methode benötigt zwei Eingaben: die Konfiguration der Loggerebene und den zu protokollierenden Text.
Sie können zwei weitere Methoden verwenden, um Protokollereignisse beizubehalten. Die logp-Methode protokolliert den Namen der Klasse und Funktionen zusammen mit dem Text. Mit der logrb-Methode können Sie das Ressourcenpaket für die Lokalisierung angeben. Dies ist wichtig für mehrsprachige Anwendungen. Beide Methoden können anstelle der Protokollmethode verwendet werden.
Das Protokollierungsframework unterstützt fünf Arten von Handlern (und daher fünf Arten von Zielen). Diese können einfach in der Eigenschaftendatei oder im Code konfiguriert werden. Lassen Sie uns diese fünf Handler untersuchen und sehen, wie sie verwendet werden sollen.
ConsoleHandler: Wie der Name schon sagt, werden dadurch Protokollereignisse an die Konsole ausgegeben. Hier gibt es keinen Mechanismus zum Beibehalten der Ausgabe. Alle Protokolleinträge gehen verloren, sobald die Konsole beendet wird. Sie können den Handler in der Eigenschaftendatei angeben:
FileHandler: Dieser Handler schreibt Protokolle in eine Datei. Mit diesem Handler können Sie Protokolldateien rotieren, wenn sie eine bestimmte Größe erreichen. Der folgende Ausschnitt zeigt, wie dieser Handler zusammen mit seinen spezifischen Parametern in der Eigenschaftendatei festgelegt wird:
Der Parameter limit definiert die maximale Protokolldateigröße in Bytes, nach der eine neue Protokolldatei erstellt wird. Der Parameter append legt fest, ob das Anhängen erlaubt sein soll, wenn der Dateiname existiert. Der Musterparameter definiert den Protokolldateinamen.
SocketHandler: Dieser Handler schreibt Protokolle in einen HTTP-Socket. Dies kann nützlich sein, wenn Sie die Protokolle in einer anderen Instanz oder einem anderen Dienst als dem bereits ausgeführten speichern müssen. Das hier verwendete Standardformat ist XMLFormatter.
StreamHandler: Dieser Handler schreibt die Ausgabe in einen OutputStream, der später zum Schreiben an ein beliebiges Ziel verwendet werden kann. Dieser Handler ist eine Basisklasse, die als Grundlage für den Fall dient, dass ein benutzerdefinierter Handler basierend auf einem anderen Ziel definiert werden muss. Die Definition ist so einfach wie das Festlegen des Handlers in der Eigenschaftendatei.
MemoryHandler: Dieser Handler schreibt alle Protokolleinträge in einen speicherinternen Ringpuffer. Es schreibt in den Speicherpuffer, wenn ein eingehender Datensatz eine höhere Ebene als eine vordefinierte hat oder bestimmte Bedingungen erfüllt. Diese Bedingungen können angepasst werden, indem eine Klasse implementiert wird, die die Protokollfunktion überschreibt. Die neue Funktion kann alle Datensätze scannen und entscheiden, wann geschrieben werden soll. Dieser Handler wird häufig verwendet, da die Pufferung im Hinblick auf die Leistung günstig und die Formatierung kostspielig ist. Durch die Verwendung dieses Handlers werden die Formatierungskosten aufgeschoben, bis der Schreibvorgang erforderlich ist.
Handler sind ein Bereich, in dem die Protokollierungsframeworks von Drittanbietern besser abschneiden als die Standardprotokollierungs-API. Log4j 2 bietet beispielsweise viele Handler, die häufig in einem Unternehmens-Setup verwendet werden. Der SysLogAppender schreibt beispielsweise Einträge in das Betriebssystemprotokoll (z. B. Syslog) oder einen Protokollaggregationsserver.
Protokollebenen helfen Entwicklern, Protokolle nach ihrer Wichtigkeit zu klassifizieren. Dies ist sehr nützlich, wenn Sie Code durch verschiedene Umgebungen migrieren – wie Entwicklung, Staging oder Produktion. In der Entwicklungsumgebung möchten Entwickler möglicherweise alle verfügbaren Informationen zum Debuggen oder Testen erhalten. Sobald der Code in der Produktion bereitgestellt wird, möchte das Betriebsteam möglicherweise nur über SCHWERE Protokollereignisse benachrichtigt werden. Das Java-Protokollierungsframework unterstützt sieben Protokollierungsstufen. Typischerweise verwenden Anwendungen die folgenden in aufsteigender Reihenfolge ihres Schweregrads:
Durch das Festlegen einer Protokollebene bei der Initialisierung der Logger-Klasse können Entwickler alle Protokolle unterhalb dieser Ebene herausfiltern. Wenn die Protokollebene beispielsweise auf INFO eingestellt ist, werden nur die mit INFO, WARNING oder SEVERE gekennzeichneten Ereignisse ausgegeben. Sie können die Protokollebene mit einem einfachen Befehl festlegen:
Mit der Protokollfunktion können Sie die Ebene für persistente Protokolleinträge festlegen.
In diesem ersten Teil unserer Übersicht haben wir die Grundlagen des Standardprotokollierungsframeworks von Java behandelt. Während das Framework alle grundlegenden Funktionen bereitstellt, die für die Protokollierung auf Anwendungsebene erforderlich sind, müssen Entwickler für erweiterte Funktionen benutzerdefinierte Handler schreiben. Protokollierungsframeworks von Drittanbietern wie Log4j 2 oder Logback erweitern den Funktionsumfang und machen eine benutzerdefinierte Entwicklung durch einen Entwickler überflüssig.
Im zweiten Teil dieser Serie lernen wir fortgeschrittene Konzepte der Java-Protokollierung kennen, einschließlich Ausnahmebehandlung, Formatierer und Protokollaggregation.
Arfan Sharif ist Produktmarketingleiter für das Observability-Portfolio bei CrowdStrike. Er verfügt über mehr als 15 Jahre Erfahrung in der Entwicklung von Log-Management-, ITOps-, Observability-, Sicherheits- und CX-Lösungen für Unternehmen wie Splunk, Genesys und Quest Software. Arfan hat einen Abschluss in Informatik von der Bucks and Chilterns University und blickt auf eine Karriere zurück, die sich über Produktmarketing und Vertriebstechnik erstreckt.
Java Logging Guide Entdecken Sie die komplette Java Logging Guide-Reihe: Logger: Handler: Formatter: ConsoleHandler: