Ein Log-Level ist die Schweregrad-Angabe eines Log-Eintrags, typischerweise TRACE, DEBUG, INFO, WARN, ERROR oder FATAL. Er zeigt Menschen und Tools, wie wichtig ein Ereignis ist, und erlaubt dem Logger, Einträge unterhalb eines konfigurierten Schwellenwerts zu verwerfen, sodass ausführliche Diagnoseausgaben in Produktion ohne Codeänderung abgeschaltet werden können.
Was ist ein Log-Level?
Ein Log-Level beschreibt den Schweregrad eines einzelnen Log-Eintrags. Alle verbreiteten Logging-Frameworks, von Log4j und Logback in Java über das logging-Modul in Python und slog in Go bis zu Node.js-Bibliotheken wie pino, versehen jeden Eintrag mit einem Level und vergleichen ihn mit einem konfigurierten Schwellenwert. Einträge darunter werden verworfen, bevor sie formatiert oder verschickt werden. Log-Level sind deshalb gleichzeitig ein Kommunikationsmittel und ein Hebel für Kosten und Performance.
Ein Level beantwortet zwei Fragen: Wie dringend ist das Ereignis für einen Menschen, und soll der Eintrag in dieser Umgebung überhaupt existieren? Ein DEBUG-Eintrag hilft auf dem Entwickler-Laptop und ist in Produktion meist Rauschen, ein ERROR-Eintrag sollte dagegen immer erfasst und oft auch gezählt werden.
Die gängigen Log-Level im Überblick
Die Bezeichnungen unterscheiden sich leicht, die meisten Frameworks nutzen aber dieselben sechs Stufen, sortiert von ausführlich nach kritisch:
| Level | Bedeutung | Typisches Beispiel |
|---|---|---|
TRACE | Sehr feingranularer Programmablauf | Betreten und Verlassen von Funktionen, Schleifendurchläufe |
DEBUG | Diagnosedetails für Entwickler | Aufgelöste Konfigurationswerte, Cache-Hit oder -Miss |
INFO | Normale, relevante Ereignisse | Service gestartet, Job beendet, Bestellung angelegt |
WARN | Unerwartet, aber behandelt | Retry erfolgreich, veraltete API genutzt, Pool fast voll |
ERROR | Eine Operation ist fehlgeschlagen | Zahlungsanfrage gescheitert, unbehandelte Exception |
FATAL | Der Prozess kann nicht weiterlaufen | Pflichtkonfiguration fehlt, nicht behebbare Datenkorruption |
Es gibt Abweichungen: Python kennt CRITICAL statt FATAL und kein TRACE, Go-slog definiert nur Debug, Info, Warn und Error, und Syslog (RFC 5424) arbeitet mit acht numerischen Stufen von 0 (Emergency) bis 7 (Debug), wobei eine kleinere Zahl schwerwiegender ist.
Log-Level in OpenTelemetry
Weil jedes Framework Level anders benennt, normalisiert das Log-Datenmodell von OpenTelemetry sie. Jeder Log Record enthält einen SeverityText (den Originalwert, etwa "warning") und eine SeverityNumber von 1 bis 24, aufgeteilt in sechs Bereiche: TRACE 1–4, DEBUG 5–8, INFO 9–12, WARN 13–16, ERROR 17–20 und FATAL 21–24. Der Wert 0 steht für „nicht angegeben“. Innerhalb eines Bereichs bedeutet eine höhere Zahl einen höheren Schweregrad, sodass zusätzliche Framework-Level ohne Verlust der Reihenfolge abgebildet werden. Abfragen wie „alles ab WARN“ funktionieren damit über Java-, Python- und Go-Services hinweg und bleiben beim Transport über OTLP erhalten.
So wählen Sie das richtige Level
- ERROR heißt: Jemand muss eventuell handeln. Wenn nie jemand hinschauen sollte, ist es kein Fehler. Erwartbare Fälle wie ein 404 für eine unbekannte ID gehören meist zu INFO oder DEBUG.
- WARN steht für „eingeschränkt, aber funktionsfähig“. Ein erfolgreicher Retry oder ein greifender Fallback gehört hierher. Viele WARNs ohne Konsequenz werden zu Rauschen und fördern Alert Fatigue.
- INFO erzählt die Geschichte des Systems. Lebenszyklus-Ereignisse und fachliche Meilensteine, nicht jeder Funktionsaufruf.
- DEBUG und TRACE sind in Produktion standardmäßig aus und werden gezielt pro Service oder Package aktiviert, idealerweise ohne Redeployment.
- Einen Fehler nur einmal loggen. Wer dieselbe Exception auf jeder Ebene des Call-Stacks loggt, vervielfacht das Volumen und verfälscht Zählungen.
Beispiel: konfigurierbarer Schwellenwert
Ein illustrativer Python-Service liest seinen Schwellenwert aus einer Umgebungsvariablen und schreibt strukturierte Einträge:
import logging, os
logging.basicConfig(level=os.getenv("LOG_LEVEL", "INFO"))
log = logging.getLogger("payments")
log.debug("fx rate loaded", extra={"pair": "EURUSD"}) # bei INFO verworfen
log.warning("charge retried", extra={"attempt": 2})
log.error("charge failed", extra={"order_id": "A-1042"})
Mit LOG_LEVEL=INFO werden nur Warnung und Fehler geschrieben. Setzen Sie während einer Analyse LOG_LEVEL=DEBUG für einen einzelnen Pod, erscheint auch der Diagnoseeintrag, ohne den Rest der Flotte zu berühren. Zusammen mit strukturiertem Logging wird das Level zu einem Feld, nach dem Sie filtern, zählen und alarmieren können. In Java erreichen Sie dasselbe über Logger-Konfigurationen pro Package, etwa ein eigenes Level für com.example.payments, das sich bei Logback oder Log4j 2 zur Laufzeit ändern lässt.
Typische Fehler
- DEBUG bleibt in Produktion aktiv, bläht das Ingest-Volumen auf und gibt unter Umständen sensible Payloads preis.
- Erwartete, behandelte Situationen werden als ERROR geloggt, sodass Fehlerzählungen ihre Aussagekraft verlieren.
- Uneinheitliche Level-Namen über Services hinweg (
warn,warning,W) brechen Abfragen, solange sie nicht normalisiert werden. - Level sind der einzige Filter, statt ausführliche Logs zusätzlich in einer Telemetrie-Pipeline zu routen oder zu sampeln.
- Jede einzelne ERROR-Zeile löst einen Alarm aus, statt Fehlerraten und deren Auswirkung zu betrachten.
Wie Obseria hilft
Obseria nimmt Logs über OpenTelemetry entgegen und bildet Schweregrade auf das OTel-Modell ab. So filtern Sie sprachübergreifend einheitlich, etwa mit fetch logs | filter service == "payments" | summarize count(), by:{level} in OQL. Obseria Pipeline kann DEBUG-Einträge beim Ingest verwerfen oder umleiten, und gefilterte Daten kosten nur die Ingestion. Mehr dazu unter Log Analytics, wo Sie Logs gemeinsam mit Traces durchsuchen und analysieren.