In diesem Blogartikel gebe ich eine kleine Einführung, wie man sehr schnell mit dem bekannten ELK Stack (Elasticsearch-Logstash-Kibana) eine Log Management Lösung für Spring Boot basierte Microservices aufsetzt. Ich werde zwei Methoden zeigen, wie man die Anwendungslogdateien einliest und zu der zentralen Elasticsearch Instanz transportiert. Grundsätzlich ist dies auch interessant für Anwender, die nicht Spring Boot einsetzen, aber bekannte Logging Frameworks, wie z.B. Logback, Log4J o.ä. verwenden.
Dieser Artikel geht nicht konkret auf die verwendeten Technologien ein und beschreibt sie von Grund auf. Im Netz gibt es dazu jedoch genügend Informationen. Falls noch kein Vorwissen besteht, sollte man sich vorher etwas über Elasticsearch, Logstash und Kibana informieren, bevor man hier startet. Eine gute Informationsquelle ist die Webseite von Elasticsearch , wo einige interessante Webinare und Dokumentationen zu finden sind. Meine Kollegen von codecentric haben ebenfalls schon über Themen im Zusammenhang mit Elasticsearch geblogged . Der Grund warum ich mich für Spring Boot als Beispiel entschieden habe ist, dass wir dieses Framework aktuell in einigen Projekten einsetzen. Ich glaube fest dran, dass Spring Boot dabei helfen wird den nächsten großen Schritt im Bereich der Enterprise Java Architekturen zu gehen. Bei der Einführung von Microservices wird jedoch auch eine größere Menge an Logdateien anfallen, so dass man hier auf jeden Fall eine gute Lösung braucht, um den Überblick zu behalten.
Zuerst klonen wir das Beispiel Git Repository und wechseln in dieses Verzeichnis.
1git clone http://github.com/denschu/elk-example 2cd elk-example
Die Spring Boot Beispielanwendung ist ein einfacher Batchjob und liegt in dem Verzeichnis „loggging-example-batch“. Die JVM wird mit folgenden Kommandos gestartet:
1cd loggging-example-batch/ 2mvn spring-boot:run
In der Datei „/tmp/server.log“ sollten nun schon einige Logeinträge zu finden sein, die so ähnlich aussehen, wie diese hier:
12014-10-10 17:21:10.358 INFO 11871 --- [ main] .t.TomcatEmbeddedServletContainerFactory : Server initialized with port: 8090 22014-10-10 17:21:10.591 INFO 11871 --- [ main] o.apache.catalina.core.StandardService : Starting service Tomcat 32014-10-10 17:21:10.592 INFO 11871 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/7.0.55 42014-10-10 17:21:10.766 INFO 11871 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 52014-10-10 17:21:10.766 INFO 11871 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2901 ms 62014-10-10 17:21:11.089 INFO 11322 [main] --- s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8090/http
Die Frage ist nun, wie man diese Datei einliest und weitertransportiert. Dazu setzen wir den ELK Stack nun auf und probieren zwei Varianten aus, wie man die Logdateien mit Logstash verarbeiten kann.
Vorbereitung
Elasticsearch
Dazu öffnen wir eine neue Shell und laden Elasticsearch zunächst herunter. Danach kann die Instanz ohne weitere Anpassungen gestartet werden.
1curl -O https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.1.1.tar.gz 2tar zxvf elasticsearch-1.1.1.tar.gz 3./elasticsearch-1.1.1/bin/elasticsearch
Kibana
In einer weitere Shell wird dann das Webfrontend Kibana installiert. Das zu entpackende Archiv enthält ein JavaScript-basiertes Dashboard, welches mit jedem beliebigen HTTP Server ausgeliefert werden kann. In diesem Beispiel wird der mitgelieferte Webserver von Python verwendet.
1curl -O https://download.elasticsearch.org/kibana/kibana/kibana-3.1.0.tar.gz 2tar zxvf kibana-3.1.0.tar.gz 3cd kibana-3.1.0/ 4python -m SimpleHTTPServer 8087
Bitte jetzt zunächst prüfen, ob das vorinstallierte Logstash Dashboard sich korrekt mit dem laufenden Elasticsearch Server verbindet. Als default verwendet Kibana hier die URL „http://localhost:9200“ (siehe config.js).
1http://localhost:8087/index.html#/dashboard/file/logstash.json
Logstash Agent
Für das Einlesen und den Transport der Logdateien werden so genannte Logstash Agenten verwendet. In einer neuen Shell wird dieser Agent ins Zielverzeichnis entpackt.
1curl -O https://download.elasticsearch.org/logstash/logstash/logstash-1.4.2.tar.gz 2tar zxvf logstash-1.4.2.tar.gz
Methode 1: Verarbeitung der Logdateien mit Grok
Die am häufigsten verwendete Methode zum verarbeiten der Dateien ist die Benutzung von Grok Filtern . Mit Hilfe von Patterns ist Grok in der Lage die relevanten Informationen aus den Logstatements zu extrahieren. Für unsere Spring Boot Beispielanwendung bzw. die dort verwendete Logback Konfiguration habe ich bereits einen Grok Filter erstellt, den wir nun direkt verwenden können:
1input { 2 stdin {} 3 file { 4 path => [ "/tmp/server.log" ] 5 } 6} 7filter { 8 multiline { 9 pattern => "^(%{TIMESTAMP_ISO8601})" 10 negate => true 11 what => "previous" 12 } 13 grok { 14 # Do multiline matching with (?m) as the above mutliline filter may add newlines to the log messages. 15 match => [ "message", "(?m)^%{TIMESTAMP_ISO8601:logtime}%{SPACE}%{LOGLEVEL:loglevel} %{SPACE}%{NUMBER:pid}%{SPACE}%{SYSLOG5424SD:threadname}%{SPACE}---%{SPACE}%{JAVACLASSSHORT:classname}%{SPACE}:%{SPACE}%{GREEDYDATA:logmessage}" ] 16 } 17} 18output { 19 elasticsearch { host => "localhost" } 20}
Damit die verkürzten Klassennamen (z.b. „o.s.web.context.ContextLoader“) korrekt eingelesen werden, muss noch ein zusätzliches Pattern (JAVACLASSSHORT) in Logstash registriert werden:
1cp custompatterns logstash-1.4.2/patterns/
Logstash Agent
Starte nun den Logstash Agenten mit der Spring Boot Konfiguration von oben. Diese Konfiguration befindet sich bereits im Beispielprojekt unter logstash-spring-boot.conf.
1./logstash-1.4.2/bin/logstash agent -v -f logstash-spring-boot.conf
Mit cURL bzw. einem HTTP POST Request wird der Job nun gestartet, damit auch Logstatements erzeugt werden.
1curl --data 'jobParameters=pathToFile=classpath:partner-import.csv' localhost:8090/batch/operations/jobs/flatfileJob
In dem vorkonfigurierten Logstash Dashboard in Kibana sollten nun die ersten Logeinträge zu sehen sein.
1http://localhost:8087/index.html#/dashboard/file/logstash.json
Methode 2: JSON Logback Encoder
Ein Nachteil von Methode 1 ist, dass es manchmal nicht so einfach ist ein voll funktionsfähiges Grok Pattern zu erstellen, dass alle Besonderheiten des Formats der Logeinträge berücksichtigt. Gerade mehrzeilige Logeinträge sind hier oft problematisch. Das in Spring Boot verwendete Log Format ist hier noch ein sehr gutes Beispiel, da größtenteils fixe Spaltengrößen verwendet werden. Eine Alternative dazu ist die direkte Erzeugung der Logeinträge im JSON-Format. Dazu wird nur ein weitere Maven Artefakt in der pom.xml benötigt (Dies ist bereits in der Beispiel Applikation eingetragen!).
1<dependency> 2 <groupId>net.logstash.logback</groupId> 3 <artifactId>logstash-logback-encoder</artifactId> 4 <version>2.5</version> 5</dependency>
… und noch ein spezieller Logstash Encoder in der Logback Konfigurationsdatei „logback.xml“, der letztendlich für die Erzeugung des JSON-Formats zuständig ist (Ebenfalls schon im Beispiel enthalten!).
1<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
Die neue Logstash Konfiguration (logstash-json.conf) ist nun viel kleiner und einfacher zu lesen:
1input { 2 file { 3 path => [ "/tmp/server.log.json" ] 4 codec => json { 5 charset => "UTF-8" 6 } 7 } 8} 9 10output { 11 elasticsearch { host => "localhost" } 12}
Alternative Log Transporter
Der Logstash Agent benötigt leider etwas mehr Speicher (bis zu 1GB) und ist somit nicht so optimal für kleinere Server (z.b. EC2 Micro Instances) geeignet. Für unsere Demo hier spielt das zwar keine große Rolle, aber insbesondere im Umfeld von Microservice-Umgebungen ist es empfehlenswert auf einen anderen Log Shipper zu setzen, wie z.B. den Logstash Forwarder (aka Lumberjack). Weitere Informationen dazu sind hier zu finden. Und für die JavaScript-Kollegen gibt es natürlich auch eine Implementierung für Node.JS .
Zusammenfassend lässt sich sagen, dass der ELK Stack (Elasticsearch-Logstash-Kibana) eine gute Kombination ist, um ein komplettes Log Management ausschließlich mit Open Source Technologien durchzuführen. Bei größeren Umgebungen mit einer sehr großen Menge an Logdateien sollte man ggf. noch ein zusätzlichen Transport (z.B. Redis) nutzen, um die einzelnen Komponenten (Log Server, Log Shipper) voneinander zu entkoppeln. In der nächsten Zeit werde ich noch weitere Themen im Zusammenhang mit Microservices beleuchten. Also seid gespannt und ich freu mich natürlich immer über Feedback :-).
Weitere Beiträge
von Dennis Schulte
Dein Job bei codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
Weitere Artikel in diesem Themenbereich
Entdecke spannende weiterführende Themen und lass dich von der codecentric Welt inspirieren.
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog-Autor*in
Dennis Schulte
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.