opentelemetry_otlp/
span.rs
1use std::fmt::Debug;
6
7use futures_core::future::BoxFuture;
8use opentelemetry::trace::TraceError;
9use opentelemetry_sdk::{
10 self as sdk,
11 export::trace::{ExportResult, SpanData},
12};
13use sdk::runtime::RuntimeChannel;
14
15#[cfg(feature = "grpc-tonic")]
16use crate::exporter::tonic::TonicExporterBuilder;
17
18#[cfg(any(feature = "http-proto", feature = "http-json"))]
19use crate::exporter::http::HttpExporterBuilder;
20
21use crate::{NoExporterConfig, OtlpPipeline};
22
23pub const OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: &str = "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT";
27pub const OTEL_EXPORTER_OTLP_TRACES_TIMEOUT: &str = "OTEL_EXPORTER_OTLP_TRACES_TIMEOUT";
29pub const OTEL_EXPORTER_OTLP_TRACES_COMPRESSION: &str = "OTEL_EXPORTER_OTLP_TRACES_COMPRESSION";
31pub const OTEL_EXPORTER_OTLP_TRACES_HEADERS: &str = "OTEL_EXPORTER_OTLP_TRACES_HEADERS";
36
37impl OtlpPipeline {
38 pub fn tracing(self) -> OtlpTracePipeline<NoExporterConfig> {
40 OtlpTracePipeline {
41 exporter_builder: NoExporterConfig(()),
42 trace_config: None,
43 batch_config: None,
44 }
45 }
46}
47
48#[derive(Debug)]
56pub struct OtlpTracePipeline<EB> {
57 exporter_builder: EB,
58 trace_config: Option<sdk::trace::Config>,
59 batch_config: Option<sdk::trace::BatchConfig>,
60}
61
62impl<EB> OtlpTracePipeline<EB> {
63 pub fn with_trace_config(mut self, trace_config: sdk::trace::Config) -> Self {
65 self.trace_config = Some(trace_config);
66 self
67 }
68
69 pub fn with_batch_config(mut self, batch_config: sdk::trace::BatchConfig) -> Self {
71 self.batch_config = Some(batch_config);
72 self
73 }
74}
75
76impl OtlpTracePipeline<NoExporterConfig> {
77 pub fn with_exporter<B: Into<SpanExporterBuilder>>(
85 self,
86 pipeline: B,
87 ) -> OtlpTracePipeline<SpanExporterBuilder> {
88 OtlpTracePipeline {
89 exporter_builder: pipeline.into(),
90 trace_config: self.trace_config,
91 batch_config: self.batch_config,
92 }
93 }
94}
95
96impl OtlpTracePipeline<SpanExporterBuilder> {
97 pub fn install_simple(self) -> Result<sdk::trace::TracerProvider, TraceError> {
103 Ok(build_simple_with_exporter(
104 self.exporter_builder.build_span_exporter()?,
105 self.trace_config,
106 ))
107 }
108
109 pub fn install_batch<R: RuntimeChannel>(
118 self,
119 runtime: R,
120 ) -> Result<sdk::trace::TracerProvider, TraceError> {
121 Ok(build_batch_with_exporter(
122 self.exporter_builder.build_span_exporter()?,
123 self.trace_config,
124 runtime,
125 self.batch_config,
126 ))
127 }
128}
129
130fn build_simple_with_exporter(
131 exporter: SpanExporter,
132 trace_config: Option<sdk::trace::Config>,
133) -> sdk::trace::TracerProvider {
134 let mut provider_builder = sdk::trace::TracerProvider::builder().with_simple_exporter(exporter);
135 if let Some(config) = trace_config {
136 provider_builder = provider_builder.with_config(config);
137 }
138
139 provider_builder.build()
140}
141
142fn build_batch_with_exporter<R: RuntimeChannel>(
143 exporter: SpanExporter,
144 trace_config: Option<sdk::trace::Config>,
145 runtime: R,
146 batch_config: Option<sdk::trace::BatchConfig>,
147) -> sdk::trace::TracerProvider {
148 let mut provider_builder = sdk::trace::TracerProvider::builder();
149 let batch_processor = sdk::trace::BatchSpanProcessor::builder(exporter, runtime)
150 .with_batch_config(batch_config.unwrap_or_default())
151 .build();
152 provider_builder = provider_builder.with_span_processor(batch_processor);
153
154 if let Some(config) = trace_config {
155 provider_builder = provider_builder.with_config(config);
156 }
157 provider_builder.build()
158}
159
160#[derive(Debug)]
162#[allow(clippy::large_enum_variant)]
165#[non_exhaustive]
166pub enum SpanExporterBuilder {
167 #[cfg(feature = "grpc-tonic")]
169 Tonic(TonicExporterBuilder),
170 #[cfg(any(feature = "http-proto", feature = "http-json"))]
172 Http(HttpExporterBuilder),
173}
174
175impl SpanExporterBuilder {
176 pub fn build_span_exporter(self) -> Result<SpanExporter, TraceError> {
178 match self {
179 #[cfg(feature = "grpc-tonic")]
180 SpanExporterBuilder::Tonic(builder) => builder.build_span_exporter(),
181 #[cfg(any(feature = "http-proto", feature = "http-json"))]
182 SpanExporterBuilder::Http(builder) => builder.build_span_exporter(),
183 }
184 }
185}
186
187#[cfg(feature = "grpc-tonic")]
188impl From<TonicExporterBuilder> for SpanExporterBuilder {
189 fn from(exporter: TonicExporterBuilder) -> Self {
190 SpanExporterBuilder::Tonic(exporter)
191 }
192}
193
194#[cfg(any(feature = "http-proto", feature = "http-json"))]
195impl From<HttpExporterBuilder> for SpanExporterBuilder {
196 fn from(exporter: HttpExporterBuilder) -> Self {
197 SpanExporterBuilder::Http(exporter)
198 }
199}
200
201#[derive(Debug)]
203pub struct SpanExporter(Box<dyn opentelemetry_sdk::export::trace::SpanExporter>);
204
205impl SpanExporter {
206 pub fn new(client: impl opentelemetry_sdk::export::trace::SpanExporter + 'static) -> Self {
208 SpanExporter(Box::new(client))
209 }
210}
211
212impl opentelemetry_sdk::export::trace::SpanExporter for SpanExporter {
213 fn export(&mut self, batch: Vec<SpanData>) -> BoxFuture<'static, ExportResult> {
214 self.0.export(batch)
215 }
216
217 fn set_resource(&mut self, resource: &opentelemetry_sdk::Resource) {
218 self.0.set_resource(resource);
219 }
220}