Skip to content

Commit 16a866e

Browse files
authored
feat: force user to add exporter builder pipeline. (#1272)
feat: force user to add exporter builder pipeline. Currently, when users don't configure a builder pipeline. We will throw a runtime error. This change force user to call `with_exporter` before building exporters or installing pipeline and eliminate the `NoExporterBuilder` error
1 parent bea0aa5 commit 16a866e

File tree

6 files changed

+99
-82
lines changed

6 files changed

+99
-82
lines changed

opentelemetry-otlp/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
- Bump MSRV to 1.64 [#1203](https://github.com/open-telemetry/opentelemetry-rust/pull/1203)
1313
- Changed dependency from `opentelemetry_api` to `opentelemetry` as the latter
1414
is now the API crate. [#1226](https://github.com/open-telemetry/opentelemetry-rust/pull/1226)
15+
- Make `NoExporterBuilder` a compiling time error [#1271](https://github.com/open-telemetry/opentelemetry-rust/pull/1271)
1516

1617
## v0.13.0
1718

opentelemetry-otlp/src/lib.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -366,10 +366,6 @@ pub enum Error {
366366
#[error("the lock of the {0} has been poisoned")]
367367
PoisonedLock(&'static str),
368368

369-
/// The pipeline will need a exporter to complete setup. Throw this error if none is provided.
370-
#[error("no exporter builder is provided, please provide one using with_exporter() method")]
371-
NoExporterBuilder,
372-
373369
/// Unsupported compression algorithm.
374370
#[error("unsupported compression algorithm '{0}'")]
375371
UnsupportedCompressionAlgorithm(String),
@@ -408,3 +404,8 @@ pub enum Protocol {
408404
/// HTTP protocol with binary protobuf
409405
HttpBinary,
410406
}
407+
408+
#[derive(Debug, Default)]
409+
#[doc(hidden)]
410+
/// Placeholder type when no exporter pipeline has been configured in telemetry pipeline.
411+
pub struct NoExporterConfig(());

opentelemetry-otlp/src/logs.rs

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::exporter::grpcio::GrpcioExporterBuilder;
1111
#[cfg(feature = "http-proto")]
1212
use crate::exporter::http::HttpExporterBuilder;
1313

14-
use crate::OtlpPipeline;
14+
use crate::{NoExporterConfig, OtlpPipeline};
1515
use async_trait::async_trait;
1616
use std::{borrow::Cow, fmt::Debug};
1717

@@ -32,8 +32,11 @@ pub const OTEL_EXPORTER_OTLP_LOGS_TIMEOUT: &str = "OTEL_EXPORTER_OTLP_LOGS_TIMEO
3232

3333
impl OtlpPipeline {
3434
/// Create a OTLP logging pipeline.
35-
pub fn logging(self) -> OtlpLogPipeline {
36-
OtlpLogPipeline::default()
35+
pub fn logging(self) -> OtlpLogPipeline<NoExporterConfig> {
36+
OtlpLogPipeline {
37+
log_config: None,
38+
exporter_builder: NoExporterConfig(()),
39+
}
3740
}
3841
}
3942

@@ -51,11 +54,6 @@ pub enum LogExporterBuilder {
5154
/// Http log exporter builder
5255
#[cfg(feature = "http-proto")]
5356
Http(HttpExporterBuilder),
54-
55-
/// Missing exporter builder
56-
#[doc(hidden)]
57-
#[cfg(not(any(feature = "http-proto", feature = "grpc-sys", feature = "grpc-tonic")))]
58-
Unconfigured,
5957
}
6058

6159
impl LogExporterBuilder {
@@ -68,10 +66,6 @@ impl LogExporterBuilder {
6866
LogExporterBuilder::Grpcio(builder) => builder.build_log_exporter(),
6967
#[cfg(feature = "http-proto")]
7068
LogExporterBuilder::Http(builder) => builder.build_log_exporter(),
71-
#[cfg(not(any(feature = "http-proto", feature = "grpc-sys", feature = "grpc-tonic")))]
72-
LogExporterBuilder::Unconfigured => {
73-
Err(LogError::Other("no configured span exporter".into()))
74-
}
7569
}
7670
}
7771
}
@@ -120,35 +114,42 @@ impl opentelemetry_sdk::export::logs::LogExporter for LogExporter {
120114
}
121115

122116
/// Recommended configuration for an OTLP exporter pipeline.
123-
#[derive(Default, Debug)]
124-
pub struct OtlpLogPipeline {
125-
exporter_builder: Option<LogExporterBuilder>,
117+
#[derive(Debug)]
118+
pub struct OtlpLogPipeline<EB> {
119+
exporter_builder: EB,
126120
log_config: Option<opentelemetry_sdk::logs::Config>,
127121
}
128122

129-
impl OtlpLogPipeline {
130-
/// Set the OTLP log exporter builder.
131-
pub fn with_exporter<B: Into<LogExporterBuilder>>(mut self, pipeline: B) -> Self {
132-
self.exporter_builder = Some(pipeline.into());
133-
self
134-
}
135-
123+
impl<EB> OtlpLogPipeline<EB> {
136124
/// Set the log provider configuration.
137125
pub fn with_log_config(mut self, log_config: opentelemetry_sdk::logs::Config) -> Self {
138126
self.log_config = Some(log_config);
139127
self
140128
}
129+
}
130+
131+
impl OtlpLogPipeline<NoExporterConfig> {
132+
/// Set the OTLP log exporter builder.
133+
pub fn with_exporter<B: Into<LogExporterBuilder>>(
134+
self,
135+
pipeline: B,
136+
) -> OtlpLogPipeline<LogExporterBuilder> {
137+
OtlpLogPipeline {
138+
exporter_builder: pipeline.into(),
139+
log_config: self.log_config,
140+
}
141+
}
142+
}
141143

144+
impl OtlpLogPipeline<LogExporterBuilder> {
142145
/// Install the configured log exporter.
143146
///
144147
/// Returns a [`Logger`] with the name `opentelemetry-otlp` and the current crate version.
145148
///
146149
/// [`Logger`]: opentelemetry_sdk::logs::Logger
147150
pub fn install_simple(self) -> Result<opentelemetry_sdk::logs::Logger, LogError> {
148151
Ok(build_simple_with_exporter(
149-
self.exporter_builder
150-
.ok_or(crate::Error::NoExporterBuilder)?
151-
.build_log_exporter()?,
152+
self.exporter_builder.build_log_exporter()?,
152153
self.log_config,
153154
))
154155
}
@@ -164,9 +165,7 @@ impl OtlpLogPipeline {
164165
runtime: R,
165166
) -> Result<opentelemetry_sdk::logs::Logger, LogError> {
166167
Ok(build_batch_with_exporter(
167-
self.exporter_builder
168-
.ok_or(crate::Error::NoExporterBuilder)?
169-
.build_log_exporter()?,
168+
self.exporter_builder.build_log_exporter()?,
170169
self.log_config,
171170
runtime,
172171
))

opentelemetry-otlp/src/metric.rs

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! Defines a [MetricsExporter] to send metric data to backend via OTEL protocol.
44
//!
55
6-
use crate::{Error, OtlpPipeline};
6+
use crate::{NoExporterConfig, OtlpPipeline};
77
use async_trait::async_trait;
88
use core::fmt;
99
use opentelemetry::{global, metrics::Result};
@@ -42,15 +42,15 @@ pub const OTEL_EXPORTER_OTLP_METRICS_TIMEOUT: &str = "OTEL_EXPORTER_OTLP_METRICS
4242
pub const OTEL_EXPORTER_OTLP_METRICS_COMPRESSION: &str = "OTEL_EXPORTER_OTLP_METRICS_COMPRESSION";
4343
impl OtlpPipeline {
4444
/// Create a OTLP metrics pipeline.
45-
pub fn metrics<RT>(self, rt: RT) -> OtlpMetricPipeline<RT>
45+
pub fn metrics<RT>(self, rt: RT) -> OtlpMetricPipeline<RT, NoExporterConfig>
4646
where
4747
RT: Runtime,
4848
{
4949
OtlpMetricPipeline {
5050
rt,
5151
aggregator_selector: None,
5252
temporality_selector: None,
53-
exporter_pipeline: None,
53+
exporter_pipeline: NoExporterConfig(()),
5454
resource: None,
5555
period: None,
5656
timeout: None,
@@ -129,17 +129,17 @@ impl From<HttpExporterBuilder> for MetricsExporterBuilder {
129129
///
130130
/// Note that currently the OTLP metrics exporter only supports tonic as it's grpc layer and tokio as
131131
/// runtime.
132-
pub struct OtlpMetricPipeline<RT> {
132+
pub struct OtlpMetricPipeline<RT, EB> {
133133
rt: RT,
134134
aggregator_selector: Option<Box<dyn AggregationSelector>>,
135135
temporality_selector: Option<Box<dyn TemporalitySelector>>,
136-
exporter_pipeline: Option<MetricsExporterBuilder>,
136+
exporter_pipeline: EB,
137137
resource: Option<Resource>,
138138
period: Option<time::Duration>,
139139
timeout: Option<time::Duration>,
140140
}
141141

142-
impl<RT> OtlpMetricPipeline<RT>
142+
impl<RT, EB> OtlpMetricPipeline<RT, EB>
143143
where
144144
RT: Runtime,
145145
{
@@ -151,14 +151,6 @@ where
151151
}
152152
}
153153

154-
/// Build with the exporter
155-
pub fn with_exporter<B: Into<MetricsExporterBuilder>>(self, pipeline: B) -> Self {
156-
OtlpMetricPipeline {
157-
exporter_pipeline: Some(pipeline.into()),
158-
..self
159-
}
160-
}
161-
162154
/// Build with timeout
163155
pub fn with_timeout(self, timeout: time::Duration) -> Self {
164156
OtlpMetricPipeline {
@@ -190,18 +182,41 @@ where
190182
..self
191183
}
192184
}
185+
}
186+
187+
impl<RT> OtlpMetricPipeline<RT, NoExporterConfig>
188+
where
189+
RT: Runtime,
190+
{
191+
/// Build with the exporter
192+
pub fn with_exporter<B: Into<MetricsExporterBuilder>>(
193+
self,
194+
pipeline: B,
195+
) -> OtlpMetricPipeline<RT, MetricsExporterBuilder> {
196+
OtlpMetricPipeline {
197+
exporter_pipeline: pipeline.into(),
198+
rt: self.rt,
199+
aggregator_selector: self.aggregator_selector,
200+
temporality_selector: self.temporality_selector,
201+
resource: self.resource,
202+
period: self.period,
203+
timeout: self.timeout,
204+
}
205+
}
206+
}
193207

208+
impl<RT> OtlpMetricPipeline<RT, MetricsExporterBuilder>
209+
where
210+
RT: Runtime,
211+
{
194212
/// Build MeterProvider
195213
pub fn build(self) -> Result<MeterProvider> {
196-
let exporter = self
197-
.exporter_pipeline
198-
.ok_or(Error::NoExporterBuilder)?
199-
.build_metrics_exporter(
200-
self.temporality_selector
201-
.unwrap_or_else(|| Box::new(DefaultTemporalitySelector::new())),
202-
self.aggregator_selector
203-
.unwrap_or_else(|| Box::new(DefaultAggregationSelector::new())),
204-
)?;
214+
let exporter = self.exporter_pipeline.build_metrics_exporter(
215+
self.temporality_selector
216+
.unwrap_or_else(|| Box::new(DefaultTemporalitySelector::new())),
217+
self.aggregator_selector
218+
.unwrap_or_else(|| Box::new(DefaultAggregationSelector::new())),
219+
)?;
205220

206221
let mut builder = PeriodicReader::builder(exporter, self.rt);
207222

@@ -228,7 +243,7 @@ where
228243
}
229244
}
230245

231-
impl<RT> fmt::Debug for OtlpMetricPipeline<RT> {
246+
impl<RT, EB: Debug> Debug for OtlpMetricPipeline<RT, EB> {
232247
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
233248
f.debug_struct("OtlpMetricPipeline")
234249
.field("exporter_pipeline", &self.exporter_pipeline)

opentelemetry-otlp/src/span.rs

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::exporter::grpcio::GrpcioExporterBuilder;
2626
#[cfg(feature = "http-proto")]
2727
use crate::exporter::http::HttpExporterBuilder;
2828

29-
use crate::OtlpPipeline;
29+
use crate::{NoExporterConfig, OtlpPipeline};
3030

3131
/// Target to which the exporter is going to send spans, defaults to https://localhost:4317/v1/traces.
3232
/// Learn about the relationship between this constant and default/metrics/logs at
@@ -39,8 +39,12 @@ pub const OTEL_EXPORTER_OTLP_TRACES_COMPRESSION: &str = "OTEL_EXPORTER_OTLP_TRAC
3939

4040
impl OtlpPipeline {
4141
/// Create a OTLP tracing pipeline.
42-
pub fn tracing(self) -> OtlpTracePipeline {
43-
OtlpTracePipeline::default()
42+
pub fn tracing(self) -> OtlpTracePipeline<NoExporterConfig> {
43+
OtlpTracePipeline {
44+
exporter_builder: NoExporterConfig(()),
45+
trace_config: None,
46+
batch_config: None,
47+
}
4448
}
4549
}
4650

@@ -51,14 +55,14 @@ impl OtlpPipeline {
5155
/// ```no_run
5256
/// let tracing_pipeline = opentelemetry_otlp::new_pipeline().tracing();
5357
/// ```
54-
#[derive(Default, Debug)]
55-
pub struct OtlpTracePipeline {
56-
exporter_builder: Option<SpanExporterBuilder>,
58+
#[derive(Debug)]
59+
pub struct OtlpTracePipeline<EB> {
60+
exporter_builder: EB,
5761
trace_config: Option<sdk::trace::Config>,
5862
batch_config: Option<sdk::trace::BatchConfig>,
5963
}
6064

61-
impl OtlpTracePipeline {
65+
impl<EB> OtlpTracePipeline<EB> {
6266
/// Set the trace provider configuration.
6367
pub fn with_trace_config(mut self, trace_config: sdk::trace::Config) -> Self {
6468
self.trace_config = Some(trace_config);
@@ -70,29 +74,37 @@ impl OtlpTracePipeline {
7074
self.batch_config = Some(batch_config);
7175
self
7276
}
77+
}
7378

79+
impl OtlpTracePipeline<NoExporterConfig> {
7480
/// Set the OTLP span exporter builder.
7581
///
7682
/// Note that the pipeline will not build the exporter until [`install_batch`] or [`install_simple`]
7783
/// is called.
7884
///
7985
/// [`install_batch`]: OtlpTracePipeline::install_batch
8086
/// [`install_simple`]: OtlpTracePipeline::install_simple
81-
pub fn with_exporter<B: Into<SpanExporterBuilder>>(mut self, pipeline: B) -> Self {
82-
self.exporter_builder = Some(pipeline.into());
83-
self
87+
pub fn with_exporter<B: Into<SpanExporterBuilder>>(
88+
self,
89+
pipeline: B,
90+
) -> OtlpTracePipeline<SpanExporterBuilder> {
91+
OtlpTracePipeline {
92+
exporter_builder: pipeline.into(),
93+
trace_config: self.trace_config,
94+
batch_config: self.batch_config,
95+
}
8496
}
97+
}
8598

99+
impl OtlpTracePipeline<SpanExporterBuilder> {
86100
/// Install the configured span exporter.
87101
///
88102
/// Returns a [`Tracer`] with the name `opentelemetry-otlp` and current crate version.
89103
///
90104
/// [`Tracer`]: opentelemetry::trace::Tracer
91105
pub fn install_simple(self) -> Result<sdk::trace::Tracer, TraceError> {
92106
Ok(build_simple_with_exporter(
93-
self.exporter_builder
94-
.ok_or(crate::Error::NoExporterBuilder)?
95-
.build_span_exporter()?,
107+
self.exporter_builder.build_span_exporter()?,
96108
self.trace_config,
97109
))
98110
}
@@ -110,9 +122,7 @@ impl OtlpTracePipeline {
110122
runtime: R,
111123
) -> Result<sdk::trace::Tracer, TraceError> {
112124
Ok(build_batch_with_exporter(
113-
self.exporter_builder
114-
.ok_or(crate::Error::NoExporterBuilder)?
115-
.build_span_exporter()?,
125+
self.exporter_builder.build_span_exporter()?,
116126
self.trace_config,
117127
runtime,
118128
self.batch_config,
@@ -181,11 +191,6 @@ pub enum SpanExporterBuilder {
181191
/// Http span exporter builder
182192
#[cfg(feature = "http-proto")]
183193
Http(HttpExporterBuilder),
184-
185-
/// Missing exporter builder
186-
#[doc(hidden)]
187-
#[cfg(not(any(feature = "http-proto", feature = "grpc-sys", feature = "grpc-tonic")))]
188-
Unconfigured,
189194
}
190195

191196
impl SpanExporterBuilder {
@@ -198,10 +203,6 @@ impl SpanExporterBuilder {
198203
SpanExporterBuilder::Grpcio(builder) => builder.build_span_exporter(),
199204
#[cfg(feature = "http-proto")]
200205
SpanExporterBuilder::Http(builder) => builder.build_span_exporter(),
201-
#[cfg(not(any(feature = "http-proto", feature = "grpc-sys", feature = "grpc-tonic")))]
202-
SpanExporterBuilder::Unconfigured => {
203-
Err(TraceError::Other("no configured span exporter".into()))
204-
}
205206
}
206207
}
207208
}

opentelemetry-sdk/src/metrics/meter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl Meter {
6060
let view_cache = Default::default();
6161

6262
Meter {
63-
scope: scope.clone(),
63+
scope,
6464
pipes: Arc::clone(&pipes),
6565
u64_resolver: Resolver::new(Arc::clone(&pipes), Arc::clone(&view_cache)),
6666
i64_resolver: Resolver::new(Arc::clone(&pipes), Arc::clone(&view_cache)),

0 commit comments

Comments
 (0)