Skip to content

Commit 61b0125

Browse files
committed
0.28 migration guide and OTLP Example fixes
1 parent 69e7e89 commit 61b0125

File tree

4 files changed

+198
-49
lines changed

4 files changed

+198
-49
lines changed

docs/migration_0.28.md

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# Migration guide from 0.27 to 0.28
2+
3+
OpenTelemetry Rust 0.28 introduces a large number of breaking changes that
4+
impact all signals (logs/metrics/traces). This guide is intended to help with a
5+
smooth migration for the common use cases of using `opentelemetry`,
6+
`opentelemetry_sdk` `opentelemetry-otlp`, `opentelemetry-appender-tracing`
7+
crates. The detailed changelog for each crate that you use can be consulted for
8+
the full set of changes. This doc covers only the common scenario.
9+
10+
## Tracing Shutdown changes
11+
12+
`opentelemetry::global::shutdown_tracer_provider()` is removed. Now, you should
13+
explicitly call shutdown() on the created tracer provider.
14+
15+
Before (0.27):
16+
17+
```rust
18+
opentelemetry::global::shutdown_tracer_provider();
19+
```
20+
21+
• After (0.28):
22+
23+
```rust
24+
let tracer_provider = opentelemetry_sdk::trace::SdkTracerProvider::builder()
25+
.build();
26+
27+
// Clone and set the tracer provider globally. Retain the original to invoke shutdown later.
28+
opentelemetry::global::set_tracer_provider(tracer_provider.clone());
29+
30+
// Shutdown the provider when application is exiting.
31+
tracer_provider.shutdown();
32+
```
33+
34+
This now makes shutdown consistent across signals.
35+
36+
## Rename SDK Structs
37+
38+
`LoggerProvider`, `TracerProvider` are renamed to `SdkLoggerProvider` and
39+
`SdkTracerProvider` respectively. `MeterProvider` was already named
40+
`SdkMeterProvider` and this now ensures consistency across signals.
41+
42+
### Async Runtime Requirements removed
43+
44+
When using OTLP Exporter for Logs, Traces a "batching" exporter is recommended.
45+
Also, metrics always required a component named `PeriodicReader`. These
46+
components previously needed user to pass in an async runtime and enable
47+
appropriate feature flag depending on the runtime.
48+
49+
These components have been re-written to no longer require an async runtime.
50+
Instead they operate by spawning dedicated background thread, and making
51+
blocking calls from the same.
52+
53+
PeriodicReader, BatchSpanProcessor, BatchLogProcessor are the components
54+
affected.
55+
56+
For Logs,Traces replace `.with_batch_exporter(exporter, runtime::Tokio)` with
57+
`.with_batch_exporter(exporter)`. For Metrics, replace `let reader =
58+
PeriodicReader::builder(exporter, runtime::Tokio).build();` with `let reader =
59+
PeriodicReader::builder(exporter).build();` or more conveniently,
60+
`.with_periodic_exporter(exporter)`.
61+
62+
Please note the following:
63+
64+
1. With the new approach, only the following grpc/http clients are supported in
65+
`opentelemetry-otlp`. grpc-tonic, reqwest-blocking-client In other words,
66+
`reqwest` and `hyper` are not supported. If using `grpc-tonic`, the OTLP
67+
Exporter must be created from within a Tokio runtime.
68+
2. Timeout enforcement is now moved to Exporters. i.e
69+
BatchProcessor,PeriodicReader does not enforce timeouts. For logs and traces,
70+
`max_export_timeout` (on Processors) or `OTEL_BLRP_EXPORT_TIMEOUT` or
71+
`OTEL_BSP_EXPORT_TIMEOUT` is no longer supported. For metrics, `with_timeout` on
72+
PeriodicReader is no longer supported.
73+
74+
`OTEL_EXPORTER_OTLP_TIMEOUT` can be used to setup timeout for OTLP Exporters via
75+
environment variables, or `.with_tonic().with_timeout()` or
76+
`.with_http().with_timeout()` programmatically.
77+
78+
If you need the old behavior (your application cannot spawn a new thread, or
79+
need to use another networking client etc.) use appropriate feature flags from
80+
below “experimental_metrics_periodicreader_with_async_runtime”
81+
"experimental_logs_batch_log_processor_with_async_runtime"
82+
"experimental_trace_batch_span_processor_with_async_runtime"
83+
84+
**and** adjust the namespace:
85+
86+
Example, when using Tokio runtime.
87+
88+
```rust
89+
let reader = opentelemetry_sdk::metrics::periodic_reader_with_async_runtime::PeriodicReader::builder(exporter, runtime::Tokio).build();
90+
let tracer_provider = SdkTracerProvider::builder()
91+
.with_span_processor(span_processor_with_async_runtime::BatchSpanProcessor::builder(exporter, runtime::Tokio).build())
92+
.build();
93+
let logger_provider = SdkLoggerProvider::builder()
94+
.with_log_processor(log_processor_with_async_runtime::BatchLogProcessor::builder(exporter, runtime::Tokio).build())
95+
.build();
96+
```
97+
98+
## OTLP Default change
99+
100+
"grpc-tonic" feature flag is no longer enabled by default. "http-proto" and
101+
"reqwest-blocking-client" features are added as default, to align with the
102+
OTel specification.
103+
104+
## Resource Changes
105+
106+
`Resource` creation is moved to a builder pattern, and `Resource::{new, empty,
107+
from_detectors, new_with_defaults, from_schema_url, merge, default}` are
108+
replaced with `Resource::builder()`.
109+
110+
Before:
111+
112+
```rust
113+
Resource::default().with_attributes([
114+
KeyValue::new("service.name", "test_service"),
115+
KeyValue::new("key", "value"),
116+
]);
117+
```
118+
119+
After:
120+
121+
```rust
122+
Resource::builder()
123+
.with_service_name("test_service")
124+
.with_attribute(KeyValue::new("key", "value"))
125+
.build();
126+
```
127+
128+
## Improved internal logging
129+
130+
OpenTelemetry internally used `tracing` to emit its internal logs. This is under
131+
feature-flag "internal-logs" that is enabled by default in all crates. When
132+
using OTel Logging, care must be taken to avoid OTel's own internal log being
133+
fed back to OTel, creating an infinite loop. This can be achieved via proper
134+
filtering. The OTLP Examples in the repo shows how to achieve this. It also
135+
shows how to send OTel's internal logs to stdtout using `tracing::Fmt`.
136+
137+
138+
## Full example
139+
140+
A fully runnable example application using OTLP Exporter is provided in this
141+
repo. Comparing the 0.27 vs 0.28 of the example would give a good overview of
142+
the changes required to be made.
143+
144+
[Basic OTLP Example
145+
(0.27)](https://github.com/open-telemetry/opentelemetry-rust/tree/opentelemetry-otlp-0.27.0/opentelemetry-otlp/examples)
146+
[Basic OTLP Example
147+
(0.28)](https://github.com/open-telemetry/opentelemetry-rust/tree/opentelemetry-otlp-0.28.0/opentelemetry-otlp/examples)
148+
149+
This guide covers only the most common breaking changes. If you’re using custom
150+
exporters or processors (or authoring one), please consult the changelog for
151+
additional migration details.
152+

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

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,15 @@
22
use once_cell::sync::Lazy;
33
use opentelemetry::{
44
global,
5-
trace::{TraceContextExt, TraceError, Tracer},
5+
trace::{TraceContextExt, Tracer},
66
InstrumentationScope, KeyValue,
77
};
88
use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge;
99
use opentelemetry_otlp::WithExportConfig;
1010
use opentelemetry_otlp::{LogExporter, MetricExporter, Protocol, SpanExporter};
11+
use opentelemetry_sdk::Resource;
1112
use opentelemetry_sdk::{
12-
logs::SdkLoggerProvider,
13-
metrics::{MetricError, SdkMeterProvider},
14-
trace::{self as sdktrace, SdkTracerProvider},
15-
};
16-
use opentelemetry_sdk::{
17-
logs::{self as sdklogs},
18-
Resource,
13+
logs::SdkLoggerProvider, metrics::SdkMeterProvider, trace::SdkTracerProvider,
1914
};
2015
use std::error::Error;
2116
use tracing::info;
@@ -28,48 +23,48 @@ static RESOURCE: Lazy<Resource> = Lazy::new(|| {
2823
.build()
2924
});
3025

31-
fn init_logs() -> Result<sdklogs::SdkLoggerProvider, opentelemetry_sdk::logs::LogError> {
26+
fn init_logs() -> SdkLoggerProvider {
3227
let exporter = LogExporter::builder()
3328
.with_http()
34-
.with_endpoint("http://localhost:4318/v1/logs")
3529
.with_protocol(Protocol::HttpBinary)
36-
.build()?;
30+
.build()
31+
.expect("Failed to create log exporter");
3732

38-
Ok(SdkLoggerProvider::builder()
33+
SdkLoggerProvider::builder()
3934
.with_batch_exporter(exporter)
4035
.with_resource(RESOURCE.clone())
41-
.build())
36+
.build()
4237
}
4338

44-
fn init_traces() -> Result<sdktrace::SdkTracerProvider, TraceError> {
39+
fn init_traces() -> SdkTracerProvider {
4540
let exporter = SpanExporter::builder()
4641
.with_http()
4742
.with_protocol(Protocol::HttpBinary) //can be changed to `Protocol::HttpJson` to export in JSON format
48-
.with_endpoint("http://localhost:4318/v1/traces")
49-
.build()?;
43+
.build()
44+
.expect("Failed to create trace exporter");
5045

51-
Ok(SdkTracerProvider::builder()
46+
SdkTracerProvider::builder()
5247
.with_batch_exporter(exporter)
5348
.with_resource(RESOURCE.clone())
54-
.build())
49+
.build()
5550
}
5651

57-
fn init_metrics() -> Result<opentelemetry_sdk::metrics::SdkMeterProvider, MetricError> {
52+
fn init_metrics() -> SdkMeterProvider {
5853
let exporter = MetricExporter::builder()
5954
.with_http()
6055
.with_protocol(Protocol::HttpBinary) //can be changed to `Protocol::HttpJson` to export in JSON format
61-
.with_endpoint("http://localhost:4318/v1/metrics")
62-
.build()?;
56+
.build()
57+
.expect("Failed to create metric exporter");
6358

64-
Ok(SdkMeterProvider::builder()
59+
SdkMeterProvider::builder()
6560
.with_periodic_exporter(exporter)
6661
.with_resource(RESOURCE.clone())
67-
.build())
62+
.build()
6863
}
6964

7065
#[tokio::main]
7166
async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
72-
let logger_provider = init_logs()?;
67+
let logger_provider = init_logs();
7368

7469
// Create a new OpenTelemetryTracingBridge using the above LoggerProvider.
7570
let otel_layer = OpenTelemetryTracingBridge::new(&logger_provider);
@@ -107,10 +102,10 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
107102
.with(fmt_layer)
108103
.init();
109104

110-
let tracer_provider = init_traces()?;
105+
let tracer_provider = init_traces();
111106
global::set_tracer_provider(tracer_provider.clone());
112107

113-
let meter_provider = init_metrics()?;
108+
let meter_provider = init_metrics();
114109
global::set_meter_provider(meter_provider.clone());
115110

116111
let common_scope_attributes = vec![KeyValue::new("scope-key", "scope-value")];

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

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
use once_cell::sync::Lazy;
2-
use opentelemetry::trace::{TraceContextExt, TraceError, Tracer};
2+
use opentelemetry::trace::{TraceContextExt, Tracer};
33
use opentelemetry::KeyValue;
44
use opentelemetry::{global, InstrumentationScope};
55
use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge;
6-
use opentelemetry_otlp::{LogExporter, MetricExporter, SpanExporter, WithExportConfig};
7-
use opentelemetry_sdk::logs::LogError;
6+
use opentelemetry_otlp::{LogExporter, MetricExporter, SpanExporter};
87
use opentelemetry_sdk::logs::SdkLoggerProvider;
9-
use opentelemetry_sdk::metrics::MetricError;
108
use opentelemetry_sdk::metrics::SdkMeterProvider;
11-
use opentelemetry_sdk::{trace as sdktrace, Resource};
9+
use opentelemetry_sdk::trace::SdkTracerProvider;
10+
use opentelemetry_sdk::Resource;
1211
use std::error::Error;
1312
use tracing::info;
1413
use tracing_subscriber::prelude::*;
@@ -20,41 +19,44 @@ static RESOURCE: Lazy<Resource> = Lazy::new(|| {
2019
.build()
2120
});
2221

23-
fn init_traces() -> Result<sdktrace::SdkTracerProvider, TraceError> {
22+
fn init_traces() -> SdkTracerProvider {
2423
let exporter = SpanExporter::builder()
2524
.with_tonic()
26-
.with_endpoint("http://localhost:4317")
27-
.build()?;
28-
Ok(sdktrace::SdkTracerProvider::builder()
25+
.build()
26+
.expect("Failed to create span exporter");
27+
SdkTracerProvider::builder()
2928
.with_resource(RESOURCE.clone())
3029
.with_batch_exporter(exporter)
31-
.build())
30+
.build()
3231
}
3332

34-
fn init_metrics() -> Result<opentelemetry_sdk::metrics::SdkMeterProvider, MetricError> {
35-
let exporter = MetricExporter::builder().with_tonic().build()?;
33+
fn init_metrics() -> SdkMeterProvider {
34+
let exporter = MetricExporter::builder()
35+
.with_tonic()
36+
.build()
37+
.expect("Failed to create metric exporter");
3638

37-
Ok(SdkMeterProvider::builder()
39+
SdkMeterProvider::builder()
3840
.with_periodic_exporter(exporter)
3941
.with_resource(RESOURCE.clone())
40-
.build())
42+
.build()
4143
}
4244

43-
fn init_logs() -> Result<opentelemetry_sdk::logs::SdkLoggerProvider, LogError> {
45+
fn init_logs() -> SdkLoggerProvider {
4446
let exporter = LogExporter::builder()
4547
.with_tonic()
46-
.with_endpoint("http://localhost:4317")
47-
.build()?;
48+
.build()
49+
.expect("Failed to create log exporter");
4850

49-
Ok(SdkLoggerProvider::builder()
51+
SdkLoggerProvider::builder()
5052
.with_resource(RESOURCE.clone())
5153
.with_batch_exporter(exporter)
52-
.build())
54+
.build()
5355
}
5456

5557
#[tokio::main]
5658
async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
57-
let logger_provider = init_logs()?;
59+
let logger_provider = init_logs();
5860

5961
// Create a new OpenTelemetryTracingBridge using the above LoggerProvider.
6062
let otel_layer = OpenTelemetryTracingBridge::new(&logger_provider);
@@ -92,10 +94,10 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
9294
.with(fmt_layer)
9395
.init();
9496

95-
let tracer_provider = init_traces()?;
97+
let tracer_provider = init_traces();
9698
global::set_tracer_provider(tracer_provider.clone());
9799

98-
let meter_provider = init_metrics()?;
100+
let meter_provider = init_metrics();
99101
global::set_meter_provider(meter_provider.clone());
100102

101103
let common_scope_attributes = vec![KeyValue::new("scope-key", "scope-value")];

opentelemetry-sdk/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ let processor = BatchLogProcessor::builder(exporter)
344344
```
345345

346346
- **Breaking**: The `BatchSpanProcessor` no longer supports configuration of `max_export_timeout`
347-
or the `OTEL_BLRP_EXPORT_TIMEOUT` environment variable. Timeout handling is now the
347+
or the `OTEL_BSP_EXPORT_TIMEOUT` environment variable. Timeout handling is now the
348348
responsibility of the exporter.
349349
For example, in the OTLP Span exporter, the export timeout can be configured using:
350350
- The environment variables `OTEL_EXPORTER_OTLP_TIMEOUT` or `OTEL_EXPORTER_OTLP_TRACES_TIMEOUT`.

0 commit comments

Comments
 (0)