use std::net::SocketAddr;
#[cfg(feature = "observability")]
use metrics_exporter_prometheus::PrometheusBuilder;
#[cfg(feature = "observability")]
pub fn init_tracing() -> bool {
use tracing_subscriber::{EnvFilter, fmt, prelude::*};
let filter = EnvFilter::try_from_default_env()
.unwrap_or_else(|_| EnvFilter::new("info,epics_ca_rs=debug"));
tracing_subscriber::registry()
.with(filter)
.with(fmt::layer().with_target(false))
.try_init()
.is_ok()
}
#[cfg(feature = "observability")]
pub fn serve_prometheus(addr: SocketAddr) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
PrometheusBuilder::new()
.with_http_listener(addr)
.install()?;
Ok(())
}
#[cfg(not(feature = "observability"))]
pub fn init_tracing() -> bool {
false
}
#[cfg(not(feature = "observability"))]
pub fn serve_prometheus(_addr: SocketAddr) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
Err("epics-ca-rs built without `observability` feature".into())
}
#[cfg(feature = "otlp")]
pub fn init_otlp(
endpoint: &str,
service_name: &str,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
use opentelemetry::KeyValue;
use opentelemetry::trace::TracerProvider as _;
use opentelemetry_otlp::WithExportConfig;
use opentelemetry_sdk::Resource;
use tracing_subscriber::{EnvFilter, fmt, prelude::*};
let exporter = opentelemetry_otlp::new_exporter()
.tonic()
.with_endpoint(endpoint);
let resource = Resource::new(vec![KeyValue::new(
"service.name",
service_name.to_string(),
)]);
let tracer_provider = opentelemetry_otlp::new_pipeline()
.tracing()
.with_exporter(exporter)
.with_trace_config(opentelemetry_sdk::trace::Config::default().with_resource(resource))
.install_batch(opentelemetry_sdk::runtime::Tokio)?;
let tracer = tracer_provider.tracer("epics-ca-rs");
let otel_layer = tracing_opentelemetry::layer().with_tracer(tracer);
let filter = EnvFilter::try_from_default_env()
.unwrap_or_else(|_| EnvFilter::new("info,epics_ca_rs=debug"));
tracing_subscriber::registry()
.with(filter)
.with(fmt::layer().with_target(false))
.with(otel_layer)
.try_init()
.map_err(|e| format!("tracing init: {e}"))?;
Ok(())
}
#[cfg(not(feature = "otlp"))]
pub fn init_otlp(
_endpoint: &str,
_service_name: &str,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
Err("epics-ca-rs built without `otlp` feature".into())
}
#[cfg(feature = "otlp")]
pub fn init_otlp_from_env() -> Result<bool, Box<dyn std::error::Error + Send + Sync>> {
let endpoint = match std::env::var("OTEL_EXPORTER_OTLP_ENDPOINT") {
Ok(v) if !v.is_empty() => v,
_ => return Ok(false),
};
let service_name =
std::env::var("OTEL_SERVICE_NAME").unwrap_or_else(|_| "epics-ca-rs".to_string());
init_otlp(&endpoint, &service_name)?;
Ok(true)
}
#[cfg(not(feature = "otlp"))]
pub fn init_otlp_from_env() -> Result<bool, Box<dyn std::error::Error + Send + Sync>> {
Ok(false)
}