Dec 8th, 2019: [DE][Elasticsearch] Loggen in Elasticsearch mit Docker und Elastic Cloud

Loggen ist eines der Themen, das gerne ignoriert wird, bis man es benötigt. Und dann braucht man meistens eine schnelle Lösung. Glücklicherweise ist das Loggen in Elasticsearch sehr flexibel und auch relativ mächtig. Aber schauen wir uns das gleich konkret an.

Elasticsearch

Damit die Demo auf allen Betriebssystemen gleich funktioniert, verwenden wir Docker und wir nehmen an, dass das bereits installiert und gestartet ist. Zum Loggen genügt uns ein einziger Elasticsearch-Container, den wir mit folgendem Befehl starten können:

docker run -p 9200:9200 \
           -e "discovery.type=single-node" \
           -e ES_JAVA_OPTS="-Xms1g -Xmx1g" \
           --name elasticsearch-log \
           docker.elastic.co/elasticsearch/elasticsearch:7.5.0

Nach einigen Augenblicken ist Elasticsearch dann gestartet, was wir auch gleich mit curl -XGET localhost:9200/ testen können. Die Logs können wir außerdem mit docker logs --follow elasticsearch-log abfragen. Dabei sind zwei Dinge zu beachten:

  1. Der Elasticsearch Docker-Container loggt standardmäßig nach STDOUT statt in eine Datei und verwendet Dockers Standard log-driver json-file.
  2. Durch den --name Parameter beim docker run müssen wir nicht die ID des Containers suchen, sondern können stattdessen über seinen Namen darauf zugreifen.

Wer stattdessen in eine Datei loggen möchte (oder die Konfiguration ohne Docker anpassen will), kann die verfügbaren Parameter in der Dokumentation der Log4j 2 Konfiguration für Elasticsearch finden.

Nun aber zur Konfiguration des eigentlichen Log-Levels. Dabei gibt es vier verschiedene Möglichkeiten, die je nach Szenario mehr oder weniger sinnvoll sind. Bevor wir uns die Details dazu ansehen, gibt es aber noch zwei Konzepte, die wir kurz behandeln wollen:

  • Die unterstützten Log-Level sind TRACE, DEBUG, INFO, WARN, ERROR und FATAL.
  • Die Logger Hierarchie definiert für welchen Teil des Elasticsearch-Codes das jeweilige Log-Level gilt. Beispielsweise verweist logger.org.elasticsearch.transport auf elasticsearch/server/src/main/java/org/elasticsearch/transport/. Über logger._root lässt sich das Log-Level global ändern, was aber speziell in Kombination mit TRACE oder DEBUG nur mit Vorsicht eingesetzt werden sollte; einerseits wird es schwieriger die relevanten Log-Nachrichten zu finden, andererseits bringt das große Log-Volumen einen gewissen Overhead mit sich.

Kommandozeile

Auf der Kommandozeile kann über den Parameter -E <hierarchy>=<level> konfigurieren. Das ist speziell dann hilfreich, wenn es ein Problem beim Starten einer Node gibt. In unserem Docker-Beispiel funktioniert das folgendermaßen:

docker run -p 9200:9200 \
           -e "discovery.type=single-node" \
           -e ES_JAVA_OPTS="-Xms1g -Xmx1g" \
           -e "logger.org.elasticsearch.transport=trace" \
           --name elasticsearch-log \
           docker.elastic.co/elasticsearch/elasticsearch:7.5.0

Konfigurationsdatei

Ganz ähnlich funktioniert die Anpassung über die elasticsearch.yml Konfigurationsdatei mit logger.org.elasticsearch.transport: trace. Dafür müsste man die Datei in den Container mounten mit dem zusätzlichen Parameter -v full_path_to/custom_elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml . Der Ansatz ist aber primär dann empfehlenswert, wenn man Probleme beim Starten von Elasticsearch als Service hat (statt über die Kommandozeile).

REST API

Im laufenden Betrieb lassen sich Log-Level jederzeit dynamisch über die REST API anpassen, was äußerst hilfreich beim Debuggen sein kann:

curl -XPUT -H "Content-Type: application/json" \
     localhost:9200/_cluster/settings -d '{
  "transient": {
    "logger.org.elasticsearch.transport": "trace"
  }
}'

Drei Anmerkungen noch dazu:

  • Dieser Ansatz ändert das Log-Level für den ganzen Cluster, während die anderen nur für die jeweilige Node angewendet werden.
  • Cluster Settings die auf transient gesetzt sind, werden durch einen kompletten Neustart des Clusters automatisch zurückgesetzt.
  • Um das Log-Level auf den Standardwert zurückzusetzen, kann man den Cluster State mit "logger.org.elasticsearch.transport": null aktualisieren.

Konfigurationsdatei des Loggers

Abschließend lassen sich noch feingranulare Konfigurationen statisch über die log4j2.properties Datei setzen (wieder mit -v full_path_to/custom_log4j2.properties:/usr/share/elasticsearch/config/log4j2.properties ), was aber eher selten notwendig sein wird:

logger.transport.name = org.elasticsearch.transport
logger.transport.level = trace

Elastic Cloud

Nachdem wir uns jetzt die Optionen auf einem selbst betriebenen Cluster angesehen haben, schauen wir doch, was auf Elastic Cloud möglich ist. Dabei nehmen wir an, dass ein Cluster bereits gestartet ist und wir sofort mit dem Loggen loslegen können.

Die Konfigurations-Optionen beschränken sich dabei auf die REST API. Einerseits sollte sich das Service um den korrekten Start des Clusters kümmern, andererseits bieten Konfigurations-Dateien oder -Parameter eine unnötige Quelle für Fehlkonfigurationen. Für die leichtere Handhabung werden wir hier auch Kibana statt der Shell verwenden (Authentifizierung und URL werden dabei automatisch richtig konfiguriert). Unter Dev Tools -> Console können wir damit die bereits bekannte Logging-Konfiguration folgendermaßen anwenden:

PUT /_cluster/settings
{
  "transient": {
    "logger.org.elasticsearch.transport": "trace"
  }
}

Aktuell kann man die Log-Nachrichten anschließend im Cloud Admin UI unter Cluster-Name -> Elasticsearch -> Logs finden. Dahinter steckt ein Logging-Cluster, in dem man auch seine eigenen Logs durchsuchen kann.

Zusammenfassung

In der Theorie ist Loggen kein Problem — in der Praxis gibt es damit trotzdem immer wieder Probleme. Ich hoffe, der Beitrag hilft etwas mehr Klarheit zu schaffen. Meine persönlichen Lieblingstricks sind:

  • Globales Logging mit logger._root anpassen (auch wenn es mit Vorsicht zu genießen ist).
  • Zurücksetzen der Konfiguration des Cluster States mit null.
  • Logging auf Elastic Cloud — eigentlich simpel, aber es führt trotzdem immer wieder zu Verwirrung, wo die Log-Datei verfügbar ist.