Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions examples/env-var-propagation/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "env-var-propagation"
version = "0.1.0"
edition = "2021"
license = "Apache-2.0"
rust-version = "1.75.0"
publish = false
autobenches = false

[[bin]]
name = "env-var-propagation"
path = "src/main.rs"
doc = false
bench = false

[dependencies]
opentelemetry = { workspace = true, features = ["trace", "otel_unstable"] }
opentelemetry_sdk = { workspace = true, features = ["trace"] }
opentelemetry-stdout = { workspace = true, features = ["trace"] }
35 changes: 35 additions & 0 deletions examples/env-var-propagation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Environment Variable Propagation Example

This example demonstrates distributed tracing across a parent process and a
child process using environment variables as the propagation carrier.

## What This Example Does

1. The parent process configures the W3C `TraceContextPropagator` and starts a
root span.
2. The parent injects that span context into an `EnvVarInjector`, then passes
the resulting environment variables to a child process. The child inherits
the rest of the parent's environment through `std::process::Command`.
3. The child process builds an `EnvVarExtractor` from the active propagator's
fields, extracts the propagated context, and starts its own span as a child
of the parent's span.

The example prints the parent's `TraceId` and `SpanId`, then prints the child's
`TraceId` and remote parent `SpanId` so you can see that the trace was
propagated across the process boundary.

## Usage

From `examples/env-var-propagation`, run:

```shell
cargo run
```

The output should show:

- the parent and child spans sharing the same `TraceId`
- the child's reported `parent_span_id` matching the parent's `span_id`

Both processes also export their spans to stdout using the OpenTelemetry stdout
exporter.
93 changes: 93 additions & 0 deletions examples/env-var-propagation/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use opentelemetry::{
global,
propagation::{EnvVarExtractor, EnvVarInjector},
trace::{Span, TraceContextExt, Tracer},
Context,
};
use opentelemetry_sdk::{propagation::TraceContextPropagator, trace::SdkTracerProvider};
use opentelemetry_stdout::SpanExporter;
use std::{env, error::Error, io, process::Command};

fn init_tracer() -> SdkTracerProvider {
// Parent and child both use W3C Trace Context when encoding env vars.
global::set_text_map_propagator(TraceContextPropagator::new());

let provider = SdkTracerProvider::builder()
.with_simple_exporter(SpanExporter::default())
.build();
global::set_tracer_provider(provider.clone());

provider
}

fn run_parent() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
let tracer = global::tracer("examples/env-var-propagation/parent");
let span = tracer.start("parent");
let span_context = span.span_context().clone();
let cx = Context::current_with_span(span);

println!(
"parent trace_id={} span_id={}",
span_context.trace_id(),
span_context.span_id()
);

// Inject into a fresh environment map. `Command` inherits the parent
// environment by default, and `envs` adds the propagated context variables.
let mut child_env = EnvVarInjector::new();
global::get_text_map_propagator(|propagator| propagator.inject_context(&cx, &mut child_env));

// Re-exec the current binary in child mode to keep the example self-contained.
let status = Command::new(env::current_exe()?)
.arg("--child")
.envs(child_env)
.status()?;

cx.span().end();

if status.success() {
Ok(())
} else {
Err(io::Error::other(format!("child process failed with status {status}")).into())
}
}

fn run_child() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
let parent_cx = global::get_text_map_propagator(|propagator| {
// Read only the environment variables used by the active propagator.
let extractor = EnvVarExtractor::from_fields(propagator.fields());
propagator.extract(&extractor)
});
let remote_parent = parent_cx.span().span_context().clone();

if !remote_parent.is_valid() {
return Err(io::Error::other("missing propagated span context").into());
}

let tracer = global::tracer("examples/env-var-propagation/child");
let mut span = tracer.start_with_context("child", &parent_cx);
let span_context = span.span_context().clone();

println!(
"child trace_id={} parent_span_id={}",
span_context.trace_id(),
remote_parent.span_id()
);

span.end();

Ok(())
}

fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
let provider = init_tracer();
// The parent launches the same executable with `--child` to demonstrate
// propagation across a real process boundary.
let result = match env::args().nth(1).as_deref() {
Some("--child") => run_child(),
_ => run_parent(),
};

provider.shutdown()?;
result
}
3 changes: 3 additions & 0 deletions opentelemetry/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## vNext

- **Added** experimental `EnvVarExtractor` and `EnvVarInjector` helpers for
propagating OpenTelemetry context through environment variables. This API is
gated behind the `otel_unstable` feature flag.
- `otel_info!`, `otel_warn!`, `otel_debug!`, and `otel_error!` macros now accept quoted-key fields
(e.g. `"otel.component.type" = "value"`) for dotted attribute names.
- **Added** `BoundGauge<T>` and `BoundUpDownCounter<T>` types (and the
Expand Down
2 changes: 2 additions & 0 deletions opentelemetry/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,14 @@ metrics = []
testing = ["trace"]
logs = []
internal-logs = ["tracing"]
otel_unstable = []
experimental_metrics_bound_instruments = ["metrics"]

[dev-dependencies]
opentelemetry_sdk = { path = "../opentelemetry-sdk"} # for documentation tests
criterion = { workspace = true }
rand = { workspace = true, features = ["os_rng", "thread_rng"] }
temp-env = { workspace = true }
tokio = { version = "1.0", features = ["full"] }

[[bench]]
Expand Down
7 changes: 7 additions & 0 deletions opentelemetry/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,13 @@ additional exporters and other related components as well.

See [docs](https://docs.rs/opentelemetry).

Experimental environment-variable propagation helpers are available behind the
`otel_unstable` feature flag via
`opentelemetry::propagation::EnvVarExtractor` and
`opentelemetry::propagation::EnvVarInjector`. See
[`examples/env-var-propagation`](https://github.com/open-telemetry/opentelemetry-rust/tree/main/examples/env-var-propagation)
for an end-to-end parent/child process example using `TraceContextPropagator`.

## Release Notes

You can find the release notes (changelog) [here](https://github.com/open-telemetry/opentelemetry-rust/blob/main/opentelemetry/CHANGELOG.md).
Expand Down
8 changes: 6 additions & 2 deletions opentelemetry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
//! which demonstrates creating spans and propagating trace context across a
//! gRPC client and server. See the
//! [examples](https://github.com/open-telemetry/opentelemetry-rust/tree/main/examples)
//! directory for additional integration patterns.
//! directory for additional integration patterns, including
//! [`examples/env-var-propagation`](https://github.com/open-telemetry/opentelemetry-rust/tree/main/examples/env-var-propagation)
//! for parent/child process propagation via environment variables.
//!
//! See the [`trace`] module docs for more information on creating and managing
//! spans.
Expand Down Expand Up @@ -173,7 +175,9 @@
//!
//!
//! The following feature flags enable APIs defined in OpenTelemetry specification that is in experimental phase:
//! * `otel_unstable`: Includes unstable APIs. There are no features behind this flag at the moment.
//! * `otel_unstable`: Includes unstable APIs such as
//! `opentelemetry::propagation::EnvVarExtractor` and
//! `opentelemetry::propagation::EnvVarInjector` for environment-variable context propagation.
//!
//! # Related Crates
//!
Expand Down
Loading
Loading