Tracing
rust-camel integrates with OpenTelemetry for distributed tracing,
metrics, and log export. OtelService owns the lifecycle of the
global OTel providers.
OtelService
OtelService is a Lifecycle implementation. It installs and owns
the process-global OpenTelemetry tracer, meter, and logger providers.
Keep one active instance per process.
Configure the OTLP endpoint and service identity with OtelConfig:
// Create OpenTelemetry configuration
// Points to the OTLP collector (grafana/otel-lgtm) running locally
// metrics_interval_ms=15000 exports metrics every 15s (default 60s is too slow for demos)
let otel_config = OtelConfig::new("http://localhost:4317", "rust-camel-otel-demo")
.with_metrics_interval_ms(15000);
Note: Service registration is Rust API only. YAML routes compile to the same
RouteDefinition. The service wiring stays in application code.
Create the service and register it with the context:
// Create the OpenTelemetry service
// OtelService manages:
// - Global TracerProvider (spans exported via OTLP)
// - Global MeterProvider (metrics exported via OTLP)
// - Global LoggerProvider + Log bridge (logs exported via OTLP)
// - as_metrics_collector() for automatic route metrics
let mut otel_service = OtelService::new(otel_config);
// Initialize tracing subscriber with both stdout and OTel log bridge
let logger_provider = otel_service.init_logger_provider()?;
let otel_layer =
opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge::new(&logger_provider);
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
tracing_subscriber::registry()
.with(tracing_subscriber::fmt::layer())
.with(otel_layer)
.init();
// Build CamelContext with the OtelService as a lifecycle service.
// with_lifecycle() auto-registers the metrics collector from OtelService.
let mut ctx = CamelContext::builder()
.build()
.await
.unwrap() // allow-unwrap
.with_lifecycle(otel_service)
.with_tracer_config(TracerConfig {
enabled: true,
detail_level: DetailLevel::Medium,
outputs: TracerOutputs {
stdout: StdoutOutput {
enabled: false, // suppress noisy JSON to stdout
..Default::default()
},
file: None,
},
..Default::default()
})
.await;
Note: Service registration is Rust API only. YAML routes compile to the same
RouteDefinition. The service wiring stays in application code.
with_lifecycle() auto-registers the metrics collector from
OtelService::as_metrics_collector(). The runtime records route-level
metrics automatically.
Operational invariants
- One global provider set.
OtelService::start()installs providers throughopentelemetry::global. OpenTelemetry global setters replace the active provider and provide no reset API. Starting a second service can detach the first from global lookups. Its exporter tasks stay alive until you stop it. Keep one activeOtelServiceper process. - Start before metric use.
OtelMetricsresolves itsMeteron first use and caches it. Recording beforeOtelService::start()binds that instance to the no-op provider. Later startup does not replace the cached meter. Start the service before you register or record metrics.
See camel-otel CONTEXT.md for the full operational invariants.
Propagation helpers
The crate provides helpers that bridge W3C trace context between transport headers and an Exchange:
| Helper | Action |
|---|---|
extract_context | extract trace context from transport headers |
inject_context | inject trace context into transport headers |
extract_into_exchange | extract trace context into an Exchange |
inject_from_exchange | inject trace context from an Exchange |
Related decisions
- ADR-0007 motivates graceful provider shutdown. OpenTelemetry global ownership makes shutdown order operationally significant.
- ADR-0012 defines the log-policy classification for service start failures.
Reference: camel-otel crate