scouter_tracing/exporter/
traits.rs

1use crate::error::TraceError;
2use crate::exporter::processor::BatchConfig;
3use crate::exporter::processor::EnrichSpanWithBaggageProcessor;
4use crate::exporter::scouter::ScouterSpanExporter;
5use crate::exporter::ExporterType;
6use opentelemetry_sdk::trace::BatchSpanProcessor;
7use opentelemetry_sdk::trace::Sampler;
8use opentelemetry_sdk::trace::SpanExporter;
9use opentelemetry_sdk::Resource;
10use tracing::debug;
11/// Common interface for all span exporter builders
12pub trait SpanExporterBuilder {
13    type Exporter: SpanExporter + 'static;
14
15    fn export_type(&self) -> ExporterType;
16
17    /// Get the sampling ratio for this exporter
18    fn sample_ratio(&self) -> Option<f64>;
19
20    /// Whether to use simple or batch exporter
21    fn batch_export(&self) -> bool;
22
23    /// Build the actual span exporter - this is non-consuming
24    fn build_exporter(&self) -> Result<Self::Exporter, TraceError>;
25
26    /// Convert sample ratio to OpenTelemetry sampler
27    fn to_sampler(&self) -> Sampler {
28        self.sample_ratio()
29            .map(Sampler::TraceIdRatioBased)
30            .unwrap_or(Sampler::AlwaysOn)
31    }
32
33    /// Build a complete tracer provider with both this exporter and a Scouter exporter
34    /// # Arguments
35    /// * `resource` - The resource to associate with the tracer provider
36    /// * `scouter_exporter` - The Scouter span exporter to include
37    /// # Returns
38    /// A fully built `SdkTracerProvider`
39    fn build_provider(
40        &self,
41        resource: Resource,
42        scouter_exporter: ScouterSpanExporter,
43        batch_config: Option<BatchConfig>,
44    ) -> Result<opentelemetry_sdk::trace::SdkTracerProvider, TraceError>
45    where
46        Self: Sized,
47    {
48        let exporter = self.build_exporter()?;
49
50        // if either the exporter or batch_config indicates batch, use batch
51        let use_batch = self.batch_export() || batch_config.is_some();
52        let sampler = self.to_sampler();
53
54        let mut builder = opentelemetry_sdk::trace::SdkTracerProvider::builder()
55            .with_span_processor(EnrichSpanWithBaggageProcessor);
56
57        if use_batch {
58            debug!("Using batch span processor for exporter");
59            let config = batch_config.unwrap_or_default();
60
61            let scouter_batch_processor = BatchSpanProcessor::builder(scouter_exporter)
62                .with_batch_config(config.to_otlp_config())
63                .build();
64            builder = builder.with_span_processor(scouter_batch_processor);
65
66            // only set an exporter if it's not Noop
67            if self.export_type() != ExporterType::Noop {
68                let exporter_batch_processor = BatchSpanProcessor::builder(exporter)
69                    .with_batch_config(config.to_otlp_config())
70                    .build();
71
72                builder = builder.with_span_processor(exporter_batch_processor);
73            }
74        } else {
75            builder = builder.with_simple_exporter(scouter_exporter);
76            if self.export_type() != ExporterType::Noop {
77                builder = builder.with_simple_exporter(exporter);
78            }
79        }
80
81        builder = builder.with_sampler(sampler).with_resource(resource);
82
83        Ok(builder.build())
84    }
85}