From 9eff0e10d790e09225b6075a82e7bfeefc3881bd Mon Sep 17 00:00:00 2001 From: Brett Blue Date: Wed, 5 Nov 2025 12:25:21 -0700 Subject: [PATCH 01/20] Draft Custom Instrumentation for Rust doc. --- .../custom_instrumentation/rust.md | 225 +++++++++++++++++- 1 file changed, 220 insertions(+), 5 deletions(-) diff --git a/content/en/tracing/trace_collection/custom_instrumentation/rust.md b/content/en/tracing/trace_collection/custom_instrumentation/rust.md index 5b2a4f1179bd9..69ff74df89b99 100644 --- a/content/en/tracing/trace_collection/custom_instrumentation/rust.md +++ b/content/en/tracing/trace_collection/custom_instrumentation/rust.md @@ -1,7 +1,10 @@ --- title: Custom Instrumentation for Rust -description: 'Manually instrument your Rust applications to send custom traces to Datadog.' +description: 'Instrument your Rust application with the OpenTelemetry API to send traces to Datadog.' further_reading: + - link: 'https://www.datadoghq.com/blog/monitor-rust-otel/' + tag: 'Blog' + text: 'How to Monitor Your Rust Applications with OpenTelemetry' - link: 'tracing/other_telemetry/connect_logs_and_traces' tag: 'Documentation' text: 'Connect your Logs and Traces together' @@ -10,12 +13,224 @@ further_reading: text: 'Explore your services, resources, and traces' --- -Datadog supports custom instrumentation for Rust applications when you use the [OpenTelemetry SDK][1]. -For more information on setting this up, see [How to Monitor Your Rust Applications with OpenTelemetry][2] on the blog. +{{% otel-custom-instrumentation-lang %}} + +Datadog provides support for custom instrumentation in Rust applications through the `datadog-opentelemetry` crate. This library is built on the OpenTelemetry (OTel) API and SDK, providing a tracer that includes Datadog-specific features and an exporter. + +Because this library is built on OpenTelemetry, you will use the standard OpenTelemetry API to create traces and spans. + +## Setup + +To configure your Rust application to send OpenTelemetry traces to Datadog, you need to add the correct dependencies and initialize the tracer provider with the Datadog exporter. + +### 1. Add dependencies + +Add `datadog-opentelemetry` and the core `opentelemetry` crate to your `Cargo.toml`. + +```toml +[dependencies] +# The main Datadog OTel library +datadog-opentelemetry = { version = "0.1" } + +# The OpenTelemetry API for creating spans +opentelemetry = { version = "0.30" } +``` + +### 2. Initialize the Tracer + +In your application's main function, initialize the Datadog tracer provider. The `tracing().init()` function automatically configures the tracer from environment variables. + +
You must shut down the provider before your application exits to ensure all pending traces are flushed. +
+ + +```rust + +use datadog_opentelemetry; +use opentelemetry::{global, trace::Tracer}; +use std::time::Duration; + +fn main() { + // This picks up env var configuration (like DD_SERVICE) + // and initializes the global tracer provider + let tracer_provider = datadog_opentelemetry::tracing() + .init(); + + // --- Your application code starts here --- + // You can now use the standard OpenTelemetry API + + let tracer = global::tracer("my-component"); + + tracer.in_span("my-operation", |cx| { + // ... do work ... + }); + + println!("Doing work..."); + + // --- Your application code ends here --- + + // Shut down the tracer provider to flush remaining spans + tracer_provider.shutdown_with_timeout(Duration::from_secs(5)).expect("tracer shutdown error"); +} +``` + +### 3. Ensure Agent is running + +The Datadog exporter sends traces to the Datadog Agent, which must be running and accessible. + +## Configuration + +The Datadog Rust SDK is configured using environment variables. For a complete list of options, see the [Configuration documentation][1]. + +## Examples + +After initialization, you use the standard OpenTelemetry API to instrument your code. + +### Get a Tracer + +Get an instance of a `Tracer` from the global provider. + +```rust +use opentelemetry::global; + +let tracer = global::tracer("my-component"); +``` + +### Create a span + +Use `tracer.in_span` (from `opentelemetry::trace::Tracer`) to create a new span that is active for the duration of a closure. + +```rust +use opentelemetry::{global, trace::Tracer}; + +fn do_work() { + let tracer = global::tracer("my-component"); + + tracer.in_span("operation_name", |span| { + // The span is active within this closure + println!("Doing work..."); + + // Spans are automatically ended when the closure finishes + }); +} +``` + +### Create a child span + +To create a child span, nest `in_span` calls. The inner span automatically becomes a child of the span active in the current context. + +```rust +use opentelemetry::{global, trace::Tracer}; + +fn parent_operation() { + let tracer = global::tracer("my-component"); + + tracer.in_span("parent_operation", |parent_span| { + // parent_span is active + + tracer.in_span("child_operation", |child_span| { + // child_span is active and is a child of parent_span + println!("Doing child work..."); + }); + + println!("Doing parent work..."); + }); +} +``` + +### Access the active span + +To get the currently active span from the context, use `Span::current()`. + +```rust +use opentelemetry::trace::{Span, Tracer}; + +fn do_work_with_active_span() { + let tracer = opentelemetry::global::tracer("my-component"); + + tracer.in_span("my-operation", |span| { + // 'span' is the active span here. + // You can also get it from the context at any point + // inside this closure: + let current_span = opentelemetry::trace::Span::current(); + + // You can now add attributes or events to it + current_span.set_attribute( + opentelemetry::KeyValue::new("accessed.from.context", true) + ); + }); +} +``` + +### Add span tags + +Add attributes to a span using the `set_attribute` method. In OpenTelemetry, tags are called attributes. + +```rust +use opentelemetry::trace::{Span, Tracer}; +use opentelemetry::KeyValue; + +fn add_tags_to_span() { + let tracer = opentelemetry::global::tracer("my-component"); + + tracer.in_span("operation.with.tags", |span| { + // Set attributes (tags) on the active span + span.set_attribute(KeyValue::new("customer.id", "12345")); + span.set_attribute(KeyValue::new("http.method", "GET")); + span.set_attribute(KeyValue::new("is.test", true)); + span.set_attribute(KeyValue::new("team.name", "backend")); + + // You can also set multiple attributes at once + span.set_attributes(vec![ + KeyValue::new("resource.name", "/users/list"), + KeyValue::new("db.system", "postgres"), + ]); + }); +} +``` + +### Add span events + +Add time-stamped log messages to a span using the `add_event` method. + +```rust +use opentelemetry::trace::{Span, Tracer}; +use opentelemetry::KeyValue; + +fn add_events_to_span() { + let tracer = opentelemetry::global::tracer("my-component"); + + tracer.in_span("operation.with.events", |span| { + // Add a simple event + span.add_event("Data received", vec![]); + + // ... some work happens ... + + // Add an event with its own attributes + span.add_event( + "Processing data", + vec![ + KeyValue::new("data.size_bytes", 1024), + KeyValue::new("data.format", "json"), + ], + ); + + // ... more work ... + + span.add_event("Processing complete", vec![]); + }); +} +``` + +## Context propagation + +Because Rust does not have automatic instrumentation, you must manually propagate the trace context when making or receiving remote calls (like HTTP requests) to connect traces across services. + +For more information, see [Trace Context Propagation][2]. ## Further Reading {{< partial name="whats-next/whats-next.html" >}} -[1]: https://opentelemetry.io/docs/instrumentation/ -[2]: https://www.datadoghq.com/blog/monitor-rust-otel/ +[1]: /tracing/trace_collection/library_config/rust +[2]: //tracing/trace_collection/trace_context_propagation From de9871a10666303e5428647098b8312544bef8b8 Mon Sep 17 00:00:00 2001 From: Brett Blue Date: Wed, 5 Nov 2025 12:25:43 -0700 Subject: [PATCH 02/20] Draft library config page for Rust. --- .../trace_collection/library_config/rust.md | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 content/en/tracing/trace_collection/library_config/rust.md diff --git a/content/en/tracing/trace_collection/library_config/rust.md b/content/en/tracing/trace_collection/library_config/rust.md new file mode 100644 index 0000000000000..7313c102c5c6b --- /dev/null +++ b/content/en/tracing/trace_collection/library_config/rust.md @@ -0,0 +1,78 @@ +--- +title: Configuring the Rust Tracing Library +code_lang: rust +type: multi-code-lang +code_lang_weight: 80 +further_reading: + - link: 'https://github.com/DataDog/dd-trace-rs' + tag: "Source Code" + text: 'Source code' + - link: "/tracing/trace_collection/trace_context_propagation/" + tag: "Documentation" + text: "Propagating trace context" + - link: 'tracing/glossary/' + tag: 'Documentation' + text: 'Explore your services, resources and traces' +--- + +After you [set up the Rust SDK][1] with your application, you can optionally configure it using the following environment variables. + +## Unified Service Tagging + +It is recommended to use `DD_ENV`, `DD_SERVICE`, and `DD_VERSION` to set `env`, `service`, and `version` for your services. + +`DD_SERVICE` +: **Default**: "unnamed-rust-service"
+: Sets the service name for your application. + +`DD_ENV` +: **Default**: `(none)`
+: Set the application's environment, for example: `prod`, `staging`. + +`DD_VERSION` +: **Default**: `(none)`
+: Set the application's version, for example: `1.2.3` or `6c44da20`. + +`DD_TAGS` +: **Default**: `(none)`
+: A list of default tags to be added to every span, in `key:value` format, separated by commas. Example: `layer:api,team:intake`. + +## Traces + +`DD_TRACE_ENABLED` +: **Default**: `true`
+: Set to `false` to disable tracing. + +## Agent + +`DD_TRACE_AGENT_URL` +: **Default**: `(none)`
+: Sets the URL of the Datadog Agent. Example: `http://localhost:8126`. + +## Logging + +`DD_LOG_LEVEL` +: **Default**: `(none)`
+: Sets the internal log level for the tracer. Example: `DEBUG`, `INFO`, `WARN`, `ERROR`. + +## Sampling + +`DD_TRACE_SAMPLING_RULES` +: **Default**: `(none)`
+: A list of rules to apply for trace sampling. + +`DD_TRACE_RATE_LIMIT` +: **Default**: `(none)`
+: An integer setting the maximum number of traces to sample per second. + +## Trace context propagation + +`DD_TRACE_PROPAGATION_STYLE` +: **Default**: `(none)`
+: A comma-separated list of propagation styles to use. Supported values are `datadog` and `tracecontext`. + +## Further reading + +{{< partial name="whats-next/whats-next.html" >}} + +[1]: /tracing/trace_collection/custom_instrumentation/rust \ No newline at end of file From e674e7c85901f7ab5af8b4c104c798339de23cdd Mon Sep 17 00:00:00 2001 From: Brett Blue Date: Wed, 5 Nov 2025 12:26:07 -0700 Subject: [PATCH 03/20] Add Rust tab to trace context propagation page. --- .../trace_context_propagation/_index.md | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/content/en/tracing/trace_collection/trace_context_propagation/_index.md b/content/en/tracing/trace_collection/trace_context_propagation/_index.md index 9c914a0185a47..095d450d1241c 100644 --- a/content/en/tracing/trace_collection/trace_context_propagation/_index.md +++ b/content/en/tracing/trace_collection/trace_context_propagation/_index.md @@ -622,6 +622,126 @@ void SetHeaderValues(MessageHeaders headers, string name, string value) {{% /tab %}} +{{% tab "Rust" %}} + +The Datadog Rust SDK is built on the OpenTelemetry (OTel) SDK. + +Trace context propagation is handled by the OTel SDK, which is configured by `datadog-opentelemetry` to support both `datadog` and `tracecontext` (W3C) formats. + +### Supported formats + +| Format | Configuration Value | +|---|---| +| [Datadog][1] | `datadog` | +| [W3C Trace Context][2] | `tracecontext` | + +### Configuration + +You can control which propagation formats are used by setting the `DD_TRACE_PROPAGATION_STYLE` environment variable. You can provide a comma-separated list. + +For example: + +```bash +# To support both W3C and Datadog +export DD_TRACE_PROPAGATION_STYLE="tracecontext,datadog" +``` + +### Manual injections and extractions + +Because there is no automatic instrumentation in Rust, you must manually propagate context when making or receiving remote calls (like HTTP requests). + +You do this by using the global OTel T`extMapPropagator`. This requires a `Carrier` that can read and write HTTP headers. Most Rust web frameworks (like `axum`, `hyper`, and `reqwest`) use the `http::HeaderMap` type. + +You can use the following wrapper structs to make `http::HeaderMap` compatible with the OTel propagator API. + +```rust +use opentelemetry::propagation::{Extractor, Injector}; +use http::HeaderMap; + +// Carrier for injecting context into a HeaderMap +struct HeaderMapCarrier<'a>(&'a mut HeaderMap); + +impl<'a> Injector for HeaderMapCarrier<'a> { + fn set(&mut self, key: &str, value: String) { + if let Ok(header_name) = http::HeaderName::from_bytes(key.as_bytes()) { + if let Ok(header_value) = http::HeaderValue::from_str(&value) { + self.0.insert(header_name, header_value); + } + } + } +} + +// Carrier for extracting context from a HeaderMap +struct HeaderMapExtractor<'a>(&'a HeaderMap); + +impl<'a> Extractor for HeaderMapExtractor<'a> { + fn get(&self, key: &str) -> Option<&str> { + self.0.get(key).and_then(|v| v.to_str().ok()) + } + + fn keys(&self) -> Vec<&str> { + self.0.keys().map(|k| k.as_str()).collect() + } +} +``` + +### Injecting context (client side) + +When making an HTTP request (for example, with `reqwest`), inject the current span context into the request headers. + +```rust +use opentelemetry::{global, Context}; +use http::HeaderMap; +// (Assumes HeaderMapCarrier from the example above is present) + +async fn make_http_request() { + let propagator = global::get_text_map_propagator(|propagator| propagator.clone()); + let context = Context::current(); + let client = reqwest::Client::new(); + + // Create a mutable HeaderMap + let mut headers = HeaderMap::new(); + + // Inject the context into the headers using the carrier + propagator.inject_with_context(&context, &mut HeaderMapCarrier(&mut headers)); + + // 'headers' now contains 'traceparent', 'x-datadog-trace-id', etc. + let res = client.get("[http://example.com](http://example.com)") + .headers(headers) + .send() + .await; +} +``` + +#### Extracting context (server side) + +When receiving an HTTP request (for example, with `axum`), extract the trace context from the headers to parent your new span. + +```rust +use opentelemetry::{global, trace::Tracer, Context}; +use axum::{extract::Request, http::HeaderMap, routing::get, Router}; +// (Assumes HeaderMapExtractor from the example above is present) + +async fn axum_handler(headers: HeaderMap) { + let propagator = global::get_text_map_propagator(|propagator| propagator.clone()); + + // Extract the parent context from the incoming headers + let parent_context = propagator.extract(&HeaderMapExtractor(&headers)); + + let tracer = global::tracer("my-server-component"); + + // Start the server span as a child of the extracted context + tracer.in_span_with_context("http.server.request", &parent_context, |span| { + // ... your handler logic ... + // This span is now correctly linked to the client's trace. + }); +} +``` +[1]: #datadog-format +[2]: https://www.w3.org/TR/trace-context/ + +{{% /tab %}} + {{< /tabs >}} ## Custom header formats From 6cee4be88199e763fcbba2faa2a2cdf09f7db71e Mon Sep 17 00:00:00 2001 From: Brett Blue Date: Wed, 5 Nov 2025 13:04:17 -0700 Subject: [PATCH 04/20] Fix typos. --- .../trace_collection/custom_instrumentation/rust.md | 10 ++++------ .../en/tracing/trace_collection/library_config/rust.md | 5 +++-- .../trace_context_propagation/_index.md | 4 ++-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/content/en/tracing/trace_collection/custom_instrumentation/rust.md b/content/en/tracing/trace_collection/custom_instrumentation/rust.md index 69ff74df89b99..e8a8d386616cb 100644 --- a/content/en/tracing/trace_collection/custom_instrumentation/rust.md +++ b/content/en/tracing/trace_collection/custom_instrumentation/rust.md @@ -1,5 +1,5 @@ --- -title: Custom Instrumentation for Rust +title: Rust Custom Instrumentation using the OpenTelemetry API description: 'Instrument your Rust application with the OpenTelemetry API to send traces to Datadog.' further_reading: - link: 'https://www.datadoghq.com/blog/monitor-rust-otel/' @@ -13,11 +13,9 @@ further_reading: text: 'Explore your services, resources, and traces' --- -{{% otel-custom-instrumentation-lang %}} - Datadog provides support for custom instrumentation in Rust applications through the `datadog-opentelemetry` crate. This library is built on the OpenTelemetry (OTel) API and SDK, providing a tracer that includes Datadog-specific features and an exporter. -Because this library is built on OpenTelemetry, you will use the standard OpenTelemetry API to create traces and spans. +Because this library is built on OpenTelemetry, you use the standard OpenTelemetry API to create traces and spans. ## Setup @@ -30,10 +28,10 @@ Add `datadog-opentelemetry` and the core `opentelemetry` crate to your `Cargo.to ```toml [dependencies] # The main Datadog OTel library -datadog-opentelemetry = { version = "0.1" } +datadog-opentelemetry = { version = "0.1" } # Note: Update to latest. # The OpenTelemetry API for creating spans -opentelemetry = { version = "0.30" } +opentelemetry = { version = "0.30" } # Note: Update to latest. ``` ### 2. Initialize the Tracer diff --git a/content/en/tracing/trace_collection/library_config/rust.md b/content/en/tracing/trace_collection/library_config/rust.md index 7313c102c5c6b..d76ae69c0edc7 100644 --- a/content/en/tracing/trace_collection/library_config/rust.md +++ b/content/en/tracing/trace_collection/library_config/rust.md @@ -69,10 +69,11 @@ It is recommended to use `DD_ENV`, `DD_SERVICE`, and `DD_VERSION` to set `env`, `DD_TRACE_PROPAGATION_STYLE` : **Default**: `(none)`
-: A comma-separated list of propagation styles to use. Supported values are `datadog` and `tracecontext`. +: A comma-separated list of propagation styles to use. Supported values are `datadog` and `tracecontext`. See [Propagating Rust Trace Context][18] for more information. ## Further reading {{< partial name="whats-next/whats-next.html" >}} -[1]: /tracing/trace_collection/custom_instrumentation/rust \ No newline at end of file +[1]: /tracing/trace_collection/custom_instrumentation/rust +[2]: /tracing/trace_collection/trace_context_propagation \ No newline at end of file diff --git a/content/en/tracing/trace_collection/trace_context_propagation/_index.md b/content/en/tracing/trace_collection/trace_context_propagation/_index.md index 095d450d1241c..68736a3291101 100644 --- a/content/en/tracing/trace_collection/trace_context_propagation/_index.md +++ b/content/en/tracing/trace_collection/trace_context_propagation/_index.md @@ -650,7 +650,7 @@ export DD_TRACE_PROPAGATION_STYLE="tracecontext,datadog" Because there is no automatic instrumentation in Rust, you must manually propagate context when making or receiving remote calls (like HTTP requests). -You do this by using the global OTel T`extMapPropagator`. This requires a `Carrier` that can read and write HTTP headers. Most Rust web frameworks (like `axum`, `hyper`, and `reqwest`) use the `http::HeaderMap` type. +You do this by using the global OTel `TextMapPropagator`. This requires a `Carrier` that can read and write HTTP headers. Most Rust web frameworks (like `axum`, `hyper`, and `reqwest`) use the `http::HeaderMap` type. You can use the following wrapper structs to make `http::HeaderMap` compatible with the OTel propagator API. @@ -713,7 +713,7 @@ async fn make_http_request() { } ``` -#### Extracting context (server side) +### Extracting context (server side) When receiving an HTTP request (for example, with `axum`), extract the trace context from the headers to parent your new span. From 9530673ce157f1ec0612492a03263bcebfde6fef Mon Sep 17 00:00:00 2001 From: Brett Blue Date: Thu, 6 Nov 2025 08:14:21 -0700 Subject: [PATCH 05/20] Fix link. --- .../en/tracing/trace_collection/custom_instrumentation/rust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/tracing/trace_collection/custom_instrumentation/rust.md b/content/en/tracing/trace_collection/custom_instrumentation/rust.md index e8a8d386616cb..7c72be24b7a2b 100644 --- a/content/en/tracing/trace_collection/custom_instrumentation/rust.md +++ b/content/en/tracing/trace_collection/custom_instrumentation/rust.md @@ -231,4 +231,4 @@ For more information, see [Trace Context Propagation][2]. {{< partial name="whats-next/whats-next.html" >}} [1]: /tracing/trace_collection/library_config/rust -[2]: //tracing/trace_collection/trace_context_propagation +[2]: /tracing/trace_collection/trace_context_propagation/?tab=rust \ No newline at end of file From 04524838cd54d30ee8d711d1bc16083fad357ace Mon Sep 17 00:00:00 2001 From: Brett Blue Date: Thu, 6 Nov 2025 16:49:32 -0700 Subject: [PATCH 06/20] Add rust tile for config and custom instrumentation landing pages. --- layouts/partials/apm/apm-compatibility.html | 7 +++++++ layouts/partials/apm/apm-otel-instrumentation-custom.html | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/layouts/partials/apm/apm-compatibility.html b/layouts/partials/apm/apm-compatibility.html index 85abc30081f59..1545e41867a51 100644 --- a/layouts/partials/apm/apm-compatibility.html +++ b/layouts/partials/apm/apm-compatibility.html @@ -65,6 +65,13 @@ + {{ $currentURL := .Page.Permalink }} {{ if and (not (in $currentURL "/compatibility/")) (not (in $currentURL "/library_config/")) }} diff --git a/layouts/partials/apm/apm-otel-instrumentation-custom.html b/layouts/partials/apm/apm-otel-instrumentation-custom.html index 429a6f187edc1..e380fbba60187 100644 --- a/layouts/partials/apm/apm-otel-instrumentation-custom.html +++ b/layouts/partials/apm/apm-otel-instrumentation-custom.html @@ -65,6 +65,13 @@ + From 8f73a3d06428d09fa75cfc254a2c6f35e45fb998 Mon Sep 17 00:00:00 2001 From: Brett Blue <84536271+brett0000FF@users.noreply.github.com> Date: Tue, 11 Nov 2025 15:08:25 -0700 Subject: [PATCH 07/20] Update content/en/tracing/trace_collection/trace_context_propagation/_index.md Co-authored-by: Edmund Kump --- .../trace_collection/trace_context_propagation/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/tracing/trace_collection/trace_context_propagation/_index.md b/content/en/tracing/trace_collection/trace_context_propagation/_index.md index 68736a3291101..dba9647383f40 100644 --- a/content/en/tracing/trace_collection/trace_context_propagation/_index.md +++ b/content/en/tracing/trace_collection/trace_context_propagation/_index.md @@ -706,7 +706,7 @@ async fn make_http_request() { propagator.inject_with_context(&context, &mut HeaderMapCarrier(&mut headers)); // 'headers' now contains 'traceparent', 'x-datadog-trace-id', etc. - let res = client.get("[http://example.com](http://example.com)") + let res = client.get("http://example.com") .headers(headers) .send() .await; From 43810957d009b9cc01dc7aa9807b3df3c9e79d57 Mon Sep 17 00:00:00 2001 From: Brett Blue Date: Tue, 11 Nov 2025 15:48:49 -0700 Subject: [PATCH 08/20] Remove custom carrier; just use headerinjector and headerextractor. --- .../trace_context_propagation/_index.md | 110 +++++++----------- 1 file changed, 44 insertions(+), 66 deletions(-) diff --git a/content/en/tracing/trace_collection/trace_context_propagation/_index.md b/content/en/tracing/trace_collection/trace_context_propagation/_index.md index dba9647383f40..e468b31008130 100644 --- a/content/en/tracing/trace_collection/trace_context_propagation/_index.md +++ b/content/en/tracing/trace_collection/trace_context_propagation/_index.md @@ -646,97 +646,75 @@ For example: export DD_TRACE_PROPAGATION_STYLE="tracecontext,datadog" ``` -### Manual injections and extractions +### Manual injection and extraction -Because there is no automatic instrumentation in Rust, you must manually propagate context when making or receiving remote calls (like HTTP requests). +Because there is no automatic instrumentation for Rust, you must manually propagate context when making or receiving remote calls (like HTTP requests). +- `HeaderExtractor` to **extract** a parent context from incoming request headers. +- `HeaderInjector` to **inject** the current context into outbound request headers. -You do this by using the global OTel `TextMapPropagator`. This requires a `Carrier` that can read and write HTTP headers. Most Rust web frameworks (like `axum`, `hyper`, and `reqwest`) use the `http::HeaderMap` type. +First, add `opentelemetry-http` to your `Cargo.toml`: -You can use the following wrapper structs to make `http::HeaderMap` compatible with the OTel propagator API. - -```rust -use opentelemetry::propagation::{Extractor, Injector}; -use http::HeaderMap; - -// Carrier for injecting context into a HeaderMap -struct HeaderMapCarrier<'a>(&'a mut HeaderMap); - -impl<'a> Injector for HeaderMapCarrier<'a> { - fn set(&mut self, key: &str, value: String) { - if let Ok(header_name) = http::HeaderName::from_bytes(key.as_bytes()) { - if let Ok(header_value) = http::HeaderValue::from_str(&value) { - self.0.insert(header_name, header_value); - } - } - } -} - -// Carrier for extracting context from a HeaderMap -struct HeaderMapExtractor<'a>(&'a HeaderMap); - -impl<'a> Extractor for HeaderMapExtractor<'a> { - fn get(&self, key: &str) -> Option<&str> { - self.0.get(key).and_then(|v| v.to_str().ok()) - } - - fn keys(&self) -> Vec<&str> { - self.0.keys().map(|k| k.as_str()).collect() - } -} +```toml +[dependencies] +# Provides HeaderInjector and HeaderExtractor +opentelemetry-http = "0.31" ``` ### Injecting context (client side) -When making an HTTP request (for example, with `reqwest`), inject the current span context into the request headers. +When making an HTTP request (for example, with `reqwest`), inject the current span context into the request headers using `HeaderInjector`. ```rust use opentelemetry::{global, Context}; -use http::HeaderMap; -// (Assumes HeaderMapCarrier from the example above is present) - -async fn make_http_request() { - let propagator = global::get_text_map_propagator(|propagator| propagator.clone()); - let context = Context::current(); - let client = reqwest::Client::new(); - - // Create a mutable HeaderMap - let mut headers = HeaderMap::new(); - - // Inject the context into the headers using the carrier - propagator.inject_with_context(&context, &mut HeaderMapCarrier(&mut headers)); - - // 'headers' now contains 'traceparent', 'x-datadog-trace-id', etc. - let res = client.get("http://example.com") - .headers(headers) - .send() - .await; +use opentelemetry_http::HeaderInjector; +use http::Request; +use hyper::Body; + +// HYPER example +fn build_outbound_request(url: &str) -> http::Result> { + let cx = Context::current(); + + // Build the request and inject headers in-place + let mut builder = Request::builder().method("GET").uri(url); + global::get_text_map_propagator(|prop| { + prop.inject_context(&cx, &mut HeaderInjector(builder.headers_mut().unwrap())) + }); + + builder.body(Body::empty()) } ``` ### Extracting context (server side) -When receiving an HTTP request (for example, with `axum`), extract the trace context from the headers to parent your new span. +When receiving an HTTP request (for example, with `axum`), extract the trace context from the headers using `HeaderExtractor` to parent your new span. ```rust -use opentelemetry::{global, trace::Tracer, Context}; -use axum::{extract::Request, http::HeaderMap, routing::get, Router}; -// (Assumes HeaderMapExtractor from the example above is present) +use opentelemetry::{ + global, + trace::{SpanKind, Tracer}, +}; +use opentelemetry_http::HeaderExtractor; +use axum::http::HeaderMap; +// AXUM example async fn axum_handler(headers: HeaderMap) { - let propagator = global::get_text_map_propagator(|propagator| propagator.clone()); - // Extract the parent context from the incoming headers - let parent_context = propagator.extract(&HeaderMapExtractor(&headers)); + let parent_cx = global::get_text_map_propagator(|p| p.extract(&HeaderExtractor(&headers))); let tracer = global::tracer("my-server-component"); - // Start the server span as a child of the extracted context - tracer.in_span_with_context("http.server.request", &parent_context, |span| { - // ... your handler logic ... - // This span is now correctly linked to the client's trace. - }); + // Start the server span as a child of the extracted context. + // Setting SpanKind::Server is a best practice. + let _span = tracer + .span_builder("http.server.request") + .with_kind(SpanKind::Server) + .start_with_context(tracer, &parent_cx); + + // ... your handler logic ... + // This span is now correctly linked to the client's trace. } ``` + [1]: #datadog-format [2]: https://www.w3.org/TR/trace-context/ From 61305c21ee63936486810fd8f8d0f95ee6fc05a5 Mon Sep 17 00:00:00 2001 From: Brett Blue Date: Wed, 12 Nov 2025 15:46:41 -0700 Subject: [PATCH 09/20] Add note that baggage isn't supported in Rust. --- .../trace_context_propagation/_index.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/content/en/tracing/trace_collection/trace_context_propagation/_index.md b/content/en/tracing/trace_collection/trace_context_propagation/_index.md index e468b31008130..1c624e70a0bb1 100644 --- a/content/en/tracing/trace_collection/trace_context_propagation/_index.md +++ b/content/en/tracing/trace_collection/trace_context_propagation/_index.md @@ -73,14 +73,16 @@ Most services send and receive trace context headers using the same format. Howe The Datadog SDK supports the following trace context formats: -| Format | Configuration Value | -|------------------------|-------------------------------| -| [Datadog][1] | `datadog` | -| [W3C Trace Context][2] | `tracecontext` | -| [B3 Single][3] | _Language Dependent Value_ | -| [B3 Multi][4] | `b3multi` | -| [Baggage][10] | `baggage` | -| [None][5] | `none` | +| Format | Configuration Value | +|------------------------|----------------------------| +| [Datadog][1] | `datadog` | +| [W3C Trace Context][2] | `tracecontext` | +| [B3 Single][3] | _Language Dependent Value_ | +| [B3 Multi][4] | `b3multi` | +| [Baggage][10] | `baggage`* | +| [None][5] | `none` | + +* **Note**: `baggage` is not supported in Rust. ## Language support From 0d6ec48fd05af75119aab47a1ee87fc4e2b48ce8 Mon Sep 17 00:00:00 2001 From: Brett Blue Date: Wed, 12 Nov 2025 15:49:34 -0700 Subject: [PATCH 10/20] All the in_span calls have a context as parameter, not a span. --- .../trace_collection/custom_instrumentation/rust.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/content/en/tracing/trace_collection/custom_instrumentation/rust.md b/content/en/tracing/trace_collection/custom_instrumentation/rust.md index 7c72be24b7a2b..b7e6000445c7d 100644 --- a/content/en/tracing/trace_collection/custom_instrumentation/rust.md +++ b/content/en/tracing/trace_collection/custom_instrumentation/rust.md @@ -104,7 +104,7 @@ use opentelemetry::{global, trace::Tracer}; fn do_work() { let tracer = global::tracer("my-component"); - tracer.in_span("operation_name", |span| { + tracer.in_span("operation_name", |cx| { // The span is active within this closure println!("Doing work..."); @@ -146,7 +146,7 @@ use opentelemetry::trace::{Span, Tracer}; fn do_work_with_active_span() { let tracer = opentelemetry::global::tracer("my-component"); - tracer.in_span("my-operation", |span| { + tracer.in_span("my-operation", |cx| { // 'span' is the active span here. // You can also get it from the context at any point // inside this closure: @@ -171,7 +171,7 @@ use opentelemetry::KeyValue; fn add_tags_to_span() { let tracer = opentelemetry::global::tracer("my-component"); - tracer.in_span("operation.with.tags", |span| { + tracer.in_span("operation.with.tags", |cx| { // Set attributes (tags) on the active span span.set_attribute(KeyValue::new("customer.id", "12345")); span.set_attribute(KeyValue::new("http.method", "GET")); @@ -198,7 +198,7 @@ use opentelemetry::KeyValue; fn add_events_to_span() { let tracer = opentelemetry::global::tracer("my-component"); - tracer.in_span("operation.with.events", |span| { + tracer.in_span("operation.with.events", |cx| { // Add a simple event span.add_event("Data received", vec![]); From e4a006462b06bfa6589ea5a0796c0873056dc422 Mon Sep 17 00:00:00 2001 From: Brett Blue Date: Wed, 12 Nov 2025 16:07:11 -0700 Subject: [PATCH 11/20] Update config options from reference. --- .../trace_collection/library_config/rust.md | 92 ++++++++++++++++--- 1 file changed, 80 insertions(+), 12 deletions(-) diff --git a/content/en/tracing/trace_collection/library_config/rust.md b/content/en/tracing/trace_collection/library_config/rust.md index d76ae69c0edc7..036137d163b77 100644 --- a/content/en/tracing/trace_collection/library_config/rust.md +++ b/content/en/tracing/trace_collection/library_config/rust.md @@ -21,14 +21,14 @@ After you [set up the Rust SDK][1] with your application, you can optionally con It is recommended to use `DD_ENV`, `DD_SERVICE`, and `DD_VERSION` to set `env`, `service`, and `version` for your services. -`DD_SERVICE` -: **Default**: "unnamed-rust-service"
-: Sets the service name for your application. - `DD_ENV` : **Default**: `(none)`
: Set the application's environment, for example: `prod`, `staging`. +`DD_SERVICE` +: **Default**: `unnamed-rust-service`
+: Sets the service name for your application. + `DD_VERSION` : **Default**: `(none)`
: Set the application's version, for example: `1.2.3` or `6c44da20`. @@ -43,37 +43,105 @@ It is recommended to use `DD_ENV`, `DD_SERVICE`, and `DD_VERSION` to set `env`, : **Default**: `true`
: Set to `false` to disable tracing. +`DD_TRACE_STATS_COMPUTATION_ENABLED` +: **Default**: `true`
+: Enable computation of trace statistics. + +`DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH` +: **Default**: `512`
+: Maximum length of the `x-datadog-tags` header in bytes. + +`DD_TRACE_PARTIAL_FLUSH_ENABLED` +: **Default**: `false`
+: Enable partial flushing of traces. + +`DD_TRACE_PARTIAL_FLUSH_MIN_SPANS` +: **Default**: `300`
+: Minimum number of spans in a trace before partial flush is triggered. + +`DD_REMOTE_CONFIGURATION_ENABLED` +: **Default**: `true`
+: Enable or disable remote configuration. Also accepts the alias `DD_REMOTE_CONFIG_ENABLED`. + +`DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS` +: **Default**: `5.0`
+: Interval in seconds for polling remote configuration updates. + ## Agent +`DD_AGENT_HOST` +: **Default**: `localhost`
+: Sets the hostname of the Datadog Agent. + +`DD_TRACE_AGENT_PORT` +: **Default**: `8126`
+: Sets the port of the Datadog Agent for trace collection. + `DD_TRACE_AGENT_URL` : **Default**: `(none)`
-: Sets the URL of the Datadog Agent. Example: `http://localhost:8126`. +: Sets the URL of the Datadog Agent. Example: `http://localhost:8126`. This takes precedence over `DD_AGENT_HOST` and `DD_TRACE_AGENT_PORT`. + +`DD_DOGSTATSD_HOST` +: **Default**: `localhost`
+: Sets the hostname for DogStatsD metric collection. + +`DD_DOGSTATSD_PORT` +: **Default**: `8125`
+: Sets the port for DogStatsD metric collection. + +`DD_DOGSTATSD_URL` +: **Default**: `(none)`
+: Sets the URL for DogStatsD. This takes precedence over `DD_DOGSTATSD_HOST` and `DD_DOGSTATSD_PORT`. + +`DD_INSTRUMENTATION_TELEMETRY_ENABLED` +: **Default**: `true`
+: Enable or disable telemetry data collection and sending. + +`DD_TELEMETRY_HEARTBEAT_INTERVAL` +: **Default**: `60.0`
+: Interval in seconds for sending telemetry heartbeat messages. + +`DD_TELEMETRY_LOG_COLLECTION_ENABLED` +: **Default**: `true`
+: Enable or disable log collection for telemetry. ## Logging `DD_LOG_LEVEL` -: **Default**: `(none)`
-: Sets the internal log level for the tracer. Example: `DEBUG`, `INFO`, `WARN`, `ERROR`. +: **Default**: `ERROR`
+: Sets the internal log level for the tracer. Valid values: `DEBUG`, `INFO`, `WARN`, `ERROR`. ## Sampling `DD_TRACE_SAMPLING_RULES` : **Default**: `(none)`
-: A list of rules to apply for trace sampling. +: A JSON array of objects to apply for trace sampling. Each rule must have a `sample_rate` between 0.0 and 1.0 (inclusive). `DD_TRACE_RATE_LIMIT` -: **Default**: `(none)`
-: An integer setting the maximum number of traces to sample per second. +: **Default**: `100`
+: Maximum number of traces to sample per second. ## Trace context propagation `DD_TRACE_PROPAGATION_STYLE` +: **Default**: `datadog,tracecontext`
+: A comma-separated list of propagation styles to use for both extraction and injection. Supported values are `datadog` and `tracecontext`. See [Propagating Rust Trace Context][2] for more information. + +`DD_TRACE_PROPAGATION_STYLE_EXTRACT` : **Default**: `(none)`
-: A comma-separated list of propagation styles to use. Supported values are `datadog` and `tracecontext`. See [Propagating Rust Trace Context][18] for more information. +: A comma-separated list of propagation styles to use for extraction. When set, this overrides `DD_TRACE_PROPAGATION_STYLE` for extraction. + +`DD_TRACE_PROPAGATION_STYLE_INJECT` +: **Default**: `(none)`
+: A comma-separated list of propagation styles to use for injection. When set, this overrides `DD_TRACE_PROPAGATION_STYLE` for injection. + +`DD_TRACE_PROPAGATION_EXTRACT_FIRST` +: **Default**: `false`
+: When set to `true`, stops extracting after the first successful trace context extraction. ## Further reading {{< partial name="whats-next/whats-next.html" >}} [1]: /tracing/trace_collection/custom_instrumentation/rust -[2]: /tracing/trace_collection/trace_context_propagation \ No newline at end of file +[2]: /tracing/trace_collection/trace_context_propagation From f5ba7e98add9a77962434bb5fb1a26f19e1be828 Mon Sep 17 00:00:00 2001 From: Brett Blue Date: Wed, 12 Nov 2025 16:23:53 -0700 Subject: [PATCH 12/20] Address feedback from review. --- .../trace_collection/trace_context_propagation/_index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/en/tracing/trace_collection/trace_context_propagation/_index.md b/content/en/tracing/trace_collection/trace_context_propagation/_index.md index 1c624e70a0bb1..23de8e89a4909 100644 --- a/content/en/tracing/trace_collection/trace_context_propagation/_index.md +++ b/content/en/tracing/trace_collection/trace_context_propagation/_index.md @@ -664,7 +664,7 @@ opentelemetry-http = "0.31" ### Injecting context (client side) -When making an HTTP request (for example, with `reqwest`), inject the current span context into the request headers using `HeaderInjector`. +When making an HTTP request (for example, with `hyper`), inject the current span context into the request headers using `HeaderInjector`. ```rust use opentelemetry::{global, Context}; @@ -688,7 +688,7 @@ fn build_outbound_request(url: &str) -> http::Result> { ### Extracting context (server side) -When receiving an HTTP request (for example, with `axum`), extract the trace context from the headers using `HeaderExtractor` to parent your new span. +When receiving an HTTP request (for example, with `hyper`), extract the trace context from the headers using `HeaderExtractor` to parent your new span. ```rust use opentelemetry::{ From aeb2baf6486740c94c2d05ff38d97dc401f7e967 Mon Sep 17 00:00:00 2001 From: Brett Blue Date: Wed, 12 Nov 2025 16:33:58 -0700 Subject: [PATCH 13/20] Add note about crate version. --- .../trace_context_propagation/_index.md | 46 +++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/content/en/tracing/trace_collection/trace_context_propagation/_index.md b/content/en/tracing/trace_collection/trace_context_propagation/_index.md index 23de8e89a4909..95951b9f8c447 100644 --- a/content/en/tracing/trace_collection/trace_context_propagation/_index.md +++ b/content/en/tracing/trace_collection/trace_context_propagation/_index.md @@ -659,9 +659,11 @@ First, add `opentelemetry-http` to your `Cargo.toml`: ```toml [dependencies] # Provides HeaderInjector and HeaderExtractor -opentelemetry-http = "0.31" +opentelemetry-http = "" ``` +
Use the same crate version for opentelemetry-http as the rest of your OpenTelemetry dependencies to avoid version conflicts.
+ ### Injecting context (client side) When making an HTTP request (for example, with `hyper`), inject the current span context into the request headers using `HeaderInjector`. @@ -693,27 +695,45 @@ When receiving an HTTP request (for example, with `hyper`), extract the trace co ```rust use opentelemetry::{ global, - trace::{SpanKind, Tracer}, + trace::{Span, FutureExt, SpanKind, Tracer}, + Context, }; use opentelemetry_http::HeaderExtractor; -use axum::http::HeaderMap; +use hyper::{Body, Request, Response}; -// AXUM example -async fn axum_handler(headers: HeaderMap) { - // Extract the parent context from the incoming headers - let parent_cx = global::get_text_map_propagator(|p| p.extract(&HeaderExtractor(&headers))); +// Utility function to extract context from a hyper request +fn extract_context(req: &Request) -> Context { + global::get_text_map_propagator(|propagator| { + propagator.extract(&HeaderExtractor(req.headers())) + }) +} - let tracer = global::tracer("my-server-component"); +// A placeholder for your actual request handling logic +async fn your_handler_logic() -> Response { + // ... your logic ... + Response::new(Body::from("Hello, World!")) +} - // Start the server span as a child of the extracted context. - // Setting SpanKind::Server is a best practice. - let _span = tracer +// HYPER example +async fn hyper_handler(req:Request) -> Response { + // Extract the parent context from the incoming headers + let parent_cx = extract_context(&req); + + let tracer = global::tracer("my-server-component"); + + // Start the server span as a child of the extracted context + let server_span = tracer .span_builder("http.server.request") .with_kind(SpanKind::Server) .start_with_context(tracer, &parent_cx); - // ... your handler logic ... - // This span is now correctly linked to the client's trace. + // Create a new context with the new server span + let cx = parent_cx.with_span(server_span); + + // Attach the new context to the future. + // This makes 'server_span' the current span for 'your_handler_logic' + // and any calls it makes. + your_handler_logic().with_context(cx).await } ``` From ef5544226190bc32bcfd9483894339b5c8db2aea Mon Sep 17 00:00:00 2001 From: Brett Blue Date: Thu, 13 Nov 2025 09:34:03 -0700 Subject: [PATCH 14/20] Compatibility page + preview banner. --- .../trace_collection/compatibility/rust.md | 52 +++++++++++++++++++ .../custom_instrumentation/rust.md | 4 ++ .../trace_context_propagation/_index.md | 2 + 3 files changed, 58 insertions(+) create mode 100644 content/en/tracing/trace_collection/compatibility/rust.md diff --git a/content/en/tracing/trace_collection/compatibility/rust.md b/content/en/tracing/trace_collection/compatibility/rust.md new file mode 100644 index 0000000000000..c030340356628 --- /dev/null +++ b/content/en/tracing/trace_collection/compatibility/rust.md @@ -0,0 +1,52 @@ +--- +title: Rust Compatibility Requirements +description: 'Compatibility Requirements for the Datadog Rust Tracer' +code_lang: rust +type: multi-code-lang +code_lang_weight: 90 +further_reading: + - link: 'tracing/trace_collection/custom_instrumentation/rust' + tag: 'Documentation' + text: 'Instrument Your Application' + - link: 'https://github.com/DataDog/dd-trace-rs' + tag: "External Site" + text: 'dd-trace-rs repository' +--- + +{{< callout btn_hidden="true" >}} + The Datadog Rust SDK is in Preview. It is not recommended for full production use. +{{< /callout >}} + +The Datadog Rust SDK is open source. For more information, see the [`dd-trace-rs` repository][1]. + +## Language and library support + +The Rust tracer relies on specific versions of the Rust compiler and the OpenTelemetry crate. + +| Component | Requirement | +|---|---| +| **Rust Version** | 1.84 (MSRV) or newer | +| **OpenTelemetry Crate** | Version 0.30 | + +## Operating systems + +The Rust tracer is tested and supported on the following operating systems: +- [TODO] + +## Integrations + +The Datadog Rust SDK does not provide automatic instrumentation. + +You must manually instrument your application using the [OpenTelemetry API][2]. This includes: +- Creating spans for functions or operations. +- Adding attributes (tags) and events to spans. +- Manually propagating trace context for distributed traces. + +For examples, see the [Rust Custom Instrumentation][2] documentation. + +## Further reading + +{{< partial name="whats-next/whats-next.html" >}} + +[1]: https://github.com/DataDog/dd-trace-rs +[2]: /tracing/trace_collection/custom_instrumentation/rust \ No newline at end of file diff --git a/content/en/tracing/trace_collection/custom_instrumentation/rust.md b/content/en/tracing/trace_collection/custom_instrumentation/rust.md index b7e6000445c7d..a7ef11cd11dd3 100644 --- a/content/en/tracing/trace_collection/custom_instrumentation/rust.md +++ b/content/en/tracing/trace_collection/custom_instrumentation/rust.md @@ -13,6 +13,10 @@ further_reading: text: 'Explore your services, resources, and traces' --- +{{< callout btn_hidden="true" >}} + The Datadog Rust SDK is in Preview. It is not recommended for full production use. +{{< /callout >}} + Datadog provides support for custom instrumentation in Rust applications through the `datadog-opentelemetry` crate. This library is built on the OpenTelemetry (OTel) API and SDK, providing a tracer that includes Datadog-specific features and an exporter. Because this library is built on OpenTelemetry, you use the standard OpenTelemetry API to create traces and spans. diff --git a/content/en/tracing/trace_collection/trace_context_propagation/_index.md b/content/en/tracing/trace_collection/trace_context_propagation/_index.md index 95951b9f8c447..2f2ea386adcf3 100644 --- a/content/en/tracing/trace_collection/trace_context_propagation/_index.md +++ b/content/en/tracing/trace_collection/trace_context_propagation/_index.md @@ -626,6 +626,8 @@ void SetHeaderValues(MessageHeaders headers, string name, string value) {{% tab "Rust" %}} +
The Datadog Rust SDK is in Preview. It is not recommended for full production use.
+ The Datadog Rust SDK is built on the OpenTelemetry (OTel) SDK. Trace context propagation is handled by the OTel SDK, which is configured by `datadog-opentelemetry` to support both `datadog` and `tracecontext` (W3C) formats. From d0a00a19804453118f77c344db45afc583df1e05 Mon Sep 17 00:00:00 2001 From: Brett Blue Date: Thu, 13 Nov 2025 10:04:52 -0700 Subject: [PATCH 15/20] Rust compatibility tweaks. --- .../en/tracing/trace_collection/compatibility/rust.md | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/content/en/tracing/trace_collection/compatibility/rust.md b/content/en/tracing/trace_collection/compatibility/rust.md index c030340356628..7505bbe106d16 100644 --- a/content/en/tracing/trace_collection/compatibility/rust.md +++ b/content/en/tracing/trace_collection/compatibility/rust.md @@ -21,17 +21,12 @@ The Datadog Rust SDK is open source. For more information, see the [`dd-trace-rs ## Language and library support -The Rust tracer relies on specific versions of the Rust compiler and the OpenTelemetry crate. +The Rust SDK relies on specific versions of the Rust compiler and the OpenTelemetry crate. | Component | Requirement | |---|---| -| **Rust Version** | 1.84 (MSRV) or newer | -| **OpenTelemetry Crate** | Version 0.30 | - -## Operating systems - -The Rust tracer is tested and supported on the following operating systems: -- [TODO] +| **Rust Version** | 1.84 (MSRV) | +| **OpenTelemetry Crate** | Version 0.31 | ## Integrations From a9f0a654f00ec5b7c1adbca131cc7b8ad1c3a4f2 Mon Sep 17 00:00:00 2001 From: Brett Blue Date: Thu, 13 Nov 2025 10:41:34 -0700 Subject: [PATCH 16/20] Adjust preview banner. --- content/en/tracing/trace_collection/compatibility/rust.md | 4 ++-- .../tracing/trace_collection/custom_instrumentation/rust.md | 4 ++-- .../trace_collection/trace_context_propagation/_index.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/content/en/tracing/trace_collection/compatibility/rust.md b/content/en/tracing/trace_collection/compatibility/rust.md index 7505bbe106d16..7e493f8a523ed 100644 --- a/content/en/tracing/trace_collection/compatibility/rust.md +++ b/content/en/tracing/trace_collection/compatibility/rust.md @@ -13,8 +13,8 @@ further_reading: text: 'dd-trace-rs repository' --- -{{< callout btn_hidden="true" >}} - The Datadog Rust SDK is in Preview. It is not recommended for full production use. +{{< callout header="false" btn_hidden="true" >}} + The Datadog Rust SDK is in Preview. {{< /callout >}} The Datadog Rust SDK is open source. For more information, see the [`dd-trace-rs` repository][1]. diff --git a/content/en/tracing/trace_collection/custom_instrumentation/rust.md b/content/en/tracing/trace_collection/custom_instrumentation/rust.md index a7ef11cd11dd3..2a88fc5b03b38 100644 --- a/content/en/tracing/trace_collection/custom_instrumentation/rust.md +++ b/content/en/tracing/trace_collection/custom_instrumentation/rust.md @@ -13,8 +13,8 @@ further_reading: text: 'Explore your services, resources, and traces' --- -{{< callout btn_hidden="true" >}} - The Datadog Rust SDK is in Preview. It is not recommended for full production use. +{{< callout header="false" btn_hidden="true" >}} + The Datadog Rust SDK is in Preview. {{< /callout >}} Datadog provides support for custom instrumentation in Rust applications through the `datadog-opentelemetry` crate. This library is built on the OpenTelemetry (OTel) API and SDK, providing a tracer that includes Datadog-specific features and an exporter. diff --git a/content/en/tracing/trace_collection/trace_context_propagation/_index.md b/content/en/tracing/trace_collection/trace_context_propagation/_index.md index 2f2ea386adcf3..d1ecb94ae068a 100644 --- a/content/en/tracing/trace_collection/trace_context_propagation/_index.md +++ b/content/en/tracing/trace_collection/trace_context_propagation/_index.md @@ -626,7 +626,7 @@ void SetHeaderValues(MessageHeaders headers, string name, string value) {{% tab "Rust" %}} -
The Datadog Rust SDK is in Preview. It is not recommended for full production use.
+
The Datadog Rust SDK is in Preview.
The Datadog Rust SDK is built on the OpenTelemetry (OTel) SDK. From b266fdd96aca7b0f45d587e46319faca0bbebc50 Mon Sep 17 00:00:00 2001 From: Brett Blue <84536271+brett0000FF@users.noreply.github.com> Date: Mon, 17 Nov 2025 16:57:24 -0500 Subject: [PATCH 17/20] Update comments for active span in Rust example Clarified comments regarding span retrieval in Rust example. --- .../trace_collection/custom_instrumentation/rust.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/content/en/tracing/trace_collection/custom_instrumentation/rust.md b/content/en/tracing/trace_collection/custom_instrumentation/rust.md index 2a88fc5b03b38..8675771d00958 100644 --- a/content/en/tracing/trace_collection/custom_instrumentation/rust.md +++ b/content/en/tracing/trace_collection/custom_instrumentation/rust.md @@ -151,9 +151,8 @@ fn do_work_with_active_span() { let tracer = opentelemetry::global::tracer("my-component"); tracer.in_span("my-operation", |cx| { - // 'span' is the active span here. - // You can also get it from the context at any point - // inside this closure: + // A new span "my-operation" is now the active span. + // You can retrieve it from the active context: let current_span = opentelemetry::trace::Span::current(); // You can now add attributes or events to it @@ -235,4 +234,4 @@ For more information, see [Trace Context Propagation][2]. {{< partial name="whats-next/whats-next.html" >}} [1]: /tracing/trace_collection/library_config/rust -[2]: /tracing/trace_collection/trace_context_propagation/?tab=rust \ No newline at end of file +[2]: /tracing/trace_collection/trace_context_propagation/?tab=rust From 2b346af3c1f85831bcea5801e9096bda59b9972c Mon Sep 17 00:00:00 2001 From: Brett Blue Date: Mon, 17 Nov 2025 20:09:33 -0500 Subject: [PATCH 18/20] Add auto-instrumentation page for Rust. --- .../dd_libraries/rust.md | 58 +++++++++++++++++++ .../trace_collection/compatibility/rust.md | 2 +- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 content/en/tracing/trace_collection/automatic_instrumentation/dd_libraries/rust.md diff --git a/content/en/tracing/trace_collection/automatic_instrumentation/dd_libraries/rust.md b/content/en/tracing/trace_collection/automatic_instrumentation/dd_libraries/rust.md new file mode 100644 index 0000000000000..c278601ca9340 --- /dev/null +++ b/content/en/tracing/trace_collection/automatic_instrumentation/dd_libraries/rust.md @@ -0,0 +1,58 @@ +--- +title: Tracing Rust Applications +description: "Set up the Datadog Rust SDK to send traces to Datadog." +aliases: +- /tracing/trace_collection/dd_libraries/rust +code_lang: rust +type: multi-code-lang +code_lang_weight: 90 +further_reading: +- link: "https://github.com/DataDog/dd-trace-rs" + tag: "Source Code" + text: Source code +- link: "/tracing/trace_collection/custom_instrumentation/rust" + tag: "Documentation" + text: "Custom Instrumentation" +--- + +{{< callout header="false" btn_hidden="true" >}} + The Datadog Rust SDK is in Preview. +{{< /callout >}} + +
+The Rust SDK does not provide automatic instrumentation. Tracing is achieved by manually instrumenting your application using the OpenTelemetry API. +
+ +## Overview + +Datadog provides tracing support for Rust applications through the `datadog-opentelemetry` crate, which is built on the OpenTelemetry (OTel) API and SDK. + +To get started, make sure you have [installed and configured the Datadog Agent][4]. + +## Instrumentation + +The Datadog Rust SDK does not provide automatic instrumentation. + +You must manually instrument your application using the OpenTelemetry API. This includes: +- Creating spans for functions or operations. +- Adding attributes (tags) and events to spans. +- Manually propagating trace context for distributed traces. + +For examples, see the [Rust Custom Instrumentation][2] documentation. + +## Configuration + +The Rust SDK can be configured using environment variables. For a full list of options, see the [Library Configuration][3] documentation. + +## Compatibility + +The Rust SDK requires a Minimum Supported Rust Version (MSRV) and specific OpenTelemetry library versions. For a full list of compatibility requirements, see the [Compatibility Requirements][1] page. + +## Further reading + +{{< partial name="whats-next/whats-next.html" >}} + +[1]: /tracing/trace_collection/compatibility/rust +[2]: /tracing/trace_collection/custom_instrumentation/rust +[3]: /tracing/trace_collection/library_config/rust +[4]: /tracing/trace_collection/automatic_instrumentation/?tab=datadoglibraries#install-and-configure-the-agent \ No newline at end of file diff --git a/content/en/tracing/trace_collection/compatibility/rust.md b/content/en/tracing/trace_collection/compatibility/rust.md index 7e493f8a523ed..2326cc586d981 100644 --- a/content/en/tracing/trace_collection/compatibility/rust.md +++ b/content/en/tracing/trace_collection/compatibility/rust.md @@ -32,7 +32,7 @@ The Rust SDK relies on specific versions of the Rust compiler and the OpenTeleme The Datadog Rust SDK does not provide automatic instrumentation. -You must manually instrument your application using the [OpenTelemetry API][2]. This includes: +You must manually instrument your application using the OpenTelemetry API]. This includes: - Creating spans for functions or operations. - Adding attributes (tags) and events to spans. - Manually propagating trace context for distributed traces. From 9120ef301e3928ba13628668a9cd03651ac4e788 Mon Sep 17 00:00:00 2001 From: Brett Blue Date: Tue, 18 Nov 2025 20:28:25 -0700 Subject: [PATCH 19/20] Final polish. --- .../dd_libraries/rust.md | 7 +-- .../trace_collection/compatibility/rust.md | 12 +++-- .../custom_instrumentation/rust.md | 46 ++++++++----------- .../trace_context_propagation/_index.md | 42 ++++++++++------- 4 files changed, 57 insertions(+), 50 deletions(-) diff --git a/content/en/tracing/trace_collection/automatic_instrumentation/dd_libraries/rust.md b/content/en/tracing/trace_collection/automatic_instrumentation/dd_libraries/rust.md index c278601ca9340..6775675add926 100644 --- a/content/en/tracing/trace_collection/automatic_instrumentation/dd_libraries/rust.md +++ b/content/en/tracing/trace_collection/automatic_instrumentation/dd_libraries/rust.md @@ -19,13 +19,13 @@ further_reading: The Datadog Rust SDK is in Preview. {{< /callout >}} -
+
The Rust SDK does not provide automatic instrumentation. Tracing is achieved by manually instrumenting your application using the OpenTelemetry API.
## Overview -Datadog provides tracing support for Rust applications through the `datadog-opentelemetry` crate, which is built on the OpenTelemetry (OTel) API and SDK. +Datadog provides tracing support for Rust applications through the []`datadog-opentelemetry` crate][5], which is built on the OpenTelemetry (OTel) API and SDK. To get started, make sure you have [installed and configured the Datadog Agent][4]. @@ -55,4 +55,5 @@ The Rust SDK requires a Minimum Supported Rust Version (MSRV) and specific OpenT [1]: /tracing/trace_collection/compatibility/rust [2]: /tracing/trace_collection/custom_instrumentation/rust [3]: /tracing/trace_collection/library_config/rust -[4]: /tracing/trace_collection/automatic_instrumentation/?tab=datadoglibraries#install-and-configure-the-agent \ No newline at end of file +[4]: /tracing/trace_collection/automatic_instrumentation/?tab=datadoglibraries#install-and-configure-the-agent +[5]: https://crates.io/crates/datadog-opentelemetry \ No newline at end of file diff --git a/content/en/tracing/trace_collection/compatibility/rust.md b/content/en/tracing/trace_collection/compatibility/rust.md index 2326cc586d981..64c1f3eba4793 100644 --- a/content/en/tracing/trace_collection/compatibility/rust.md +++ b/content/en/tracing/trace_collection/compatibility/rust.md @@ -17,7 +17,7 @@ further_reading: The Datadog Rust SDK is in Preview. {{< /callout >}} -The Datadog Rust SDK is open source. For more information, see the [`dd-trace-rs` repository][1]. +The Datadog Rust SDK is open source. For more information, see the [`dd-trace-rs` repository][1] or the [`datadog-opentelemetry` crate][4]. ## Language and library support @@ -25,14 +25,14 @@ The Rust SDK relies on specific versions of the Rust compiler and the OpenTeleme | Component | Requirement | |---|---| -| **Rust Version** | 1.84 (MSRV) | -| **OpenTelemetry Crate** | Version 0.31 | +| Rust Version | 1.84 (MSRV) | +| [OpenTelemetry Crate][3] | Version 0.31 | ## Integrations The Datadog Rust SDK does not provide automatic instrumentation. -You must manually instrument your application using the OpenTelemetry API]. This includes: +You must manually instrument your application using the OpenTelemetry API. This includes: - Creating spans for functions or operations. - Adding attributes (tags) and events to spans. - Manually propagating trace context for distributed traces. @@ -44,4 +44,6 @@ For examples, see the [Rust Custom Instrumentation][2] documentation. {{< partial name="whats-next/whats-next.html" >}} [1]: https://github.com/DataDog/dd-trace-rs -[2]: /tracing/trace_collection/custom_instrumentation/rust \ No newline at end of file +[2]: /tracing/trace_collection/custom_instrumentation/rust +[3]: https://crates.io/crates/opentelemetry +[4]: https://crates.io/crates/datadog-opentelemetry \ No newline at end of file diff --git a/content/en/tracing/trace_collection/custom_instrumentation/rust.md b/content/en/tracing/trace_collection/custom_instrumentation/rust.md index 8675771d00958..b59b5752847da 100644 --- a/content/en/tracing/trace_collection/custom_instrumentation/rust.md +++ b/content/en/tracing/trace_collection/custom_instrumentation/rust.md @@ -17,7 +17,7 @@ further_reading: The Datadog Rust SDK is in Preview. {{< /callout >}} -Datadog provides support for custom instrumentation in Rust applications through the `datadog-opentelemetry` crate. This library is built on the OpenTelemetry (OTel) API and SDK, providing a tracer that includes Datadog-specific features and an exporter. +Datadog provides support for custom instrumentation in Rust applications through the [`datadog-opentelemetry` crate][3]. This library is built on the OpenTelemetry (OTel) API and SDK, providing a tracer that includes Datadog-specific features and an exporter. Because this library is built on OpenTelemetry, you use the standard OpenTelemetry API to create traces and spans. @@ -32,22 +32,19 @@ Add `datadog-opentelemetry` and the core `opentelemetry` crate to your `Cargo.to ```toml [dependencies] # The main Datadog OTel library -datadog-opentelemetry = { version = "0.1" } # Note: Update to latest. +datadog-opentelemetry = { version = "0.1" } # Note: Check crates.io for latest # The OpenTelemetry API for creating spans -opentelemetry = { version = "0.30" } # Note: Update to latest. +opentelemetry = { version = "0.31" } ``` ### 2. Initialize the Tracer In your application's main function, initialize the Datadog tracer provider. The `tracing().init()` function automatically configures the tracer from environment variables. -
You must shut down the provider before your application exits to ensure all pending traces are flushed. -
- +
You must shut down the provider before your application exits to ensure all pending traces are flushed.
```rust - use datadog_opentelemetry; use opentelemetry::{global, trace::Tracer}; use std::time::Duration; @@ -63,7 +60,7 @@ fn main() { let tracer = global::tracer("my-component"); - tracer.in_span("my-operation", |cx| { + tracer.in_span("my-operation", |_cx| { // ... do work ... }); @@ -100,7 +97,7 @@ let tracer = global::tracer("my-component"); ### Create a span -Use `tracer.in_span` (from `opentelemetry::trace::Tracer`) to create a new span that is active for the duration of a closure. +Use `tracer.in_span` (from `opentelemetry::trace::Tracer`) to create a new span. The span is automatically ended when the closure finishes. ```rust use opentelemetry::{global, trace::Tracer}; @@ -108,11 +105,9 @@ use opentelemetry::{global, trace::Tracer}; fn do_work() { let tracer = global::tracer("my-component"); - tracer.in_span("operation_name", |cx| { + tracer.in_span("operation_name", |_cx| { // The span is active within this closure println!("Doing work..."); - - // Spans are automatically ended when the closure finishes }); } ``` @@ -127,11 +122,11 @@ use opentelemetry::{global, trace::Tracer}; fn parent_operation() { let tracer = global::tracer("my-component"); - tracer.in_span("parent_operation", |parent_span| { - // parent_span is active + tracer.in_span("parent_operation", |_cx| { + // The "parent_operation" span is now active on this thread - tracer.in_span("child_operation", |child_span| { - // child_span is active and is a child of parent_span + tracer.in_span("child_operation", |_cx| { + // This span is automatically parented to "parent_operation" println!("Doing child work..."); }); @@ -150,7 +145,7 @@ use opentelemetry::trace::{Span, Tracer}; fn do_work_with_active_span() { let tracer = opentelemetry::global::tracer("my-component"); - tracer.in_span("my-operation", |cx| { + tracer.in_span("my-operation", |_cx| { // A new span "my-operation" is now the active span. // You can retrieve it from the active context: let current_span = opentelemetry::trace::Span::current(); @@ -165,27 +160,23 @@ fn do_work_with_active_span() { ### Add span tags -Add attributes to a span using the `set_attribute` method. In OpenTelemetry, tags are called attributes. +Add attributes to a span using the `set_attribute` method. You must retrieve the span from the context `cx` to modify it. ```rust -use opentelemetry::trace::{Span, Tracer}; +use opentelemetry::trace::{Tracer, TraceContextExt}; // TraceContextExt is required for cx.span() use opentelemetry::KeyValue; fn add_tags_to_span() { let tracer = opentelemetry::global::tracer("my-component"); tracer.in_span("operation.with.tags", |cx| { + let span = cx.span(); // Retrieve the span from context + // Set attributes (tags) on the active span span.set_attribute(KeyValue::new("customer.id", "12345")); span.set_attribute(KeyValue::new("http.method", "GET")); span.set_attribute(KeyValue::new("is.test", true)); span.set_attribute(KeyValue::new("team.name", "backend")); - - // You can also set multiple attributes at once - span.set_attributes(vec![ - KeyValue::new("resource.name", "/users/list"), - KeyValue::new("db.system", "postgres"), - ]); }); } ``` @@ -195,13 +186,15 @@ fn add_tags_to_span() { Add time-stamped log messages to a span using the `add_event` method. ```rust -use opentelemetry::trace::{Span, Tracer}; +use opentelemetry::trace::{Tracer, TraceContextExt}; use opentelemetry::KeyValue; fn add_events_to_span() { let tracer = opentelemetry::global::tracer("my-component"); tracer.in_span("operation.with.events", |cx| { + let span = cx.span(); + // Add a simple event span.add_event("Data received", vec![]); @@ -235,3 +228,4 @@ For more information, see [Trace Context Propagation][2]. [1]: /tracing/trace_collection/library_config/rust [2]: /tracing/trace_collection/trace_context_propagation/?tab=rust +[3]: https://crates.io/crates/datadog-opentelemetry \ No newline at end of file diff --git a/content/en/tracing/trace_collection/trace_context_propagation/_index.md b/content/en/tracing/trace_collection/trace_context_propagation/_index.md index d1ecb94ae068a..835c669ec0543 100644 --- a/content/en/tracing/trace_collection/trace_context_propagation/_index.md +++ b/content/en/tracing/trace_collection/trace_context_propagation/_index.md @@ -656,28 +656,33 @@ Because there is no automatic instrumentation for Rust, you must manually propag - `HeaderExtractor` to **extract** a parent context from incoming request headers. - `HeaderInjector` to **inject** the current context into outbound request headers. -First, add `opentelemetry-http` to your `Cargo.toml`: +First, add `opentelemetry-http` to your `Cargo.toml`. ```toml [dependencies] # Provides HeaderInjector and HeaderExtractor -opentelemetry-http = "" +# Ensure this version matches your other opentelemetry dependencies +opentelemetry-http = "0.31" + +# Only required for the Hyper examples below +http-body-util = "0.1" ```
Use the same crate version for opentelemetry-http as the rest of your OpenTelemetry dependencies to avoid version conflicts.
### Injecting context (client side) -When making an HTTP request (for example, with `hyper`), inject the current span context into the request headers using `HeaderInjector`. +When making an HTTP request (for example, with `hyper` 1.0), inject the current span context into the request headers using `HeaderInjector`. ```rust use opentelemetry::{global, Context}; use opentelemetry_http::HeaderInjector; -use http::Request; -use hyper::Body; +use hyper::Request; +use http_body_util::Empty; +use hyper::body::Bytes; // HYPER example -fn build_outbound_request(url: &str) -> http::Result> { +fn build_outbound_request(url: &str) -> http::Result>> { let cx = Context::current(); // Build the request and inject headers in-place @@ -686,13 +691,15 @@ fn build_outbound_request(url: &str) -> http::Result> { prop.inject_context(&cx, &mut HeaderInjector(builder.headers_mut().unwrap())) }); - builder.body(Body::empty()) + builder.body(Empty::::new()) } ``` ### Extracting context (server side) -When receiving an HTTP request (for example, with `hyper`), extract the trace context from the headers using `HeaderExtractor` to parent your new span. +When receiving an HTTP request, extract the trace context from the headers using `HeaderExtractor`. + +When using async runtimes (like Tokio), you must attach the extracted context to the future so that it propagates correctly through the async task chain. ```rust use opentelemetry::{ @@ -701,23 +708,26 @@ use opentelemetry::{ Context, }; use opentelemetry_http::HeaderExtractor; -use hyper::{Body, Request, Response}; +use hyper::{Request, Response}; +use hyper::body::Incoming; +use http_body_util::Full; +use hyper::body::Bytes; // Utility function to extract context from a hyper request -fn extract_context(req: &Request) -> Context { +fn extract_context(req: &Request) -> Context { global::get_text_map_propagator(|propagator| { propagator.extract(&HeaderExtractor(req.headers())) }) } // A placeholder for your actual request handling logic -async fn your_handler_logic() -> Response { +async fn your_handler_logic() -> Response> { // ... your logic ... - Response::new(Body::from("Hello, World!")) + Response::new(Full::new(Bytes::from("Hello, World!"))) } // HYPER example -async fn hyper_handler(req:Request) -> Response { +async fn hyper_handler(req: Request) -> Response> { // Extract the parent context from the incoming headers let parent_cx = extract_context(&req); @@ -730,11 +740,11 @@ async fn hyper_handler(req:Request) -> Response { .start_with_context(tracer, &parent_cx); // Create a new context with the new server span + // This is critical for async propagation let cx = parent_cx.with_span(server_span); - // Attach the new context to the future. - // This makes 'server_span' the current span for 'your_handler_logic' - // and any calls it makes. + // Attach the new context to the future using .with_context(cx) + // This makes the span active for the duration of the handler your_handler_logic().with_context(cx).await } ``` From 422c92420b3da51d90a077605c6ebe6848df71b7 Mon Sep 17 00:00:00 2001 From: Brett Blue Date: Wed, 19 Nov 2025 09:13:19 -0700 Subject: [PATCH 20/20] Add Rust to baggage table. --- .../automatic_instrumentation/dd_libraries/rust.md | 2 +- .../trace_collection/trace_context_propagation/_index.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/content/en/tracing/trace_collection/automatic_instrumentation/dd_libraries/rust.md b/content/en/tracing/trace_collection/automatic_instrumentation/dd_libraries/rust.md index 6775675add926..0e4d884f73042 100644 --- a/content/en/tracing/trace_collection/automatic_instrumentation/dd_libraries/rust.md +++ b/content/en/tracing/trace_collection/automatic_instrumentation/dd_libraries/rust.md @@ -25,7 +25,7 @@ The Rust SDK does not provide automatic instrumentation. Tracing is achieved by ## Overview -Datadog provides tracing support for Rust applications through the []`datadog-opentelemetry` crate][5], which is built on the OpenTelemetry (OTel) API and SDK. +Datadog provides tracing support for Rust applications through the [`datadog-opentelemetry` crate][5], which is built on the OpenTelemetry (OTel) API and SDK. To get started, make sure you have [installed and configured the Datadog Agent][4]. diff --git a/content/en/tracing/trace_collection/trace_context_propagation/_index.md b/content/en/tracing/trace_collection/trace_context_propagation/_index.md index 835c669ec0543..82bd5793435c9 100644 --- a/content/en/tracing/trace_collection/trace_context_propagation/_index.md +++ b/content/en/tracing/trace_collection/trace_context_propagation/_index.md @@ -800,7 +800,8 @@ Support for baggage as span tags was introduced in the following releases: | .NET | 3.23.0 | | Node | 5.54.0 | | PHP | 1.10.0 | -| C++/Proxy | Not yet supported | +| C++/Proxy | Not supported | +| Rust | Not supported | ## Further reading