KubeMQ
Client SDKsPythonHow-to guidesObservability

OpenTelemetry Setup

Configure OpenTelemetry tracing and metrics for a KubeMQ Python client to observe messaging operations.

Overview

OpenTelemetry integration wires the client'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 metrics broken out by channel and operation. Instrumenting that by hand around every publish_event or subscribe call is tedious and easy to get inconsistent; letting the client do it guarantees uniform coverage.

ClientConfig accepts tracer_provider and meter_provider from the OpenTelemetry SDK. Once set, every gRPC operation — publish, subscribe, send, receive — is automatically instrumented with traces and metrics following OpenTelemetry semantic conventions, so you write no tracing code in your business logic. max_channel_cardinality and channel_allowlist bound the number of unique label combinations tracked, which matters once channel names become dynamic. Gotchas: instrumentation is inert until you attach a real exporter (OTLP, Jaeger) to the provider — the console exporters shown here export nowhere useful in production; the optional otel extra must be installed or the client silently falls back to uninstrumented operation; and forgetting to call shutdown() on the providers drops the last in-flight batch of spans and metrics.

Prerequisites

  • KubeMQ server running on localhost:50000
  • Python SDK installed (pip install kubemq)

Code

opentelemetry_setup.py
"""Example: OpenTelemetry setup — configure tracing and metrics with OTel providers.

Requires the optional 'otel' dependency:
    pip install kubemq[otel]
    pip install opentelemetry-sdk opentelemetry-exporter-otlp
"""

from __future__ import annotations

import asyncio

from kubemq import ClientConfig
from kubemq import AsyncPubSubClient, EventMessage

# OpenTelemetry imports — require optional otel dependency
try:
    from opentelemetry import trace
    from opentelemetry.sdk.trace import TracerProvider
    from opentelemetry.sdk.trace.export import SimpleSpanProcessor, ConsoleSpanExporter
    from opentelemetry.sdk.metrics import MeterProvider
    from opentelemetry.sdk.metrics.export import ConsoleMetricExporter, PeriodicExportingMetricReader

    HAS_OTEL = True
except ImportError:
    HAS_OTEL = False


async def main() -> None:
    if not HAS_OTEL:
        print(
            "OpenTelemetry SDK not installed. Install with:\n"
            "  pip install kubemq[otel] opentelemetry-sdk"
        )
        print("\nShowing configuration pattern without actual OTel providers:")

        # Even without OTel SDK installed, you can still use the config fields
        config = ClientConfig(
            address="localhost:50000",
            client_id="python-observability-opentelemetry-setup-client",
            tracer_provider=None,
            meter_provider=None,
        )
        print(f"Config created: {config}")
        return

    # Set up OpenTelemetry tracing
    tracer_provider = TracerProvider()
    tracer_provider.add_span_processor(
        SimpleSpanProcessor(ConsoleSpanExporter())
    )
    trace.set_tracer_provider(tracer_provider)

    # Set up OpenTelemetry metrics
    metric_reader = PeriodicExportingMetricReader(
        ConsoleMetricExporter(),
        export_interval_millis=5000,
    )
    meter_provider = MeterProvider(metric_readers=[metric_reader])

    # Configure KubeMQ client with OTel providers
    config = ClientConfig(
        address="localhost:50000",
        client_id="python-observability-opentelemetry-setup-client",
        tracer_provider=tracer_provider,
        meter_provider=meter_provider,
        # Cardinality management for metrics
        max_channel_cardinality=100,
        channel_allowlist=["python-observability.*"],
    )

    async with AsyncPubSubClient(config=config) as client:
        info = await client.ping()
        print(f"Connected to {info.host} with OTel instrumentation")

        # Operations will emit traces and metrics
        await client.publish_event(
            EventMessage(
                channel="python-observability.opentelemetry-setup",
                body=b"Traced and metered message",
            )
        )
        print("Event sent with OpenTelemetry tracing and metrics")

    # Shutdown OTel providers
    tracer_provider.shutdown()
    meter_provider.shutdown()
    print("OTel providers shut down")


if __name__ == "__main__":
    asyncio.run(main())

How It Works

ClientConfig accepts tracer_provider and meter_provider from the OpenTelemetry SDK. When provided, the client instruments every gRPC operation — publish, subscribe, send, receive — with traces and metrics following the OpenTelemetry semantic conventions. max_channel_cardinality and channel_allowlist prevent metric cardinality explosions in environments with many dynamic channel names. If the otel extra is not installed, the graceful fallback prints a setup hint; the client still works, just without instrumentation.

Was this page helpful?

On this page