pub mod config;
pub mod container_spans;
pub mod error;
pub mod log_reader;
pub mod logging;
pub mod logs;
pub mod metrics;
pub mod propagation;
pub mod tracing_otel;
use std::path::PathBuf;
pub use config::*;
pub use container_spans::*;
pub use error::{ObservabilityError, Result};
pub use logging::{init_logging, LogGuard};
pub use metrics::{init_metrics, metrics, HealthStatus, ZLayerMetrics};
pub use tracing_otel::{
init_otlp_in_runtime, otlp_is_enabled, set_telemetry_provider, DefaultOtlpProvider, OtlpGuard,
TelemetryProvider,
};
pub struct ObservabilityGuards {
pub log_guard: LogGuard,
pub otlp: OtlpGuard,
}
pub fn init_observability(config: &ObservabilityConfig) -> Result<ObservabilityGuards> {
let log_guard = if otlp_is_enabled(&config.tracing) {
LogGuard::noop()
} else {
let g = logging::init_logging_inner(&config.logging)?;
tracing::info!("Observability initialized");
g
};
let _ = init_metrics(&config.metrics)?;
Ok(ObservabilityGuards {
log_guard,
otlp: OtlpGuard::default(),
})
}
#[derive(Debug, Clone)]
pub struct CommonLoggingOptions {
pub file: bool,
pub log_dir: Option<PathBuf>,
pub default_level: LogLevel,
pub filter_directives: Option<String>,
pub format: LogFormat,
}
impl Default for CommonLoggingOptions {
fn default() -> Self {
Self {
file: true,
log_dir: None,
default_level: LogLevel::Info,
filter_directives: None,
format: LogFormat::Pretty,
}
}
}
pub fn init_common_logging(
app_name: &str,
opts: CommonLoggingOptions,
) -> Result<ObservabilityGuards> {
let file = if opts.file {
let dir = opts.log_dir.unwrap_or_else(default_common_log_dir);
let _ = std::fs::create_dir_all(&dir);
Some(FileLoggingConfig {
directory: dir,
prefix: format!("{app_name}.log"),
rotation: RotationStrategy::Daily,
max_files: Some(7),
})
} else {
None
};
let logging = LoggingConfig {
level: opts.default_level,
format: opts.format,
file,
filter_directives: opts.filter_directives,
..Default::default()
};
let tracing = TracingConfig::from_env();
if otlp_is_enabled(&tracing) && tokio::runtime::Handle::try_current().is_ok() {
let obs = ObservabilityConfig {
logging,
tracing,
..Default::default()
};
let otlp = init_otlp_in_runtime(&obs);
return Ok(ObservabilityGuards {
log_guard: LogGuard::noop(),
otlp,
});
}
let log_guard = logging::init_logging_inner(&logging)?;
Ok(ObservabilityGuards {
log_guard,
otlp: OtlpGuard::default(),
})
}
fn default_common_log_dir() -> PathBuf {
std::env::var_os("HOME")
.or_else(|| std::env::var_os("USERPROFILE"))
.map_or_else(std::env::temp_dir, PathBuf::from)
.join(".zlayer")
.join("logs")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = ObservabilityConfig::default();
assert!(!config.tracing.enabled);
assert!(config.metrics.enabled);
}
}