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:
[ 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
Configure OTLP HTTP Exporter
Set up the OTLP exporter with HTTP transport. 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
}
Configure Authentication
Add headers for authentication if required by your backend. 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" );
Use the Tracer
Create and export spans as usual. 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 (())
}
Exporting Metrics via HTTP
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
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:
HTTP Binary (Protobuf)
HTTP JSON
use opentelemetry_otlp :: Protocol ;
// More efficient, smaller payload size
. with_protocol ( Protocol :: HttpBinary )
Use Protocol::HttpBinary for production as it’s more efficient. Use Protocol::HttpJson for development and debugging.
Common Backend Endpoints
Local OpenTelemetry Collector
// 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:
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:
# 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
When using environment variables, you can create exporters without explicit configuration in code. The SDK will automatically read these values.
Batch Configuration
Configure batching behavior for better performance:
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
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 );
}
}
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.