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..7e493f8a523ed
--- /dev/null
+++ b/content/en/tracing/trace_collection/compatibility/rust.md
@@ -0,0 +1,47 @@
+---
+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 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].
+
+## Language and library support
+
+The Rust SDK relies on specific versions of the Rust compiler and the OpenTelemetry crate.
+
+| Component | Requirement |
+|---|---|
+| **Rust Version** | 1.84 (MSRV) |
+| **OpenTelemetry Crate** | Version 0.31 |
+
+## 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 5b2a4f1179bd9..2a88fc5b03b38 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.'
+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/'
+ 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,226 @@ 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.
+{{< 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.
+
+Because this library is built on OpenTelemetry, you 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" } # Note: Update to latest.
+
+# The OpenTelemetry API for creating spans
+opentelemetry = { version = "0.30" } # Note: Update to latest.
+```
+
+### 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", |cx| {
+ // 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", |cx| {
+ // '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", |cx| {
+ // 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", |cx| {
+ // 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/?tab=rust
\ No newline at end of file
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..036137d163b77
--- /dev/null
+++ b/content/en/tracing/trace_collection/library_config/rust.md
@@ -0,0 +1,147 @@
+---
+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_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`.
+
+`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.
+
+`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`. 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**: `ERROR`
+: Sets the internal log level for the tracer. Valid values: `DEBUG`, `INFO`, `WARN`, `ERROR`.
+
+## Sampling
+
+`DD_TRACE_SAMPLING_RULES`
+: **Default**: `(none)`
+: 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**: `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 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
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..d1ecb94ae068a 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
@@ -622,6 +624,126 @@ void SetHeaderValues(MessageHeaders headers, string name, string value)
{{% /tab %}}
+{{% tab "Rust" %}}
+
+The Datadog Rust SDK is in Preview.
+
+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 injection and extraction
+
+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.
+
+First, add `opentelemetry-http` to your `Cargo.toml`:
+
+```toml
+[dependencies]
+# Provides HeaderInjector and HeaderExtractor
+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`.
+
+```rust
+use opentelemetry::{global, Context};
+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 `hyper`), extract the trace context from the headers using `HeaderExtractor` to parent your new span.
+
+```rust
+use opentelemetry::{
+ global,
+ trace::{Span, FutureExt, SpanKind, Tracer},
+ Context,
+};
+use opentelemetry_http::HeaderExtractor;
+use hyper::{Body, Request, Response};
+
+// 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()))
+ })
+}
+
+// A placeholder for your actual request handling logic
+async fn your_handler_logic() -> Response {
+ // ... your logic ...
+ Response::new(Body::from("Hello, World!"))
+}
+
+// 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);
+
+ // 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
+}
+```
+
+[1]: #datadog-format
+[2]: https://www.w3.org/TR/trace-context/
+
+{{% /tab %}}
+
{{< /tabs >}}
## Custom header formats
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 @@
+