# OpenTelemetry Setup (/sdks/rust/how-to/observability/opentelemetry-setup)



## Overview [#overview]

**OpenTelemetry integration** wires the SDK's messaging operations into your tracing and metrics pipeline without hand-instrumenting every call site. In a distributed system where a message might be published by one service, queued, and consumed by three others, per-call logging tells you almost nothing — you need spans that correlate across process boundaries and latency/error visibility broken out by channel and operation. The Rust SDK takes a deliberately minimal approach here: it has **no built-in OpenTelemetry dependency**, only the lightweight [`tracing`](https://docs.rs/tracing) crate, which keeps the SDK's dependency footprint small regardless of whether your application uses OTel at all.

The SDK emits `tracing` spans and events for connections, sends, receives, and errors. Your application bridges those events to an OpenTelemetry backend by registering an `OpenTelemetryLayer` (from [`tracing-opentelemetry`](https://docs.rs/tracing-opentelemetry)) on the global `tracing_subscriber` — once wired up, every SDK-emitted event flows into your OTel pipeline automatically alongside your own instrumented code. &#x2A;*Gotchas:** the subscriber must be initialized *before* the KubeMQ client is created, or early connection spans are missed; the stdout exporter shown here is for local debugging only — production needs a real OTLP or Jaeger exporter; and because the bridge lives entirely in your application, not the SDK, a missing or misconfigured subscriber fails silently — the client works fine, it just emits no telemetry.

## Prerequisites [#prerequisites]

* KubeMQ server running on `localhost:50000`
* Rust SDK installed (`cargo add kubemq`)
* Bridge crates in your application (`cargo add tracing-subscriber tracing-opentelemetry opentelemetry_sdk opentelemetry-stdout`)

## Code [#code]

```rust title="main.rs"
use kubemq::prelude::*;
use kubemq::EventBuilder;
use std::time::Duration;

// The KubeMQ Rust SDK emits `tracing` events for each operation.
// To forward those events to OpenTelemetry you wire up a tracing subscriber
// that includes the tracing-opentelemetry layer in your *application*:
//
//   use opentelemetry_sdk::trace::SdkTracerProvider;
//   use opentelemetry_stdout::SpanExporter;
//   use tracing_opentelemetry::OpenTelemetryLayer;
//   use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
//
//   let exporter = SpanExporter::default();
//   let provider = SdkTracerProvider::builder()
//       .with_simple_exporter(exporter)
//       .build();
//   let tracer = provider.tracer("kubemq-app");
//
//   tracing_subscriber::registry()
//       .with(OpenTelemetryLayer::new(tracer))
//       .init();
//
// After that, all `tracing` events emitted by the SDK (and your own
// instrumented code) flow into the OpenTelemetry pipeline automatically.

#[tokio::main]
async fn main() -> kubemq::Result<()> {
    // Initialise a minimal tracing subscriber so SDK events appear on stdout.
    // Replace this with the OpenTelemetry setup above for production use.
    tracing_subscriber::fmt::init();

    let client = KubemqClient::builder()
        .host("localhost")
        .port(50000)
        .build()
        .await?;

    let event = EventBuilder::new()
        .channel("rust-observability.otel-example")
        .body(b"traced-event".to_vec())
        .metadata("otel-demo")
        .build();

    client.send_event(event).await?;
    println!("Event sent — tracing events emitted to subscriber");

    tokio::time::sleep(Duration::from_secs(1)).await;
    client.close().await?;
    Ok(())
}
```

## How It Works [#how-it-works]

* The KubeMQ Rust SDK depends only on the `tracing` crate for diagnostics — there is no OpenTelemetry dependency inside the SDK itself.
* The SDK emits `tracing` spans and events for connections, sends, receives, and errors.
* To route those events to an OTel backend, add `tracing-opentelemetry` to your application and register an `OpenTelemetryLayer` on the global tracing subscriber (see the commented setup above).
* For production, replace the stdout exporter (`opentelemetry-stdout`) with an OTLP exporter targeting Jaeger, Zipkin, or any OTel-compatible collector.
* Review timeouts, channel names, and client IDs before running against shared environments.
* Run the program while the server from the prerequisites is available.

## Related [#related]

* [Rust SDK Reference](/sdks/rust/reference/client)
