Skip to content

Commit 2c994be

Browse files
authored
Merge branch 'main' into otel-periodic-reader-remove-timeout
2 parents f5d08a0 + 5e6b3d6 commit 2c994be

File tree

9 files changed

+144
-36
lines changed

9 files changed

+144
-36
lines changed

examples/metrics-advanced/src/main.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,12 @@ fn init_meter_provider() -> opentelemetry_sdk::metrics::SdkMeterProvider {
4949
.with_temporality(Temporality::Delta)
5050
.build();
5151

52-
let reader = PeriodicReader::builder(exporter).build();
53-
5452
let resource = Resource::builder()
5553
.with_service_name("metrics-advanced-example")
5654
.build();
5755

5856
let provider = SdkMeterProvider::builder()
59-
.with_reader(reader)
57+
.with_periodic_exporter(exporter)
6058
.with_resource(resource)
6159
.with_view(my_view_rename_and_unit)
6260
.with_view(my_view_drop_attributes)

examples/metrics-basic/src/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ fn init_meter_provider() -> opentelemetry_sdk::metrics::SdkMeterProvider {
1010
// Build exporter using Delta Temporality (Defaults to Temporality::Cumulative)
1111
// .with_temporality(opentelemetry_sdk::metrics::Temporality::Delta)
1212
.build();
13-
let reader = PeriodicReader::builder(exporter).build();
1413
let provider = SdkMeterProvider::builder()
15-
.with_reader(reader)
14+
.with_periodic_exporter(exporter)
1615
.with_resource(
1716
Resource::builder()
1817
.with_service_name("metrics-basic-example")

opentelemetry-otlp/examples/basic-otlp-http/src/main.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,8 @@ fn init_metrics() -> Result<opentelemetry_sdk::metrics::SdkMeterProvider, Metric
6161
.with_endpoint("http://localhost:4318/v1/metrics")
6262
.build()?;
6363

64-
let reader = opentelemetry_sdk::metrics::PeriodicReader::builder(exporter).build();
65-
6664
Ok(SdkMeterProvider::builder()
67-
.with_reader(reader)
65+
.with_periodic_exporter(exporter)
6866
.with_resource(RESOURCE.clone())
6967
.build())
7068
}

opentelemetry-otlp/examples/basic-otlp/src/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,9 @@ fn init_traces() -> Result<sdktrace::TracerProvider, TraceError> {
3333

3434
fn init_metrics() -> Result<opentelemetry_sdk::metrics::SdkMeterProvider, MetricError> {
3535
let exporter = MetricExporter::builder().with_tonic().build()?;
36-
let reader = PeriodicReader::builder(exporter).build();
3736

3837
Ok(SdkMeterProvider::builder()
39-
.with_reader(reader)
38+
.with_periodic_exporter(exporter)
4039
.with_resource(RESOURCE.clone())
4140
.build())
4241
}

opentelemetry-sdk/CHANGELOG.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,14 +430,33 @@ Released 2024-Nov-27
430430
Migration Guidance:
431431
- These methods are intended for log appenders. Keep the clone of the provider handle, instead of depending on above methods.
432432

433-
434433
- **Bug Fix:** Validates the `with_boundaries` bucket boundaries used in
435434
Histograms. The boundaries provided by the user must not contain `f64::NAN`,
436435
`f64::INFINITY` or `f64::NEG_INFINITY` and must be sorted in strictly
437436
increasing order, and contain no duplicates. Instruments will not record
438437
measurements if the boundaries are invalid.
439438
[#2351](https://github.com/open-telemetry/opentelemetry-rust/pull/2351)
440439

440+
- Added `with_periodic_exporter` method to `MeterProviderBuilder`, allowing
441+
users to easily attach an exporter with a PeriodicReader for automatic metric
442+
export. Retained with_reader() for advanced use cases where a custom
443+
MetricReader configuration is needed.
444+
[2597](https://github.com/open-telemetry/opentelemetry-rust/pull/2597)
445+
Example Usage:
446+
447+
```rust
448+
SdkMeterProvider::builder()
449+
.with_periodic_exporter(exporter)
450+
.build();
451+
```
452+
453+
Using a custom PeriodicReader (advanced use case):
454+
455+
let reader = PeriodicReader::builder(exporter).build();
456+
SdkMeterProvider::builder()
457+
.with_reader(reader)
458+
.build();
459+
441460
## 0.27.0
442461

443462
Released 2024-Nov-11

opentelemetry-sdk/src/logs/log_processor.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -228,19 +228,33 @@ type LogsData = Box<(LogRecord, InstrumentationScope)>;
228228
/// individually. It uses a **dedicated background thread** to manage and export logs
229229
/// asynchronously, ensuring that the application's main execution flow is not blocked.
230230
///
231-
/// - This processor supports the following configurations:
232-
/// - **Queue size**: Maximum number of log records that can be buffered.
233-
/// - **Batch size**: Maximum number of log records to include in a single export.
234-
/// - **Scheduled delay**: Frequency at which the batch is exported.
231+
/// This processor supports the following configurations:
232+
/// - **Queue size**: Maximum number of log records that can be buffered.
233+
/// - **Batch size**: Maximum number of log records to include in a single export.
234+
/// - **Scheduled delay**: Frequency at which the batch is exported.
235235
///
236236
/// When using this processor with the OTLP Exporter, the following exporter
237237
/// features are supported:
238-
/// - `grpc-tonic`: This requires `MeterProvider` to be created within a tokio
239-
/// runtime.
238+
/// - `grpc-tonic`: Requires `LoggerProvider` to be created within a tokio runtime.
240239
/// - `reqwest-blocking-client`: Works with a regular `main` or `tokio::main`.
241240
///
242241
/// In other words, other clients like `reqwest` and `hyper` are not supported.
243242
///
243+
/// `BatchLogProcessor` buffers logs in memory and exports them in batches. An
244+
/// export is triggered when `max_export_batch_size` is reached or every
245+
/// `scheduled_delay` milliseconds. Users can explicitly trigger an export using
246+
/// the `force_flush` method. Shutdown also triggers an export of all buffered
247+
/// logs and is recommended to be called before the application exits to ensure
248+
/// all buffered logs are exported.
249+
///
250+
/// **Warning**: When using tokio's current-thread runtime, `shutdown()`, which
251+
/// is a blocking call ,should not be called from your main thread. This can
252+
/// cause deadlock. Instead, call `shutdown()` from a separate thread or use
253+
/// tokio's `spawn_blocking`.
254+
///
255+
/// [`shutdown()`]: crate::logs::LoggerProvider::shutdown
256+
/// [`force_flush()`]: crate::logs::LoggerProvider::force_flush
257+
///
244258
/// ### Using a BatchLogProcessor:
245259
///
246260
/// ```rust

opentelemetry-sdk/src/metrics/meter_provider.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ use crate::{
1919
};
2020

2121
use super::{
22-
meter::SdkMeter, noop::NoopMeter, pipeline::Pipelines, reader::MetricReader, view::View,
22+
exporter::PushMetricExporter, meter::SdkMeter, noop::NoopMeter, pipeline::Pipelines,
23+
reader::MetricReader, view::View, PeriodicReader,
2324
};
2425

2526
/// Handles the creation and coordination of [Meter]s.
@@ -244,14 +245,37 @@ impl MeterProviderBuilder {
244245
}
245246

246247
/// Associates a [MetricReader] with a [MeterProvider].
248+
/// [`MeterProviderBuilder::with_periodic_exporter()] can be used to add a PeriodicReader which is
249+
/// the most common use case.
247250
///
248-
/// By default, if this option is not used, the [MeterProvider] will perform no
249-
/// operations; no data will be exported without a [MetricReader].
251+
/// A [MeterProvider] will export no metrics without [MetricReader]
252+
/// added.
250253
pub fn with_reader<T: MetricReader>(mut self, reader: T) -> Self {
251254
self.readers.push(Box::new(reader));
252255
self
253256
}
254257

258+
/// Adds a [`PushMetricExporter`] to the [`MeterProvider`] and configures it
259+
/// to export metrics at **fixed** intervals (60 seconds) using a
260+
/// [`PeriodicReader`].
261+
///
262+
/// To customize the export interval, set the
263+
/// **"OTEL_METRIC_EXPORT_INTERVAL"** environment variable (in
264+
/// milliseconds).
265+
///
266+
/// Most users should use this method to attach an exporter. Advanced users
267+
/// who need finer control over the export process can use
268+
/// [`crate::metrics::PeriodicReaderBuilder`] to configure a custom reader and attach it
269+
/// using [`MeterProviderBuilder::with_reader()`].
270+
pub fn with_periodic_exporter<T>(mut self, exporter: T) -> Self
271+
where
272+
T: PushMetricExporter,
273+
{
274+
let reader = PeriodicReader::builder(exporter).build();
275+
self.readers.push(Box::new(reader));
276+
self
277+
}
278+
255279
#[cfg(feature = "spec_unstable_metrics_views")]
256280
/// Associates a [View] with a [MeterProvider].
257281
///

opentelemetry-sdk/src/metrics/periodic_reader.rs

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -64,25 +64,51 @@ where
6464
}
6565
}
6666

67-
/// A [MetricReader] that continuously collects and exports metrics at a set
68-
/// interval.
67+
/// A `MetricReader` that periodically collects and exports metrics at a configurable interval.
6968
///
70-
/// By default, `PeriodicReader` will collect and export metrics every 60
71-
/// seconds. The export time is not counted towards the interval between
72-
/// attempts. `PeriodicReader` itself does not enforce a timeout. Instead, the
73-
/// exporter is supposed to return with result in a configured time.
69+
70+
/// By default, [`PeriodicReader`] collects and exports metrics every **60 seconds**.
71+
/// The time taken for export is **not** included in the interval. Use [`PeriodicReaderBuilder`]
72+
/// to customize the interval.
73+
///
74+
/// [`PeriodicReader`] spawns a background thread to handle metric collection and export.
75+
/// This thread remains active until [`shutdown()`] is called.
76+
///
77+
/// ## Collection Process
78+
/// "Collection" refers to gathering aggregated metrics from the SDK's internal storage.
79+
/// During this phase, callbacks from observable instruments are also triggered.
80+
///
81+
/// [`PeriodicReader`] does **not** enforce a timeout for collection. If an
82+
/// observable callback takes too long, it may delay the next collection cycle.
83+
/// If a callback never returns, it **will stall** all metric collection (and exports)
84+
/// indefinitely.
85+
///
86+
/// ## Exporter Compatibility
87+
/// When used with the [`OTLP Exporter`](https://docs.rs/opentelemetry-otlp), the following
88+
/// transport options are supported:
89+
///
90+
/// - **`grpc-tonic`**: Requires [`MeterProvider`] to be initialized within a `tokio` runtime.
91+
/// - **`reqwest-blocking-client`**: Works with both a standard (`main`) function and `tokio::main`.
92+
///
93+
/// [`PeriodicReader`] does **not** enforce a timeout for exports either. Instead,
94+
/// the configured exporter is responsible for enforcing timeouts. If an export operation
95+
/// never returns, [`PeriodicReader`] will **stop exporting new metrics**, stalling
96+
/// metric collection.
7497
///
75-
/// `PeriodicReader` spawns a background thread to handle the periodic
76-
/// collection and export of metrics. The background thread will continue to run
77-
/// until `shutdown()` is called.
98+
/// ## Manual Export & Shutdown
99+
/// Users can manually trigger an export via [`force_flush()`]. Calling [`shutdown()`]
100+
/// exports any remaining metrics and should be done before application exit to ensure
101+
/// all data is sent.
78102
///
79-
/// When using this reader with the OTLP Exporter, the following exporter
80-
/// features are supported:
81-
/// - `grpc-tonic`: This requires `MeterProvider` to be created within a tokio
82-
/// runtime.
83-
/// - `reqwest-blocking-client`: Works with a regular `main` or `tokio::main`.
103+
/// **Warning**: If using **tokio’s current-thread runtime**, calling [`shutdown()`]
104+
/// from the main thread may cause a deadlock. To prevent this, call [`shutdown()`]
105+
/// from a separate thread or use tokio's `spawn_blocking`.
84106
///
85-
/// In other words, other clients like `reqwest` and `hyper` are not supported.
107+
/// [`PeriodicReader`]: crate::metrics::PeriodicReader
108+
/// [`PeriodicReaderBuilder`]: crate::metrics::PeriodicReaderBuilder
109+
/// [`MeterProvider`]: crate::metrics::SdkMeterProvider
110+
/// [`shutdown()`]: crate::metrics::SdkMeterProvider::shutdown
111+
/// [`force_flush()`]: crate::metrics::SdkMeterProvider::force_flush
86112
///
87113
/// # Example
88114
///

opentelemetry-sdk/src/trace/span_processor.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,38 @@ enum BatchMessage {
252252
SetResource(Arc<Resource>),
253253
}
254254

255-
/// A batch span processor with a dedicated background thread.
255+
/// The `BatchSpanProcessor` collects finished spans in a buffer and exports them
256+
/// in batches to the configured `SpanExporter`. This processor is ideal for
257+
/// high-throughput environments, as it minimizes the overhead of exporting spans
258+
/// individually. It uses a **dedicated background thread** to manage and export spans
259+
/// asynchronously, ensuring that the application's main execution flow is not blocked.
260+
///
261+
/// This processor supports the following configurations:
262+
/// - **Queue size**: Maximum number of spans that can be buffered.
263+
/// - **Batch size**: Maximum number of spans to include in a single export.
264+
/// - **Scheduled delay**: Frequency at which the batch is exported.
265+
///
266+
/// When using this processor with the OTLP Exporter, the following exporter
267+
/// features are supported:
268+
/// - `grpc-tonic`: Requires `TracerProvider` to be created within a tokio runtime.
269+
/// - `reqwest-blocking-client`: Works with a regular `main` or `tokio::main`.
270+
///
271+
/// In other words, other clients like `reqwest` and `hyper` are not supported.
272+
///
273+
/// `BatchSpanProcessor` buffers spans in memory and exports them in batches. An
274+
/// export is triggered when `max_export_batch_size` is reached or every
275+
/// `scheduled_delay` milliseconds. Users can explicitly trigger an export using
276+
/// the `force_flush` method. Shutdown also triggers an export of all buffered
277+
/// spans and is recommended to be called before the application exits to ensure
278+
/// all buffered spans are exported.
279+
///
280+
/// **Warning**: When using tokio's current-thread runtime, `shutdown()`, which
281+
/// is a blocking call ,should not be called from your main thread. This can
282+
/// cause deadlock. Instead, call `shutdown()` from a separate thread or use
283+
/// tokio's `spawn_blocking`.
284+
///
285+
/// [`shutdown()`]: crate::trace::TracerProvider::shutdown
286+
/// [`force_flush()`]: crate::trace::TracerProvider::force_flush
256287
#[derive(Debug)]
257288
pub struct BatchSpanProcessor {
258289
span_sender: SyncSender<SpanData>, // Data channel to store spans

0 commit comments

Comments
 (0)