Skip to main content

opentelemetry-jaeger-propagator

Version: 0.31.0 The opentelemetry-jaeger-propagator crate provides the Jaeger propagation format for distributing trace context across service boundaries.
For exporting traces to Jaeger, use the OTLP exporter instead. Jaeger natively supports OTLP since version 1.35. This crate is specifically for propagation format compatibility with existing Jaeger deployments.

Installation

[dependencies]
opentelemetry-jaeger-propagator = "0.31"

Feature Flags

  • internal-logs: Enable internal logging (enabled by default)

What is Jaeger Propagation?

Jaeger propagation uses the B3 propagation format to transmit trace context via HTTP headers. This allows services instrumented with different SDKs to maintain trace continuity.

B3 Header Formats

Single Header (b3):
b3: {TraceId}-{SpanId}-{SamplingState}-{ParentSpanId}
Multiple Headers (X-B3-*):
X-B3-TraceId: {TraceId}
X-B3-SpanId: {SpanId}
X-B3-ParentSpanId: {ParentSpanId}
X-B3-Sampled: {SamplingState}

Quick Start

Set as Global Propagator

use opentelemetry::global;
use opentelemetry_jaeger_propagator::Propagator;

// Set Jaeger propagator as global
global::set_text_map_propagator(Propagator::new());

Sending Requests

use opentelemetry::{global, trace::{Tracer, TraceContextExt}, Context};
use std::collections::HashMap;

let tracer = global::tracer("my-service");
let span = tracer.start("send_request");
let cx = Context::current_with_span(span);

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

// headers now contains: b3: {trace-id}-{span-id}-1
// Send request with headers...

Receiving Requests

use opentelemetry::{global, trace::Tracer};
use std::collections::HashMap;

let headers: HashMap<String, String> = /* incoming headers */;

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

// Create child span with extracted parent
let tracer = global::tracer("my-service");
let span = tracer
    .span_builder("handle_request")
    .start_with_context(&tracer, &parent_cx);

Core Types

Propagator
struct
Jaeger/B3 trace context propagator
use opentelemetry_jaeger_propagator::Propagator;

// Create with default settings (multiple headers)
let propagator = Propagator::new();

// Or create with custom header name
let propagator = Propagator::with_custom_header("custom-trace-header");

Configuration

Default Propagator

Uses multiple B3 headers (X-B3-*):
use opentelemetry_jaeger_propagator::Propagator;

let propagator = Propagator::new();
// Reads/writes: X-B3-TraceId, X-B3-SpanId, X-B3-Sampled, X-B3-ParentSpanId

Custom Header Name

Use a custom header name:
use opentelemetry_jaeger_propagator::Propagator;

let propagator = Propagator::with_custom_header("my-trace-header");
// Reads/writes: my-trace-header: {trace-id}-{span-id}-{sampled}

Complete Example

HTTP Client

use opentelemetry::{global, trace::{Tracer, TraceContextExt}, Context};
use opentelemetry_jaeger_propagator::Propagator;
use std::collections::HashMap;

// Setup
global::set_text_map_propagator(Propagator::new());

let tracer = global::tracer("http-client");

// Before sending request
let mut span = tracer.start("GET /api/users");
let cx = Context::current_with_span(span);

let mut headers = HashMap::new();
global::get_text_map_propagator(|propagator| {
    propagator.inject_context(&cx, &mut headers);
});

// Send HTTP request with headers
// GET /api/users
// X-B3-TraceId: 80f198ee56343ba864fe8b2a57d3eff7
// X-B3-SpanId: e457b5a2e4d86bd1
// X-B3-Sampled: 1

HTTP Server

use opentelemetry::{global, trace::Tracer};
use opentelemetry_jaeger_propagator::Propagator;
use std::collections::HashMap;

// Setup
global::set_text_map_propagator(Propagator::new());

fn handle_request(headers: HashMap<String, String>) {
    // Extract parent context
    let parent_cx = global::get_text_map_propagator(|propagator| {
        propagator.extract(&headers)
    });

    // Create span with parent context
    let tracer = global::tracer("http-server");
    let span = tracer
        .span_builder("handle_request")
        .start_with_context(&tracer, &parent_cx);
    
    // Process request with active span...
}

Integration with HTTP Frameworks

With opentelemetry-http

use opentelemetry::{global, trace::Tracer};
use opentelemetry_http::{HeaderExtractor, HeaderInjector};
use opentelemetry_jaeger_propagator::Propagator;
use http::HeaderMap;

// Set propagator
global::set_text_map_propagator(Propagator::new());

// Extract from HTTP request
let headers: HeaderMap = /* ... */;
let parent_cx = global::get_text_map_propagator(|propagator| {
    propagator.extract(&HeaderExtractor(&headers))
});

// Inject into HTTP request
let mut headers = HeaderMap::new();
let cx = /* current context */;
global::get_text_map_propagator(|propagator| {
    propagator.inject_context(&cx, &mut HeaderInjector(&mut headers));
});

When to Use Jaeger Propagator

Legacy Systems

Interoperating with services using Jaeger’s B3 format

Mixed Environments

Services using different instrumentation libraries

Migration

Transitioning from Jaeger to OpenTelemetry

Compatibility

Need to maintain compatibility with existing Jaeger infrastructure

Alternative Propagators

OpenTelemetry supports multiple propagation formats:
  • W3C Trace Context (recommended): opentelemetry::propagation::TraceContextPropagator
  • W3C Baggage: opentelemetry_sdk::propagation::BaggagePropagator
  • Jaeger: This crate
  • Zipkin B3: opentelemetry_zipkin::Propagator
use opentelemetry::global;
use opentelemetry_sdk::propagation::TraceContextPropagator;

// Use W3C Trace Context (recommended for new deployments)
global::set_text_map_propagator(TraceContextPropagator::new());

Composite Propagators

Use multiple propagators for compatibility:
use opentelemetry::{global, propagation::TextMapCompositePropagator};
use opentelemetry_sdk::propagation::{
    TraceContextPropagator, 
    BaggagePropagator
};
use opentelemetry_jaeger_propagator::Propagator as JaegerPropagator;

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

global::set_text_map_propagator(composite);

Exporting to Jaeger

This crate only handles propagation. To export traces to Jaeger, use the OTLP exporter:
use opentelemetry::global;
use opentelemetry_otlp::SpanExporter;
use opentelemetry_jaeger_propagator::Propagator;

// Propagator for context propagation
global::set_text_map_propagator(Propagator::new());

// OTLP exporter for sending traces to Jaeger
let exporter = SpanExporter::builder()
    .with_tonic()
    .with_endpoint("http://localhost:4317") // Jaeger OTLP endpoint
    .build()?;

let provider = opentelemetry_sdk::trace::SdkTracerProvider::builder()
    .with_batch_exporter(exporter)
    .build();

Documentation

Full API Documentation

View complete API reference on docs.rs

Jaeger Propagation Format

Official Jaeger propagation documentation

Minimum Rust Version

MSRV: 1.75.0

Build docs developers (and LLMs) love