generated from Patagia/template-nix
127 lines
4.2 KiB
Rust
127 lines
4.2 KiB
Rust
|
use anyhow::{anyhow, Result};
|
||
|
use once_cell::sync::Lazy;
|
||
|
use opentelemetry::{trace::TracerProvider as _, KeyValue};
|
||
|
use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge;
|
||
|
use opentelemetry_sdk::{
|
||
|
logs::LoggerProvider,
|
||
|
metrics::{MeterProviderBuilder, PeriodicReader, SdkMeterProvider},
|
||
|
runtime,
|
||
|
trace::{RandomIdGenerator, Sampler, TracerProvider},
|
||
|
Resource,
|
||
|
};
|
||
|
use tracing_opentelemetry::{MetricsLayer, OpenTelemetryLayer};
|
||
|
use tracing_subscriber::layer::SubscriberExt;
|
||
|
use tracing_subscriber::util::SubscriberInitExt;
|
||
|
|
||
|
static RESOURCE: Lazy<Resource> = Lazy::new(|| {
|
||
|
Resource::new(vec![
|
||
|
KeyValue::new(
|
||
|
opentelemetry_semantic_conventions::resource::SERVICE_NAME,
|
||
|
env!("CARGO_PKG_NAME"),
|
||
|
),
|
||
|
KeyValue::new(
|
||
|
opentelemetry_semantic_conventions::resource::SERVICE_VERSION,
|
||
|
env!("CARGO_PKG_VERSION"),
|
||
|
),
|
||
|
])
|
||
|
});
|
||
|
|
||
|
// Construct LoggingProdiver for LoggingLayer
|
||
|
fn init_logging_provider() -> Result<LoggerProvider> {
|
||
|
let exporter = opentelemetry_otlp::LogExporter::builder()
|
||
|
.with_tonic()
|
||
|
.build()?;
|
||
|
let logging_provider: LoggerProvider = LoggerProvider::builder()
|
||
|
.with_resource(RESOURCE.clone())
|
||
|
.with_batch_exporter(exporter, runtime::Tokio)
|
||
|
.build();
|
||
|
Ok(logging_provider)
|
||
|
}
|
||
|
|
||
|
// Construct MeterProvider for MetricsLayer
|
||
|
fn init_meter_provider() -> Result<SdkMeterProvider> {
|
||
|
let exporter = opentelemetry_otlp::MetricExporter::builder()
|
||
|
.with_tonic()
|
||
|
.with_temporality(opentelemetry_sdk::metrics::Temporality::default())
|
||
|
.build()
|
||
|
.map_err(|e| anyhow!("Error creating OTLP metric exporter: {:?}", e))?;
|
||
|
|
||
|
let meter_provider = MeterProviderBuilder::default()
|
||
|
.with_resource(RESOURCE.clone())
|
||
|
.with_reader(
|
||
|
PeriodicReader::builder(exporter, runtime::Tokio)
|
||
|
.with_interval(std::time::Duration::from_secs(10))
|
||
|
.build(),
|
||
|
)
|
||
|
.build();
|
||
|
|
||
|
opentelemetry::global::set_meter_provider(meter_provider.clone());
|
||
|
|
||
|
Ok(meter_provider)
|
||
|
}
|
||
|
|
||
|
// Construct TracerProvider for OpenTelemetryLayer
|
||
|
fn init_tracer_provider() -> Result<TracerProvider> {
|
||
|
let exporter = opentelemetry_otlp::SpanExporter::builder()
|
||
|
.with_tonic()
|
||
|
.build()
|
||
|
.map_err(|e| anyhow!("Error creating OTLP span exporter: {:?}", e))?;
|
||
|
|
||
|
let tracer_provider = opentelemetry_sdk::trace::TracerProvider::builder()
|
||
|
.with_config(
|
||
|
opentelemetry_sdk::trace::Config::default()
|
||
|
.with_sampler(Sampler::ParentBased(Box::new(Sampler::TraceIdRatioBased(
|
||
|
1.0,
|
||
|
))))
|
||
|
.with_id_generator(RandomIdGenerator::default())
|
||
|
.with_resource(RESOURCE.clone()),
|
||
|
)
|
||
|
.with_batch_exporter(exporter, opentelemetry_sdk::runtime::Tokio)
|
||
|
.build();
|
||
|
|
||
|
Ok(tracer_provider)
|
||
|
}
|
||
|
|
||
|
// Initialize tracing-subscriber and return OtelGuard for opentelemetry-related termination processing
|
||
|
pub fn init_tracing_subscriber() -> Result<OtelGuard> {
|
||
|
let logging_provider = init_logging_provider()?;
|
||
|
let meter_provider = init_meter_provider()?;
|
||
|
let tracer_provider = init_tracer_provider()?;
|
||
|
|
||
|
let tracer = tracer_provider.tracer("tracing-otel-subscriber");
|
||
|
|
||
|
tracing_subscriber::registry()
|
||
|
.with(tracing_subscriber::EnvFilter::from_default_env())
|
||
|
.with(tracing_subscriber::fmt::layer())
|
||
|
.with(MetricsLayer::new(meter_provider.clone()))
|
||
|
.with(OpenTelemetryLayer::new(tracer))
|
||
|
.with(OpenTelemetryTracingBridge::new(&logging_provider))
|
||
|
.init();
|
||
|
|
||
|
Ok(OtelGuard {
|
||
|
logging_provider,
|
||
|
meter_provider,
|
||
|
tracer_provider,
|
||
|
})
|
||
|
}
|
||
|
|
||
|
pub struct OtelGuard {
|
||
|
logging_provider: LoggerProvider,
|
||
|
meter_provider: SdkMeterProvider,
|
||
|
tracer_provider: TracerProvider,
|
||
|
}
|
||
|
|
||
|
impl Drop for OtelGuard {
|
||
|
fn drop(&mut self) {
|
||
|
if let Err(err) = self.tracer_provider.shutdown() {
|
||
|
eprintln!("{err:?}");
|
||
|
}
|
||
|
if let Err(err) = self.logging_provider.shutdown() {
|
||
|
eprintln!("{err:?}");
|
||
|
}
|
||
|
if let Err(err) = self.meter_provider.shutdown() {
|
||
|
eprintln!("{err:?}");
|
||
|
}
|
||
|
}
|
||
|
}
|