Skip to main content

pleme_observability/
lib.rs

1//! # pleme-observability
2//!
3//! Observability library for Pleme platform services.
4//!
5//! ## Features
6//!
7//! - **Structured Logging** - JSON logging with tracing
8//! - **Distributed Tracing** - OpenTelemetry integration (feature-gated)
9//! - **Metrics** - Prometheus metric definition macros and tracking helpers
10//! - **Context Propagation** - W3C Trace Context
11//!
12//! ## Quick Start
13//!
14//! ```rust,ignore
15//! use pleme_observability::init_observability;
16//!
17//! fn main() {
18//!     // Auto-detects: uses OTel if OTEL_EXPORTER_OTLP_ENDPOINT is set,
19//!     // otherwise falls back to basic JSON tracing.
20//!     init_observability("my-service");
21//!     tracing::info!("Service started");
22//! }
23//! ```
24
25pub mod logging;
26
27#[cfg(feature = "distributed-tracing")]
28pub mod tracing;
29
30pub mod metrics;
31
32#[macro_use]
33pub mod macros;
34
35pub mod tracking;
36
37pub use logging::init_tracing;
38
39#[cfg(feature = "distributed-tracing")]
40pub use tracing::{
41    init_distributed_tracing, init_distributed_tracing_with_config, shutdown_tracing, TracingConfig,
42};
43
44pub use metrics::MetricsCollector;
45
46use thiserror::Error;
47
48/// Observability errors
49#[derive(Error, Debug)]
50pub enum ObservabilityError {
51    #[error("Tracing initialization failed: {0}")]
52    TracingInit(String),
53
54    #[error("Metrics collection failed: {0}")]
55    MetricsError(String),
56}
57
58/// Result type for observability operations
59pub type Result<T> = std::result::Result<T, ObservabilityError>;
60
61/// Initialize observability with automatic environment detection.
62///
63/// - If `OTEL_EXPORTER_OTLP_ENDPOINT` is set: initializes distributed tracing with OTel
64/// - Otherwise: initializes basic JSON tracing (local dev)
65///
66/// This lets the same code work in dev (no OTel) and prod (with OTel) without code changes.
67pub fn init_observability(service_name: &str) {
68    match std::env::var("OTEL_EXPORTER_OTLP_ENDPOINT") {
69        #[cfg(feature = "distributed-tracing")]
70        Ok(endpoint) => {
71            let mut config = TracingConfig::new(service_name, &endpoint);
72
73            if let Ok(env) = std::env::var("DEPLOYMENT_ENV") {
74                config = config.with_environment(env);
75            }
76            if let Ok(version) = std::env::var("SERVICE_VERSION") {
77                config = config.with_version(version);
78            }
79
80            if let Err(e) = init_distributed_tracing_with_config(config) {
81                eprintln!(
82                    "WARNING: Failed to initialize distributed tracing: {}. Falling back to basic tracing.",
83                    e
84                );
85                init_tracing(service_name);
86            }
87        }
88        #[cfg(not(feature = "distributed-tracing"))]
89        Ok(_endpoint) => {
90            eprintln!(
91                "WARNING: OTEL_EXPORTER_OTLP_ENDPOINT is set but distributed-tracing feature is not enabled. Using basic tracing."
92            );
93            init_tracing(service_name);
94        }
95        Err(_) => {
96            init_tracing(service_name);
97        }
98    }
99}