Skip to main content

Telemetry (Tracing & Metrics)

Ratatosk emits OpenTelemetry-compatible tracing and metrics from every connector operation. Each connector has its own ActivitySource and Meter — traces and metrics are available out of the box without any manual instrumentation.

Signals emitted

Tracing (Activity)

OperationSpan nameActivitySource
SendMessageAsync{connector} sendRatatosk.Connector.{type}
ReceiveMessagesAsync{connector} receiveRatatosk.Connector.{type}
SendBatchAsync{connector} batch_sendRatatosk.Connector.{type}
InitializeAsync{connector} initializeRatatosk.Connector.{type}
GetStatusAsync{connector} status_queryRatatosk.Connector.{type}
GetMessageStatusAsync{connector} status_queryRatatosk.Connector.{type}
ReceiveMessageStatusAsync{connector} receive_statusRatatosk.Connector.{type}
GetHealthAsync{connector} health_checkRatatosk.Connector.{type}

Each span carries semantic convention attributes:

AttributeExample value
messaging.systemratatosk
messaging.operationsend, receive, status_query
messaging.destinationChannel name
messaging.message.idMessage ID
ratatosk.connector.typetwilio_sms
ratatosk.connector.nameConnector instance name
error.typeError code (on failure)

Metrics (Meter)

Each connector exposes a Meter named Ratatosk.Connector.{type} with the following instruments:

Metric nameTypeUnitDescription
ratatosk.messages.sentCounter{message}Total messages sent
ratatosk.messages.send_failedCounter{message}Messages that failed to send
ratatosk.messages.receivedCounter{message}Total messages received
ratatosk.messages.receive_failedCounter{message}Messages that failed to receive
ratatosk.messages.send.durationHistogrammsSend operation latency
ratatosk.messages.receive.durationHistogrammsReceive operation latency
ratatosk.messages.send.payload_sizeHistogramByPayload size in bytes
ratatosk.connector.state_changesCounter{change}Connector state transitions

The IMessagingClient facade also emits its own telemetry under Ratatosk.Client:

Metric nameTypeUnit
ratatosk.client.messages.sentCounter{message}
ratatosk.client.messages.send_failedCounter{message}
ratatosk.client.messages.send.durationHistogramms

Wiring with OpenTelemetry SDK

Add the Ratatosk.Extensions.OpenTelemetry package to register all sources:

dotnet add package Ratatosk.Extensions.OpenTelemetry
using Ratatosk;

builder.Services
.AddMessaging()
.AddTwilioSmsConnector(options => { /* ... */ })
.WithOpenTelemetry();

.WithOpenTelemetry() internally calls AddOpenTelemetry().WithTracing().WithMetrics(), registers both the connector (Ratatosk.Connector.*) and client (Ratatosk.Client) sources, and manages the TracerProvider/MeterProvider lifecycle through the host.

Option 2 — Manual on TracerProviderBuilder / MeterProviderBuilder

When you already have an OpenTelemetry setup and want to add Ratatosk sources:

using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
using Ratatosk;

builder.Services.AddOpenTelemetry()
.WithTracing(t => t
.AddRatatoskInstrumentation()
.AddConsoleExporter() // or any exporter
)
.WithMetrics(m => m
.AddRatatoskInstrumentation()
.AddConsoleExporter()
);

AddRatatoskInstrumentation() adds:

  • Ratatosk.Client — client-level ActivitySource and Meter
  • Ratatosk.Connector.* — all connector ActivitySources and Meters (wildcard matching, new connectors are picked up automatically)

Configuration

Telemetry can be configured per connector without modifying its provider-specific options.

Via the connector builder

services.AddMessaging()
.AddConnector<TwilioSmsConnector>("sms", cfg => cfg
.WithSettings("Twilio")
.WithTelemetry(t =>
{
t.EnableTracing = true;
t.EnableMetrics = true;
t.EnablePayloadSizeMetrics = false; // off by default
}));

Via ConnectionSettings

var settings = new ConnectionSettings()
.SetParameter("Telemetry.EnableTracing", false)
.SetParameter("Telemetry.EnablePayloadSizeMetrics", true);

var connector = new TwilioSmsConnector(schema, settings);

TelemetryOptions reference

PropertyDefaultDescription
EnableTracingtrueEmit Activity spans for connector operations
EnableMetricstrueRecord metric counters and histograms
EnablePayloadSizeMetricsfalseSerialize message to measure payload size (may impact throughput)

Client-level telemetry

The IMessagingClient facade reads its telemetry configuration from MessagingClientOptions:

services.AddMessaging()
.AddClient(options =>
{
options.Telemetry.EnableTracing = true;
options.Telemetry.EnableMetrics = true;
});

ConnectionSettings keys

All telemetry settings keys are available as constants in TelemetrySettingsKeys:

KeyConstantExpected value
Telemetry.EnableTracing.EnableTracingbool
Telemetry.EnableMetrics.EnableMetricsbool
Telemetry.EnablePayloadSizeMetrics.EnablePayloadSizeMetricsbool

Performance considerations

  • Payload size metrics require serialising the message to JSON to measure byte count — this adds CPU and memory overhead per send. Disabled by default.
  • When telemetry is fully enabled, the overhead is limited to creating Activity objects and recording metric observations, both designed for high-throughput scenarios.
  • Each connector has its own ActivitySource and Meter — if no OpenTelemetry SDK is configured (no listeners attached), HasListeners() returns false and the activity creation is skipped entirely with negligible cost.

Viewing telemetry

Once wired, traces and metrics flow to any OpenTelemetry-compatible backend:

# Console output during development
dotnet add package OpenTelemetry.Exporter.Console

builder.Services.AddOpenTelemetry()
.WithTracing(t => t
.AddRatatoskInstrumentation()
.AddConsoleExporter())
.WithMetrics(m => m
.AddRatatoskInstrumentation()
.AddConsoleExporter());

For production, configure an OTLP exporter:

dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
builder.Services.AddOpenTelemetry()
.WithTracing(t => t
.AddRatatoskInstrumentation()
.AddOtlpExporter())
.WithMetrics(m => m
.AddRatatoskInstrumentation()
.AddOtlpExporter());

Example: tracing a send operation

Service A Twilio Connector
│ │
│ SendAsync(channel, message) │
│─────────────────────────────────▶ │
│ Span: "twilio_sms send" │
│ tags: │
│ messaging.system=ratatosk │
│ messaging.operation=send │
│ messaging.message.id=... │
│ ratatosk.connector.type= │
│ twilio_sms │
│ │
│ SendMessageCoreAsync() │
│ ─────────────────────────▶ │
│ ◀──────────────────────── │
│ │
│ counter: sent +1 │
│ histogram: send.duration │
│ │
│◀───────────────────────────────── │

See also