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 logging;
26pub mod metrics;
27pub mod propagation;
28pub mod tracing_otel;
29
30pub use config::*;
31pub use container_spans::*;
32pub use error::{ObservabilityError, Result};
33pub use logging::{init_logging, LogGuard};
34pub use metrics::{init_metrics, metrics, HealthStatus, ZLayerMetrics};
35pub use tracing_otel::{create_otel_layer, init_tracing, TracingGuard};
36
37/// Combined guards for all observability components
38pub struct ObservabilityGuards {
39 /// Guard for the logging system (keeps async file writer running)
40 pub log_guard: LogGuard,
41 /// Guard for the tracing system (flushes traces on drop)
42 pub tracing_guard: TracingGuard,
43}
44
45/// Initialize all observability components
46///
47/// This is the recommended way to set up observability. It initializes:
48/// - Logging (always)
49/// - Metrics (always)
50/// - Tracing (if enabled in config)
51///
52/// Returns guards that must be held for the lifetime of the application.
53///
54/// # Example
55///
56/// ```no_run
57/// use zlayer_observability::{init_observability, ObservabilityConfig};
58///
59/// #[tokio::main]
60/// async fn main() {
61/// let config = ObservabilityConfig::default();
62/// let _guards = init_observability(&config).expect("Failed to init observability");
63///
64/// tracing::info!("Application started");
65/// // guards are dropped when main exits, flushing logs and traces
66/// }
67/// ```
68pub fn init_observability(config: &ObservabilityConfig) -> Result<ObservabilityGuards> {
69 // Initialize logging first so we can log from other init functions
70 let log_guard = init_logging(&config.logging)?;
71
72 // Initialize metrics
73 let _ = init_metrics(&config.metrics)?;
74
75 // Initialize tracing (may be disabled)
76 let tracing_guard = init_tracing(&config.tracing)?;
77
78 tracing::info!("Observability initialized");
79
80 Ok(ObservabilityGuards {
81 log_guard,
82 tracing_guard,
83 })
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn test_default_config() {
92 let config = ObservabilityConfig::default();
93 assert!(!config.tracing.enabled);
94 assert!(config.metrics.enabled);
95 }
96}