Skip to main content

zlayer_observability/
lib.rs

1//! `ZLayer` Observability - Logging, Tracing, and Metrics
2//!
3//! Provides unified observability infrastructure:
4//! - Structured logging with JSON/pretty formats
5//! - OpenTelemetry distributed tracing
6//! - Prometheus metrics exposition
7//!
8//! # Quick Start
9//!
10//! ```no_run
11//! use zlayer_observability::{init_observability, ObservabilityConfig};
12//!
13//! #[tokio::main]
14//! async fn main() {
15//!     let config = ObservabilityConfig::default();
16//!     let _guards = init_observability(&config).expect("Failed to init observability");
17//!
18//!     tracing::info!("Application started");
19//! }
20//! ```
21
22pub mod config;
23pub mod container_spans;
24pub mod error;
25pub mod log_reader;
26pub mod logging;
27pub mod logs;
28pub mod metrics;
29pub mod propagation;
30pub mod tracing_otel;
31
32pub use config::*;
33pub use container_spans::*;
34pub use error::{ObservabilityError, Result};
35pub use logging::{init_logging, LogGuard};
36pub use metrics::{init_metrics, metrics, HealthStatus, ZLayerMetrics};
37pub use tracing_otel::{create_otel_layer, init_tracing, TracingGuard};
38
39/// Combined guards for all observability components
40pub struct ObservabilityGuards {
41    /// Guard for the logging system (keeps async file writer running)
42    pub log_guard: LogGuard,
43    /// Guard for the tracing system (flushes traces on drop)
44    pub tracing_guard: TracingGuard,
45}
46
47/// Initialize all observability components
48///
49/// This is the recommended way to set up observability. It initializes:
50/// - Logging (always)
51/// - Metrics (always)
52/// - Tracing (if enabled in config)
53///
54/// Returns guards that must be held for the lifetime of the application.
55///
56/// # Example
57///
58/// ```no_run
59/// use zlayer_observability::{init_observability, ObservabilityConfig};
60///
61/// #[tokio::main]
62/// async fn main() {
63///     let config = ObservabilityConfig::default();
64///     let _guards = init_observability(&config).expect("Failed to init observability");
65///
66///     tracing::info!("Application started");
67///     // guards are dropped when main exits, flushing logs and traces
68/// }
69/// ```
70///
71/// # Errors
72/// Returns an error if any observability component fails to initialize.
73pub fn init_observability(config: &ObservabilityConfig) -> Result<ObservabilityGuards> {
74    // Initialize logging first so we can log from other init functions
75    let log_guard = init_logging(&config.logging)?;
76
77    // Initialize metrics
78    let _ = init_metrics(&config.metrics)?;
79
80    // Initialize tracing (may be disabled)
81    let tracing_guard = init_tracing(&config.tracing)?;
82
83    tracing::info!("Observability initialized");
84
85    Ok(ObservabilityGuards {
86        log_guard,
87        tracing_guard,
88    })
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94
95    #[test]
96    fn test_default_config() {
97        let config = ObservabilityConfig::default();
98        assert!(!config.tracing.enabled);
99        assert!(config.metrics.enabled);
100    }
101}