Zum Inhalt springen

Logging

DuckDB implementiert einen Logging-Mechanismus, der detaillierte Informationen zu Ereignissen wie Query-Ausführung, Leistungsmetriken und Systemereignissen liefert.

Grundlagen

Der DuckDB-Logging-Mechanismus lässt sich über die spezielle Funktion enable_logging ein- oder ausschalten. Logs werden in einer speziellen View namens duckdb_logs gespeichert, die sich wie jede normale Tabelle abfragen lässt.

Beispiel:

CALL enable_logging();
-- Run some queries...
SELECT * FROM duckdb_logs;

Um Logging zu deaktivieren, führen Sie aus

CALL disable_logging();

Um das aktuelle Log zu leeren, führen Sie aus

CALL truncate_duckdb_logs();

Log-Level

DuckDB unterstützt verschiedene Log-Level, die die Ausführlichkeit der Logs steuern:

  • ERROR: Protokolliert nur Fehlermeldungen
  • WARN: Protokolliert Warnungen und Fehler
  • INFO: Protokolliert allgemeine Informationen, Warnungen und Fehler (Standard)
  • DEBUG: Protokolliert detaillierte Debugging-Informationen
  • TRACE: Protokolliert sehr detaillierte Tracing-Informationen

Das Log-Level kann so gesetzt werden:

CALL enable_logging(level = 'debug');

Log-Typen

In DuckDB können Log-Meldungen einen zugehörigen Log-Typ haben. Log-Typen ermöglichen zwei Dinge:

  • Feingranulare Steuerung der Erzeugung von Log-Meldungen
  • Unterstützung für strukturiertes Logging

Bestimmte Typen loggen

Um nur Meldungen eines bestimmten Typs zu loggen:

CALL enable_logging('HTTP');

Die obige Funktion setzt automatisch das passende Log-Level und fügt den Typ HTTP zu den Einstellungen enabled_log_types hinzu. So werden nur Log-Meldungen vom Typ ‘HTTP’ ins Log geschrieben.

Um mehrere Log-Typen zu aktivieren, übergeben Sie einfach:

CALL enable_logging(['HTTP', 'QueryLog']);

Strukturiertes Logging

Einige Log-Typen wie HTTP haben ein zugehöriges Nachrichten-Schema. Damit DuckDB die Nachricht automatisch parst, verwenden Sie das Makro duckdb_logs_parsed(). Beispiel:

SELECT request.headers FROM duckdb_logs_parsed('HTTP');

Um das Schema jedes strukturierten Log-Typs anzuzeigen, führen Sie einfach aus:

DESCRIBE FROM duckdb_logs_parsed('HTTP');

Liste der verfügbaren Log-Typen

Dies ist eine (nicht vollständige) Liste der in DuckDB verfügbaren Log-Typen.

Log-Typ Beschreibung Strukturiert
QueryLog Protokolliert, welche Queries in DuckDB ausgeführt werden Nein
FileSystem Protokolliert alle FileSystem-Interaktionen mit DuckDBs Filesystem Ja
HTTP Protokolliert den gesamten HTTP-Verkehr des internen HTTP-Clients von DuckDB Ja
PhysicalOperator Protokolliert Ereignisse physischer Operatoren während der Query-Ausführung Ja
Metrics Protokolliert Profiling-Metriken, die während der Query-Ausführung erfasst werden Ja

Die strukturierten Log-Typen stellen die folgenden Schemas bereit, die Sie jederzeit mit DESCRIBE FROM duckdb_logs_parsed(⟨log_type⟩){:.language-sql .highlight} einsehen können:

Log-Typ Schema
FileSystem fs VARCHAR, path VARCHAR, op VARCHAR, bytes BIGINT, pos BIGINT
HTTP request STRUCT(type, url, start_time, duration_ms, headers MAP), response STRUCT(status, reason, headers MAP)
PhysicalOperator operator_type VARCHAR, parameters MAP(VARCHAR, VARCHAR), class VARCHAR, event VARCHAR, info MAP(VARCHAR, VARCHAR)
Metrics metric VARCHAR, value VARCHAR

Log-Speicher

Standardmäßig loggt DuckDB in einen In-Memory-Log-Speicher (memory). DuckDB unterstützt verschiedene Arten von Log-Speicher. Derzeit sind die folgenden Log-Speichertypen im DuckDB-Kern implementiert.

Log-Speicher Beschreibung
memory (Standard) In einen In-Memory-Puffer loggen
stdout Auf die stdout des aktuellen Prozesses loggen (im CSV-Format)
file In eine oder mehrere CSV-Dateien loggen

Beachten Sie, dass die View duckdb_logs automatisch auf den aktuell aktiven Log-Speicher zeigt. Das Umschalten des Log-Speichers kann daher beeinflussen, was die Funktion duckdb_logs zurückgibt.

Logging nach stdout

CALL enable_logging(storage = 'stdout');

Logging in eine Datei

CALL enable_logging(storage = 'file', storage_config = {'path': 'path/to/store/logs'});

oder mit der gleichwertigen Kurzform:

CALL enable_logging(storage_path = 'path/to/store/logs');

Fortgeschrittene Nutzung

Normalisiertes vs. denormalisiertes Logging

Die Log-Speicher von DuckDB können auf zwei Arten loggen: normalisiert oder denormalisiert.

Beim denormalisierten Logging werden die Kontextinformationen direkt an jeden Log-Eintrag angehängt, beim normalisierten Logging werden die Log-Einträge getrennt gespeichert und verweisen über context_ids auf die Kontextinformationen.

Log-Speicher Normalisiert
memory ja
file konfigurierbar
stdout nein

Für den Dateispeicher können Sie zwischen normalisiert und denormalisiert wechseln, indem Sie einen Pfad angeben, der auf .csv endet (normalisiert) oder ohne .csv (denormalisiert). Für Datei-Logging ist Denormalisierung in der Regel empfehlenswert, weil das die Leistung steigert und die Gesamtgröße der Logs verringert. Normalisierung des file-Log-Speichers konfigurieren:

-- normalized: creates `/tmp/duckdb_log_contexts.csv` and `/tmp/duckdb_log_entries.csv`
CALL enable_logging(storage_path = '/tmp');
-- denormalized: creates `/tmp/logs.csv`
CALL enable_logging(storage_path = '/tmp/logs.csv');

Beachten Sie, dass der Unterschied zwischen normalisiert und denormalisiert für Benutzer typischerweise hinter der Funktion duckdb_logs verborgen bleibt, die normalisierte Tabellen automatisch zu einem einheitlichen Ergebnis zusammenführt. Zur Veranschaulichung: Beide Konfigurationen oben sind mit FROM duckdb_logs; abfragbar und liefern identische Ergebnisse.

Puffergröße

Der Log-Speicher in DuckDB implementiert einen Puffermechanismus, um die Logging-Leistung zu optimieren. Diese Implementierung führt zu einer möglichen Verzögerung zwischen dem Loggen einer Meldung und dem Schreiben in den Speicher. Diese Verzögerung kann den tatsächlichen Schreibzeitpunkt der Meldung verschleiern, was besonders beim Debuggen von Abstürzen problematisch ist, weil unmittelbar vor einem Absturz erzeugte Meldungen möglicherweise nicht geschrieben werden. Um das zu adressieren, kann die Puffergröße wie folgt konfiguriert werden:

CALL enable_logging(storage_config = {'buffer_size': 0});

oder mit der gleichwertigen Kurzform:

CALL enable_logging(storage_buffer_size = 0);

Beachten Sie, dass die Standard-Puffergröße je nach Log-Speicher unterschiedlich ist:

Log-Speicher Standard-Puffergröße
memory STANDARD_VECTOR_SIZE (2048)
file STANDARD_VECTOR_SIZE (2048)
stdout Deaktiviert (0)

Wenn Sie beispielsweise die stdout-Logging-Leistung steigern möchten, aktivieren Sie einfach Pufferung, um das Logging deutlich (>10×) zu beschleunigen:

CALL enable_logging(storage = 'stdout', storage_buffer_size = 2048);

Oder stellen Sie sich vor, Sie debuggen einen Absturz in DuckDB und möchten den file-Logger nutzen, um zu verstehen, was passiert. Deaktivieren Sie einfach die Pufferung mit:

CALL enable_logging(storage_path = '/tmp/mylogs', storage_buffer_size = 0);

Syntaktischer Zucker

DuckDB bietet etwas syntaktischen Zucker, um gängige Pfade zu vereinfachen. Die folgenden Anweisungen sind beispielsweise alle gleichwertig:

-- regular invocation
CALL enable_logging(storage = 'file', storage_config = {'path': 'path/to/store/logs'});
-- using shorthand for common path storage config param
CALL enable_logging(storage = 'file', storage_path = 'path/to/store/logs');
-- omitting `storage = 'file'` -> is implied from presence of `storage_config`
CALL enable_logging(storage_config = {'path': 'path/to/store/logs'});