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
"""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.
Related
Was this page helpful?