use opentelemetry::propagation::TextMapCompositePropagator;
use opentelemetry::propagation::TextMapPropagator;
use opentelemetry_sdk::trace::SdkTracerProvider;
use opentelemetry_sdk::trace::SpanProcessor;
use tower::BoxError;
use crate::plugins::telemetry::CustomTraceIdPropagator;
use crate::plugins::telemetry::config::Conf;
use crate::plugins::telemetry::config::Propagation;
use crate::plugins::telemetry::config::Tracing;
use crate::plugins::telemetry::config::TracingCommon;
use crate::plugins::telemetry::config_new::spans::Spans;
pub(crate) struct TracingBuilder<'a> {
common: &'a TracingCommon,
spans: &'a Spans,
builder: opentelemetry_sdk::trace::TracerProviderBuilder,
}
impl<'a> TracingBuilder<'a> {
pub(crate) fn new(config: &'a Conf) -> Self {
let common = &config.exporters.tracing.common;
Self {
common,
spans: &config.instrumentation.spans,
builder: common.configure_tracer_provider_builder(
opentelemetry_sdk::trace::SdkTracerProvider::builder(),
),
}
}
pub(crate) fn configure<T: TracingConfigurator>(&mut self, config: &T) -> Result<(), BoxError> {
if config.is_enabled() {
return config.configure(self);
}
Ok(())
}
pub(crate) fn tracing_common(&self) -> &TracingCommon {
self.common
}
pub(crate) fn spans(&self) -> &Spans {
self.spans
}
pub(crate) fn with_span_processor<T: SpanProcessor + 'static>(&mut self, span_processor: T) {
let builder = std::mem::take(&mut self.builder);
self.builder = builder.with_span_processor(span_processor);
}
pub(crate) fn build(self) -> SdkTracerProvider {
self.builder.build()
}
}
pub(crate) fn create_propagator(
propagation: &Propagation,
tracing: &Tracing,
) -> TextMapCompositePropagator {
let mut propagators: Vec<Box<dyn TextMapPropagator + Send + Sync + 'static>> = Vec::new();
if tracing.is_jaeger_propagation_enabled() {
propagators.push(Box::<opentelemetry_jaeger_propagator::Propagator>::default());
}
if tracing.is_baggage_propagation_enabled() {
propagators.push(Box::<opentelemetry_sdk::propagation::BaggagePropagator>::default());
}
if tracing.is_trace_context_propagation_enabled() {
propagators.push(Box::<opentelemetry_sdk::propagation::TraceContextPropagator>::default());
}
if tracing.is_zipkin_propagation_enabled() {
propagators.push(Box::<opentelemetry_zipkin::Propagator>::default());
}
if tracing.is_datadog_propagation_enabled() {
if tracing.is_jaeger_propagation_enabled()
|| tracing.is_trace_context_propagation_enabled()
|| tracing.is_zipkin_propagation_enabled()
|| tracing.is_aws_xray_propagation_enabled()
{
if tracing.datadog.enabled && propagation.datadog.unwrap_or(false) {
tracing::warn!(
"if the datadog exporter is enabled and any other propagator except for baggage is enabled, the datadog propagator should be disabled to avoid trace id conflicts"
);
} else if let Some(true) = propagation.datadog {
tracing::warn!(
"datadog propagation should not be used with any other propagator except for baggage to avoid trace id conflicts"
);
} else if propagation.datadog.is_none() {
tracing::warn!(
"datadog propagation should be explicitly disabled if the datadog exporter is enabled and any propagator other than baggage is enabled to avoid trace id conflicts"
);
}
}
propagators.push(Box::<
crate::plugins::telemetry::tracing::datadog_exporter::DatadogPropagator,
>::default());
}
if propagation.aws_xray {
propagators.push(Box::<opentelemetry_aws::trace::XrayPropagator>::default());
}
if let Some(from_request_header) = &propagation.request.header_name {
propagators.push(Box::new(CustomTraceIdPropagator::new(
from_request_header.to_string(),
propagation.request.format.clone(),
)));
}
TextMapCompositePropagator::new(propagators)
}
pub(crate) trait TracingConfigurator {
fn config(conf: &Conf) -> &Self;
fn is_enabled(&self) -> bool;
fn configure(&self, builder: &mut TracingBuilder) -> Result<(), BoxError>;
}