KubeMQ
Client SDKsC#How-to guidesObservability

OpenTelemetry Setup

Configure OpenTelemetry tracing and metrics for a KubeMQ C# client to observe messaging in production.

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 metrics broken out by channel and operation. Instrumenting that by hand around every SendEventAsync or subscribe call is tedious and easy to get inconsistent; letting the SDK's built-in diagnostics do it guarantees uniform coverage.

The SDK exposes tracing and metrics through the standard .NET diagnostics primitives: System.Diagnostics.ActivitySource (named "KubeMQ.Sdk") for spans and System.Diagnostics.Metrics.Meter (same name) for counters — no OpenTelemetry NuGet dependency is required in the core SDK itself. An ActivityListener with ShouldListenTo matched to "KubeMQ.Sdk" and Sample set to AllData captures every operation's spans and tags as they're created. Gotchas: an ActivityListener only sees activities created after it's registered, so it must be set up before the client is constructed; the console-based listener shown here is for local debugging only — production needs the OpenTelemetry SDK's AddSource("KubeMQ.Sdk") wired to a real exporter; and forgetting to keep the listener/provider alive for the process lifetime (e.g., disposing it early) silently stops span capture.

Prerequisites

  • KubeMQ server running on localhost:50000
  • C# SDK installed (dotnet add package KubeMQ.SDK.CSharp)

Code

Program.cs
// KubeMQ .NET SDK — Observability: OpenTelemetry Integration
//
// This example demonstrates how the SDK exposes tracing and metrics via
// System.Diagnostics.ActivitySource and System.Diagnostics.Metrics.Meter.
//
// The SDK uses "KubeMQ.Sdk" as the ActivitySource and Meter name.
// No OpenTelemetry NuGet dependency is required in the core SDK —
// the OTel collector picks up traces/metrics automatically when configured.
//
// Prerequisites:
//   - KubeMQ server running on localhost:50000
//   - dotnet run
//
// To export to an OTel collector, add OpenTelemetry packages to your app:
//   dotnet add package OpenTelemetry.Extensions.Hosting
//   dotnet add package OpenTelemetry.Exporter.Console
//   dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol

using KubeMQ.Sdk.Client;
using KubeMQ.Sdk.Events;
using System.Diagnostics;
using System.Text;

// Listen for KubeMQ SDK activities (traces)
using var listener = new ActivityListener
{
    ShouldListenTo = source => source.Name == "KubeMQ.Sdk",
    Sample = (ref ActivityCreationOptions<ActivityContext> _) => ActivitySamplingResult.AllData,
    ActivityStarted = activity =>
    {
        Console.WriteLine($"[Trace] Started: {activity.OperationName}");
        foreach (var tag in activity.Tags)
        {
            Console.WriteLine($"  {tag.Key} = {tag.Value}");
        }
    },
    ActivityStopped = activity =>
    {
        Console.WriteLine($"[Trace] Stopped: {activity.OperationName} ({activity.Duration.TotalMilliseconds:F1}ms)");
    }
};
ActivitySource.AddActivityListener(listener);

// Create and use the client — traces are emitted automatically
await using var client = new KubeMQClient(new KubeMQClientOptions
{
    ClientId = "csharp-observability-open-telemetry-client",
});
await client.ConnectAsync();

Console.WriteLine("\nPublishing events (traces will be logged above)...\n");

for (var i = 1; i <= 3; i++)
{
    await client.SendEventAsync(new EventMessage
    {
        Channel = "csharp-observability.open-telemetry",
        Body = Encoding.UTF8.GetBytes($"Traced event #{i}")
    });
}

Console.WriteLine("\nDone. In production, configure OpenTelemetry SDK to export to your collector.");

How It Works

  • The SDK instruments every gRPC operation using System.Diagnostics.ActivitySource (named "KubeMQ.Sdk") — no OpenTelemetry NuGet package is required in the SDK itself.
  • ActivityListener.ShouldListenTo is checked per source name; setting Sample to AllData captures all attributes and child spans on matched activities.
  • In production, replace the console listener with the OpenTelemetry SDK wired to your collector: add OpenTelemetry.Extensions.Hosting and call AddSource("KubeMQ.Sdk") in your TracerProvider builder.
  • The Meter name is also "KubeMQ.Sdk" — subscribe with MeterListener or IMeterFactory to capture throughput, error rate, and latency counters emitted by the client.

Was this page helpful?

On this page