Logging in Rust-Anwendungen: Best Practices für die Einrichtung

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Warum Logging für Rust-Anwendungen entscheidend ist

Logging ist nicht nur das Aufzeichnen von Ereignissen in einer Datei. In einer Produktionsumgebung ermöglichen hochwertige Logs eine schnelle Diagnose von Fehlern, die Überwachung der Leistung und die Analyse des Systemverhaltens. Rust, als systemnahe Programmiersprache, bietet flexible und leistungsstarke Werkzeuge für diese Aufgabe. In diesem Artikel werden wir die besten Praktiken für das Logging in Rust durchgehen: von der Auswahl der Crate bis zur Konfiguration von strukturierten Logs und Rotation.



1. Grundlagen: Die Crates log und env_logger

Das Rust-Ökosystem bietet einen modularen Ansatz. Die Crate log stellt eine Abstraktion (Fassade) bereit, während eine konkrete Implementierung (Backend) durch eine separate Crate wie env_logger oder pretty_env_logger eingebunden wird.



Installation und Konfiguration

Fügen Sie die Abhängigkeiten in Cargo.toml hinzu:

[dependencies]log = "0.4"env_logger = "0.10"


Basisbeispiel

use log::{info, warn, error};

fn main() { env_logger::init();

info!("Anwendung gestartet"); let user_id = 42; warn!("Benutzer {} nicht im Cache gefunden", user_id); error!("Fehler bei der Datenbankverbindung: {:?}", "timeout");}


Wichtig: Standardmäßig werden keine Logs ausgegeben, bis Sie die Umgebungsvariable RUST_LOG setzen. Starten Sie das Programm wie folgt:

RUST_LOG=info cargo run


Log-Level

Die Crate log unterstützt fünf Standard-Level (von der höchsten zur niedrigsten Priorität):

  • error — Kritische Fehler, die sofortiges Eingreifen erfordern.
  • warn — Warnungen vor potenziellen Problemen.
  • info — Allgemeine Informationen zum Programmablauf.
  • debug — Debug-Informationen für Entwickler.
  • trace — Maximal detaillierte Ereignisse (häufig in Schleifen verwendet).

Filterung nach Modulen: RUST_LOG=my_crate=debug,other_crate=info.



2. Fortgeschrittenes Logging: Die Crate tracing

Für komplexe Anwendungen (Webserver, Microservices) wird die Verwendung der Crate tracing empfohlen. Sie bietet das Konzept von Spans (Zeitintervallen) und strukturiertes Logging mit Kontext.



Installation von tracing

[dependencies]tracing = "0.1"tracing-subscriber = "0.3"


Beispiel mit Span

use tracing::{info, instrument, span, Level};use tracing_subscriber;

fn main() { tracing_subscriber::fmt::init();

let parent_span = span!(Level::INFO, "request_processing", request_id = 123); let _guard = parent_span.enter(); process_data();}

#[instrument]fn process_data() { info!("Datenverarbeitung gestartet"); std::thread::sleep(std::time::Duration::from_millis(50)); info!("Datenverarbeitung abgeschlossen");}

Das Attribut #[instrument] erstellt automatisch einen Span für die Funktion und zeichnet die Ausführungszeit auf. Die Ausgabe enthält verschachtelte Zeitstempel, was für das Profiling unverzichtbar ist.



3. Strukturierte Logs (JSON) und Rotation

In einer Produktionsumgebung werden Logs oft zentralisiert gesammelt (ELK, Loki, Grafana). Dafür ist es praktisch, Logs im JSON-Format auszugeben.



JSON-Ausgabe mit tracing-subscriber

use tracing_subscriber::fmt::format::Json;use tracing_subscriber::prelude::*;

fn main() { let format = Json::new() .with_timer(tracing_subscriber::fmt::time::UtcTime::rfc3339()) .with_target(true) .with_level(true);

tracing_subscriber::fmt() .event_format(format) .init();

tracing::info!("Server gestartet auf Port 8080");}

Die Logs sehen dann wie folgt aus:

Blogs

Buchempfehlungen