use opentelemetry::trace::{SpanContext, SpanId, TraceContextExt, TraceFlags, TraceId, TraceState};
use opentelemetry::Context;
use crate::web::context::RequestContext;
pub struct OtelConfig {
pub service_name: &'static str,
pub service_version: &'static str,
pub otlp_endpoint: &'static str,
}
pub fn init_tracer(cfg: &OtelConfig) {
use opentelemetry::KeyValue;
use opentelemetry_otlp::WithExportConfig;
use opentelemetry_sdk::trace::TracerProvider;
use opentelemetry_sdk::Resource;
let resource = Resource::new(vec![
KeyValue::new("service.name", cfg.service_name),
KeyValue::new("service.version", cfg.service_version),
]);
let exporter_result = opentelemetry_otlp::SpanExporter::builder()
.with_tonic()
.with_endpoint(cfg.otlp_endpoint)
.build();
match exporter_result {
Ok(exporter) => {
let provider = TracerProvider::builder()
.with_batch_exporter(exporter, opentelemetry_sdk::runtime::Tokio)
.with_resource(resource)
.build();
opentelemetry::global::set_tracer_provider(provider);
tracing::info!(
endpoint = cfg.otlp_endpoint,
service = cfg.service_name,
"OTLP tracer initialised"
);
}
Err(e) => {
tracing::warn!(
error = %e,
endpoint = cfg.otlp_endpoint,
"OTLP tracer failed to initialise — spans will not be exported"
);
}
}
}
pub fn parent_context_from(ctx: &RequestContext) -> Context {
let parent_span_id = match ctx.parent_span_id() {
Some(bytes) => SpanId::from_bytes(bytes),
None => return Context::current(), };
let span_context = SpanContext::new(
TraceId::from_bytes(ctx.trace_id()),
parent_span_id,
TraceFlags::SAMPLED,
true, TraceState::default(),
);
Context::current().with_remote_span_context(span_context)
}