opentelemetry_otlp/
span.rs

1//! # OTLP - Span Exporter
2//!
3//! Defines a [SpanExporter] to send trace data via the OpenTelemetry Protocol (OTLP)
4
5use std::fmt::Debug;
6
7use opentelemetry_sdk::error::OTelSdkResult;
8use opentelemetry_sdk::trace::SpanData;
9
10use crate::ExporterBuildError;
11#[cfg(feature = "grpc-tonic")]
12use crate::{
13    exporter::tonic::{HasTonicConfig, TonicExporterBuilder},
14    TonicExporterBuilderSet,
15};
16
17#[cfg(any(feature = "http-proto", feature = "http-json"))]
18use crate::{
19    exporter::http::{HasHttpConfig, HttpExporterBuilder},
20    HttpExporterBuilderSet,
21};
22
23use crate::{exporter::HasExportConfig, NoExporterBuilderSet};
24
25/// Target to which the exporter is going to send spans, defaults to https://localhost:4317/v1/traces.
26/// Learn about the relationship between this constant and default/metrics/logs at
27/// <https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#endpoint-urls-for-otlphttp>
28pub const OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: &str = "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT";
29/// Max waiting time for the backend to process each spans batch, defaults to 10s.
30pub const OTEL_EXPORTER_OTLP_TRACES_TIMEOUT: &str = "OTEL_EXPORTER_OTLP_TRACES_TIMEOUT";
31/// Compression algorithm to use, defaults to none.
32pub const OTEL_EXPORTER_OTLP_TRACES_COMPRESSION: &str = "OTEL_EXPORTER_OTLP_TRACES_COMPRESSION";
33/// Key-value pairs to be used as headers associated with gRPC or HTTP requests
34/// for sending spans.
35/// Example: `k1=v1,k2=v2`
36/// Note: this is only supported for HTTP.
37pub const OTEL_EXPORTER_OTLP_TRACES_HEADERS: &str = "OTEL_EXPORTER_OTLP_TRACES_HEADERS";
38
39#[derive(Debug, Default, Clone)]
40pub struct SpanExporterBuilder<C> {
41    client: C,
42}
43
44impl SpanExporterBuilder<NoExporterBuilderSet> {
45    pub fn new() -> Self {
46        SpanExporterBuilder::default()
47    }
48
49    #[cfg(feature = "grpc-tonic")]
50    pub fn with_tonic(self) -> SpanExporterBuilder<TonicExporterBuilderSet> {
51        SpanExporterBuilder {
52            client: TonicExporterBuilderSet(TonicExporterBuilder::default()),
53        }
54    }
55
56    #[cfg(any(feature = "http-proto", feature = "http-json"))]
57    pub fn with_http(self) -> SpanExporterBuilder<HttpExporterBuilderSet> {
58        SpanExporterBuilder {
59            client: HttpExporterBuilderSet(HttpExporterBuilder::default()),
60        }
61    }
62}
63
64#[cfg(feature = "grpc-tonic")]
65impl SpanExporterBuilder<TonicExporterBuilderSet> {
66    pub fn build(self) -> Result<SpanExporter, ExporterBuildError> {
67        let span_exporter = self.client.0.build_span_exporter()?;
68        opentelemetry::otel_debug!(name: "SpanExporterBuilt");
69        Ok(span_exporter)
70    }
71}
72
73#[cfg(any(feature = "http-proto", feature = "http-json"))]
74impl SpanExporterBuilder<HttpExporterBuilderSet> {
75    pub fn build(self) -> Result<SpanExporter, ExporterBuildError> {
76        let span_exporter = self.client.0.build_span_exporter()?;
77        Ok(span_exporter)
78    }
79}
80
81#[cfg(feature = "grpc-tonic")]
82impl HasExportConfig for SpanExporterBuilder<TonicExporterBuilderSet> {
83    fn export_config(&mut self) -> &mut crate::ExportConfig {
84        &mut self.client.0.exporter_config
85    }
86}
87
88#[cfg(any(feature = "http-proto", feature = "http-json"))]
89impl HasExportConfig for SpanExporterBuilder<HttpExporterBuilderSet> {
90    fn export_config(&mut self) -> &mut crate::ExportConfig {
91        &mut self.client.0.exporter_config
92    }
93}
94
95#[cfg(feature = "grpc-tonic")]
96impl HasTonicConfig for SpanExporterBuilder<TonicExporterBuilderSet> {
97    fn tonic_config(&mut self) -> &mut crate::TonicConfig {
98        &mut self.client.0.tonic_config
99    }
100}
101
102#[cfg(any(feature = "http-proto", feature = "http-json"))]
103impl HasHttpConfig for SpanExporterBuilder<HttpExporterBuilderSet> {
104    fn http_client_config(&mut self) -> &mut crate::exporter::http::HttpConfig {
105        &mut self.client.0.http_config
106    }
107}
108
109/// OTLP exporter that sends tracing data
110#[derive(Debug)]
111pub struct SpanExporter {
112    client: SupportedTransportClient,
113}
114
115#[derive(Debug)]
116enum SupportedTransportClient {
117    #[cfg(feature = "grpc-tonic")]
118    Tonic(crate::exporter::tonic::trace::TonicTracesClient),
119    #[cfg(any(feature = "http-proto", feature = "http-json"))]
120    Http(crate::exporter::http::OtlpHttpClient),
121}
122
123impl SpanExporter {
124    /// Obtain a builder to configure a [SpanExporter].
125    pub fn builder() -> SpanExporterBuilder<NoExporterBuilderSet> {
126        SpanExporterBuilder::default()
127    }
128
129    #[cfg(any(feature = "http-proto", feature = "http-json"))]
130    pub(crate) fn from_http(client: crate::exporter::http::OtlpHttpClient) -> Self {
131        SpanExporter {
132            client: SupportedTransportClient::Http(client),
133        }
134    }
135
136    #[cfg(feature = "grpc-tonic")]
137    pub(crate) fn from_tonic(client: crate::exporter::tonic::trace::TonicTracesClient) -> Self {
138        SpanExporter {
139            client: SupportedTransportClient::Tonic(client),
140        }
141    }
142}
143
144impl opentelemetry_sdk::trace::SpanExporter for SpanExporter {
145    async fn export(&self, batch: Vec<SpanData>) -> OTelSdkResult {
146        match &self.client {
147            #[cfg(feature = "grpc-tonic")]
148            SupportedTransportClient::Tonic(client) => client.export(batch).await,
149            #[cfg(any(feature = "http-proto", feature = "http-json"))]
150            SupportedTransportClient::Http(client) => client.export(batch).await,
151        }
152    }
153
154    fn set_resource(&mut self, resource: &opentelemetry_sdk::Resource) {
155        match &mut self.client {
156            #[cfg(feature = "grpc-tonic")]
157            SupportedTransportClient::Tonic(client) => client.set_resource(resource),
158            #[cfg(any(feature = "http-proto", feature = "http-json"))]
159            SupportedTransportClient::Http(client) => client.set_resource(resource),
160        }
161    }
162}