> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/open-telemetry/opentelemetry-rust/llms.txt
> Use this file to discover all available pages before exploring further.

# Context propagators

> Propagate context across service boundaries using TextMapPropagator and standard formats

## Overview

Propagators are used to extract and inject context data across service boundaries. They enable distributed tracing by passing trace context and baggage between services using standard formats like W3C Trace Context.

<CardGroup cols={2}>
  <Card title="Injector" icon="arrow-up-from-bracket">
    Injects context into outgoing requests
  </Card>

  <Card title="Extractor" icon="arrow-down-to-bracket">
    Extracts context from incoming requests
  </Card>
</CardGroup>

## TextMapPropagator

The `TextMapPropagator` trait defines the interface for context propagation using string key-value pairs:

```rust theme={null}
pub trait TextMapPropagator {
    /// Injects context into a carrier
    fn inject_context(&self, cx: &Context, injector: &mut dyn Injector);
    
    /// Extracts context from a carrier
    fn extract_with_context(&self, cx: &Context, extractor: &dyn Extractor) -> Context;
    
    /// Returns the fields set by this propagator
    fn fields(&self) -> Vec<String>;
}
```

## Built-in propagators

OpenTelemetry Rust provides several standard propagators:

### W3C Trace Context

The default propagator implementing the [W3C Trace Context](https://www.w3.org/TR/trace-context/) specification:

```rust theme={null}
use opentelemetry::global;
use opentelemetry_sdk::propagation::TraceContextPropagator;

// Set the global propagator
global::set_text_map_propagator(TraceContextPropagator::new());
```

### W3C Baggage

Propagates baggage according to the [W3C Baggage](https://www.w3.org/TR/baggage/) specification:

```rust theme={null}
use opentelemetry_sdk::propagation::BaggagePropagator;

global::set_text_map_propagator(BaggagePropagator::new());
```

### Composite propagator

Combine multiple propagators to support different formats:

```rust theme={null}
use opentelemetry::global;
use opentelemetry::propagation::TextMapCompositePropagator;
use opentelemetry_sdk::propagation::{TraceContextPropagator, BaggagePropagator};

let propagator = TextMapCompositePropagator::new(vec![
    Box::new(TraceContextPropagator::new()),
    Box::new(BaggagePropagator::new()),
]);

global::set_text_map_propagator(propagator);
```

### Jaeger propagator

For Jaeger-specific propagation format, use the separate `opentelemetry-jaeger-propagator` crate:

```rust theme={null}
use opentelemetry_jaeger_propagator::Propagator as JaegerPropagator;

global::set_text_map_propagator(JaegerPropagator::new());
```

## Injector and Extractor traits

### Injector

The `Injector` trait is implemented by carriers that can have context injected into them:

```rust theme={null}
pub trait Injector {
    /// Add a key and value to the underlying data
    fn set(&mut self, key: &str, value: String);
    
    /// Hint to reserve capacity for additional entries
    fn reserve(&mut self, additional: usize) {}
}
```

**HashMap implementation:**

```rust theme={null}
use std::collections::HashMap;
use opentelemetry::propagation::Injector;

let mut headers = HashMap::new();
headers.set("traceparent", "00-trace-id-span-id-01".to_string());
```

### Extractor

The `Extractor` trait is implemented by carriers that can have context extracted from them:

```rust theme={null}
pub trait Extractor {
    /// Get a value from a key
    fn get(&self, key: &str) -> Option<&str>;
    
    /// Collect all keys
    fn keys(&self) -> Vec<&str>;
    
    /// Get all values from a key
    fn get_all(&self, key: &str) -> Option<Vec<&str>>;
}
```

## HTTP propagation example

### Client-side injection

Inject context into HTTP headers:

```rust theme={null}
use opentelemetry::global;
use opentelemetry::Context;
use std::collections::HashMap;

// Get the current context with active span
let cx = Context::current();

// Prepare headers
let mut headers = HashMap::new();

// Inject context into headers
global::get_text_map_propagator(|propagator| {
    propagator.inject_context(&cx, &mut headers);
});

// Use headers in HTTP request
for (key, value) in headers {
    // request.header(key, value);
}
```

### Server-side extraction

Extract context from incoming HTTP headers:

```rust theme={null}
use opentelemetry::global;
use opentelemetry::Context;
use std::collections::HashMap;

// Extract headers from incoming request
let headers: HashMap<String, String> = get_request_headers();

// Extract context from headers
let parent_cx = global::get_text_map_propagator(|propagator| {
    propagator.extract(&headers)
});

// Use the extracted context to create child spans
let tracer = global::tracer("my-service");
let span = tracer
    .span_builder("handle_request")
    .start_with_context(&tracer, &parent_cx);
```

## Custom propagator

Implement a custom propagator for non-standard formats:

```rust theme={null}
use opentelemetry::propagation::{Extractor, Injector, TextMapPropagator};
use opentelemetry::Context;

struct CustomPropagator;

impl TextMapPropagator for CustomPropagator {
    fn inject_context(&self, cx: &Context, injector: &mut dyn Injector) {
        // Extract trace context from cx
        // Format according to custom protocol
        // Inject into carrier
        injector.set("custom-trace-id", "...".to_string());
    }
    
    fn extract_with_context(
        &self,
        cx: &Context,
        extractor: &dyn Extractor,
    ) -> Context {
        // Extract custom headers
        if let Some(trace_id) = extractor.get("custom-trace-id") {
            // Parse trace context
            // Create new context with extracted data
        }
        cx.clone()
    }
    
    fn fields(&self) -> Vec<String> {
        vec!["custom-trace-id".to_string()]
    }
}
```

## Best practices

<Note>
  **Always use composite propagator** - Combine TraceContext and Baggage propagators to support both trace context and custom attributes.
</Note>

<Tip>
  **Case-insensitive extraction** - The HashMap implementations handle case-insensitive header names automatically by converting to lowercase.
</Tip>

<Warning>
  **Security consideration** - Be cautious with baggage content as it propagates across all services. Avoid putting sensitive data in baggage.
</Warning>

## Related

<CardGroup cols={2}>
  <Card title="Context propagation" icon="arrows-rotate" href="/concepts/context-propagation">
    Learn about context flow
  </Card>

  <Card title="Baggage" icon="suitcase" href="/advanced/baggage">
    Add custom attributes to context
  </Card>
</CardGroup>
