Logging System
10/30/24About 1 min
Logging System (tracing)
A robust logging system is the foundation of observability, essential for debugging, performance monitoring, and audit trails. Our project uses the most advanced tracing framework in the Rust ecosystem to build a high-performance, structured, and configurable logging system.
Core Design Philosophy
- Structured: We record structured events with rich context, not plain text strings
- High-Performance: Logging never blocks core application logic
- Configurable: All logging behavior is managed through configuration files
- Developer-Friendly: Pretty-printed console output in dev; compact, machine-friendly file output in production
Core Features
1. Structured Logging (tracing)
// Simple info log
tracing::info!("User logged in successfully");
// Log with structured context
tracing::info!(
user_id = user.id,
username = user.username,
ip_address = %client_ip,
"User logged in successfully"
);2. Dual Output
- Console (stdout): Pretty-printed with colors for local development
- Log files: Compact single-line format (JSON-like) for log collection systems
3. Non-blocking (Async) Log Writing
Uses tracing_appender::non_blocking to wrap file and console writes. When application code calls tracing::info!, the message is quickly sent to an in-memory channel, and the app continues immediately. A dedicated background worker thread performs the actual I/O.
4. Rolling Log Files
Uses hourly rolling to prevent single log files from growing indefinitely.
Configuration
[logger]
level = "Info"
log_dir = "logs"
file_name = "app.log"How to Use in Code
// Simple info event
tracing::info!("Processing order creation request");
// Warning with context
tracing::warn!(order_id = 12345, error = "Insufficient inventory", "Order creation failed");
// Function with instrumentation
#[tracing::instrument]
async fn process_payment(amount: u64) {
tracing::debug!("Processing payment...");
// ... logic ...
tracing::info!("Payment completed");
}Best Practices
- Use structured fields: Add meaningful key-value pairs to log events
- Choose appropriate levels:
ERROR: Critical errors, application may be unable to continueWARN: Unexpected situations, but application can continueINFO: Important lifecycle eventsDEBUG: Development debuggingTRACE: Most detailed, function-level debugging
- Use
instrument: For important async functions, use#[tracing::instrument]to track execution flow and duration