> ## 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.

# OTLP HTTP Exporter

> Export telemetry data via OTLP over HTTP to observability backends

## Overview

The OTLP (OpenTelemetry Protocol) HTTP exporter allows you to send traces, metrics, and logs to any OpenTelemetry-compatible backend over HTTP. This is the recommended protocol for production deployments.

## Dependencies

Add these dependencies to your `Cargo.toml`:

```toml Cargo.toml theme={null}
[dependencies]
opentelemetry = { version = "*" }
opentelemetry_sdk = { version = "*", features = ["rt-tokio"] }
opentelemetry-otlp = { version = "*", features = ["http-proto", "reqwest-client"] }
tokio = { version = "1", features = ["full"] }
```

## Exporting Traces via HTTP

<Steps>
  <Step title="Configure OTLP HTTP Exporter">
    Set up the OTLP exporter with HTTP transport.

    ```rust theme={null}
    use opentelemetry::global;
    use opentelemetry_sdk::trace::SdkTracerProvider;
    use opentelemetry_otlp::{Protocol, WithExportConfig};

    fn init_tracer() -> SdkTracerProvider {
        let exporter = opentelemetry_otlp::SpanExporter::builder()
            .with_http()
            .with_protocol(Protocol::HttpBinary) // or Protocol::HttpJson
            .with_endpoint("http://localhost:4318/v1/traces")
            .build()
            .expect("Failed to create OTLP exporter");

        let provider = SdkTracerProvider::builder()
            .with_batch_exporter(exporter, opentelemetry_sdk::runtime::Tokio)
            .build();

        global::set_tracer_provider(provider.clone());
        provider
    }
    ```
  </Step>

  <Step title="Configure Authentication">
    Add headers for authentication if required by your backend.

    ```rust theme={null}
    use opentelemetry_otlp::WithHttpConfig;
    use std::collections::HashMap;

    let mut headers = HashMap::new();
    headers.insert(
        "Authorization".to_string(),
        "Bearer YOUR_API_TOKEN".to_string(),
    );

    let exporter = opentelemetry_otlp::SpanExporter::builder()
        .with_http()
        .with_protocol(Protocol::HttpBinary)
        .with_endpoint("https://your-backend.com/v1/traces")
        .with_headers(headers)
        .build()
        .expect("Failed to create OTLP exporter");
    ```
  </Step>

  <Step title="Use the Tracer">
    Create and export spans as usual.

    ```rust theme={null}
    use opentelemetry::trace::{Tracer, SpanKind};

    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let tracer_provider = init_tracer();
        let tracer = global::tracer("my-service");

        let span = tracer
            .span_builder("operation")
            .with_kind(SpanKind::Internal)
            .start(&tracer);

        // Your application logic

        tracer_provider.shutdown()?;
        Ok(())
    }
    ```
  </Step>
</Steps>

## Exporting Metrics via HTTP

```rust theme={null}
use opentelemetry::global;
use opentelemetry_sdk::metrics::SdkMeterProvider;
use opentelemetry_otlp::WithExportConfig;

fn init_metrics() -> SdkMeterProvider {
    let exporter = opentelemetry_otlp::MetricExporter::builder()
        .with_http()
        .with_protocol(Protocol::HttpBinary)
        .with_endpoint("http://localhost:4318/v1/metrics")
        .build()
        .expect("Failed to create OTLP metrics exporter");

    let provider = SdkMeterProvider::builder()
        .with_periodic_exporter(exporter, opentelemetry_sdk::runtime::Tokio)
        .build();

    global::set_meter_provider(provider.clone());
    provider
}
```

## Exporting Logs via HTTP

```rust theme={null}
use opentelemetry_sdk::logs::SdkLoggerProvider;
use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge;
use tracing_subscriber::prelude::*;

fn init_logs() -> SdkLoggerProvider {
    let exporter = opentelemetry_otlp::LogExporter::builder()
        .with_http()
        .with_protocol(Protocol::HttpBinary)
        .with_endpoint("http://localhost:4318/v1/logs")
        .build()
        .expect("Failed to create OTLP log exporter");

    let provider = SdkLoggerProvider::builder()
        .with_batch_exporter(exporter, opentelemetry_sdk::runtime::Tokio)
        .build();

    let otel_layer = OpenTelemetryTracingBridge::new(&provider);
    tracing_subscriber::registry().with(otel_layer).init();

    provider
}
```

## Protocol Options

The OTLP HTTP exporter supports two protocols:

<CodeGroup>
  ```rust HTTP Binary (Protobuf) theme={null}
  use opentelemetry_otlp::Protocol;

  // More efficient, smaller payload size
  .with_protocol(Protocol::HttpBinary)
  ```

  ```rust HTTP JSON theme={null}
  use opentelemetry_otlp::Protocol;

  // Human-readable, easier debugging
  .with_protocol(Protocol::HttpJson)
  ```
</CodeGroup>

<Tip>
  Use `Protocol::HttpBinary` for production as it's more efficient. Use `Protocol::HttpJson` for development and debugging.
</Tip>

## Common Backend Endpoints

### Local OpenTelemetry Collector

```rust theme={null}
// Traces
.with_endpoint("http://localhost:4318/v1/traces")

// Metrics
.with_endpoint("http://localhost:4318/v1/metrics")

// Logs
.with_endpoint("http://localhost:4318/v1/logs")
```

### Cloud Providers

Most cloud providers require custom endpoints and authentication headers:

```rust theme={null}
let mut headers = HashMap::new();
headers.insert("X-API-Key".to_string(), env::var("OTEL_API_KEY")?);;

let exporter = opentelemetry_otlp::SpanExporter::builder()
    .with_http()
    .with_endpoint("https://otlp.your-provider.com/v1/traces")
    .with_headers(headers)
    .build()?;
```

## Configuration via Environment Variables

The OTLP exporter respects standard OpenTelemetry environment variables:

```bash theme={null}
# Endpoint (automatically appends signal-specific paths)
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318

# Signal-specific endpoints
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4318/v1/traces
export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://localhost:4318/v1/metrics
export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://localhost:4318/v1/logs

# Headers (comma-separated key=value pairs)
export OTEL_EXPORTER_OTLP_HEADERS="api-key=secret,x-custom-header=value"

# Protocol
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf  # or http/json

# Timeout (milliseconds)
export OTEL_EXPORTER_OTLP_TIMEOUT=10000
```

<Note>
  When using environment variables, you can create exporters without explicit configuration in code. The SDK will automatically read these values.
</Note>

## Batch Configuration

Configure batching behavior for better performance:

```rust theme={null}
use opentelemetry_sdk::trace::BatchConfig;
use std::time::Duration;

let batch_config = BatchConfig::default()
    .with_max_queue_size(2048)
    .with_max_export_batch_size(512)
    .with_scheduled_delay(Duration::from_secs(5));

let provider = SdkTracerProvider::builder()
    .with_batch_exporter(
        exporter,
        opentelemetry_sdk::runtime::Tokio,
    )
    .with_batch_config(batch_config)
    .build();
```

## Error Handling

```rust theme={null}
use opentelemetry_otlp::Error;

let exporter_result = opentelemetry_otlp::SpanExporter::builder()
    .with_http()
    .with_endpoint("http://localhost:4318/v1/traces")
    .build();

match exporter_result {
    Ok(exporter) => {
        // Use exporter
    }
    Err(Error::NoValidEndpoint) => {
        eprintln!("Invalid OTLP endpoint");
    }
    Err(e) => {
        eprintln!("OTLP exporter error: {}", e);
    }
}
```

<Tip>
  Always handle exporter initialization errors gracefully. In production, you may want to fall back to a stdout exporter or disable telemetry if the backend is unavailable.
</Tip>
