Messaging Protocol Tracing
Telegen provides deep observability for message queue and event streaming platforms using eBPF protocol tracing. All messaging protocols are detected at the wire level — no client library changes, no SDK instrumentation.
Overview
Telegen traces the following messaging protocols:
Protocol |
Version |
Default System |
Detection Method |
|---|---|---|---|
Kafka |
All |
Kafka |
Magic byte |
AMQP 0-9-1 |
— |
RabbitMQ |
Preface |
AMQP 1.0 |
— |
ActiveMQ |
Preface |
OpenWire |
— |
ActiveMQ |
“ActiveMQ” magic string in first 56 bytes |
STOMP |
1.0, 1.1, 1.2 |
ActiveMQ |
Command matching (SEND, MESSAGE, SUBSCRIBE, etc.) |
NATS |
— |
NATS |
Text-based protocol detection |
MQTT |
3.1, 3.1.1, 5.0 |
MQTT |
Fixed header detection |
AMQP 0-9-1 (RabbitMQ)
AMQP 0-9-1 is the native protocol used by RabbitMQ. Telegen captures all class/method operations and resolves queue/exchange destinations per channel.
Detected Operations
Class.Method |
Operation Type |
Description |
|---|---|---|
|
|
Publish message to exchange |
|
|
Create consumer on queue |
|
|
Deliver message to consumer |
|
|
Synchronous get |
|
|
Acknowledge message |
|
|
Negative acknowledge |
|
|
Reject message |
|
|
Declare/delete exchange |
|
|
Declare queue |
|
|
Bind/unbind queue to exchange |
|
|
Open vhost connection |
|
|
Open channel |
Destination Resolution
Telegen combines exchange and routing key to construct the destination:
Empty exchange → use routing key (direct queue binding)
Empty routing key → use exchange name
Otherwise →
exchange:routingKey
Settle operations (ack/nack/reject) carry no destination in their frames. Telegen uses an LRU cache per channel to resolve the originally published/consumed destination.
Sample Span
span:
name: "basic.publish"
kind: CLIENT
duration_ms: 0.8
attributes:
messaging.system: "rabbitmq"
messaging.destination.name: "orders:new"
messaging.operation.name: "basic.publish"
messaging.operation.type: "publish"
messaging.protocol: "amqp"
messaging.protocol_version: "0-9-1"
net.peer.ip: "10.0.1.50"
net.peer.port: 5672
AMQP 1.0
AMQP 1.0 is used by ActiveMQ, Azure Service Bus, RabbitMQ, Qpid, and Solace. Telegen detects performatives and resolves addresses via per-link caching.
Detected Performatives
Performative |
Descriptor |
Operation Type |
Description |
|---|---|---|---|
|
|
|
Attach link to source/target |
|
|
|
Transfer message (request/response) |
|
|
|
Settle delivery (ack/nack) |
|
|
|
Flow control update |
|
|
|
Detach link |
Messaging System Disambiguation
AMQP 1.0 is used by multiple brokers. Telegen resolves the correct messaging.system using hints derived from:
Process executable name (
beam.smp→ RabbitMQ,activemq→ ActiveMQ)Container name / K8s labels
Host port (5672/5671 → RabbitMQ, 61616-61617 → ActiveMQ, 61613-61614 → STOMP)
User-configured hints
Hint |
Resolved System |
|---|---|
|
Azure Service Bus |
|
ActiveMQ |
|
RabbitMQ |
|
JMS |
OpenWire (ActiveMQ)
OpenWire is the native protocol of Apache ActiveMQ.
Detection
Telegen scans for the “ActiveMQ” magic string within the first 56 bytes of the TCP payload, or matches known command IDs (1, 5, 6, 22, 23).
Sample Span
span:
name: "openwire.send"
kind: CLIENT
attributes:
messaging.system: "activemq"
messaging.destination.name: "queue://orders"
messaging.operation.type: "publish"
STOMP
STOMP (Simple/Streaming Text Oriented Messaging Protocol) is supported for ActiveMQ, RabbitMQ, and other STOMP-compatible brokers.
Detected Commands
Command |
Operation Type |
Description |
|---|---|---|
|
|
Send message to destination |
|
|
Receive message from subscription |
|
|
Create subscription |
|
|
Remove subscription |
|
|
Acknowledge message |
|
|
Negative acknowledge |
|
|
Establish connection |
|
|
Close connection |
Kafka
Kafka tracing captures:
Topic and partition from produce/fetch API requests
Consumer group tracking
Broker server-span fallback (when client spans are unavailable)
Consumer lag metrics
Configuration
Kafka tracing is enabled by default in the generic tracer. No configuration required.
Broadened detection (since v3.1.18) now covers more Kafka client libraries and wire-level variations.
OpenTelemetry Attributes
All messaging spans include standard OTel semantic conventions:
Attribute |
Description |
|---|---|
|
Broker type (kafka, rabbitmq, activemq, etc.) |
|
Queue, topic, or exchange name |
|
Protocol-specific method (basic.publish, amqp1.transfer, etc.) |
|
publish, process, receive, settle, create |
|
amqp, amqp1, openwire, stomp, kafka |
|
0-9-1, 1.0, etc. |
Architecture
flowchart LR
subgraph App["Application"]
P["Producer"]
C["Consumer"]
end
subgraph Kernel["Linux Kernel"]
E["eBPF Protocol Parser"]
end
subgraph Broker["Message Broker"]
B["Queue/Topic"]
end
P -->|"Publish"| E
E -->|"Forward"| B
B -->|"Deliver"| E
E -->|"Forward"| C
E -->|"Telemetry"| T["Telegen Agent"]
T -->|"OTLP"| O["Backend"]
Telegen intercepts messaging wire protocols at the kernel level, parsing frames and performatives without modifying application code.
eBPF Implementation
Generic Tracer (kprobe-based)
bpf/generictracer/protocol_amqp.h— AMQP 0-9-1, AMQP 1.0, OpenWire, STOMP detection and frame validationbpf/generictracer/k_tracer.c— Routes MQ protocols to large buffer capture pathBPF protocol types:
k_protocol_type_amqp = 6,k_protocol_type_amqp1 = 16,k_protocol_type_openwire = 17,k_protocol_type_stomp = 18
Go Tracer (uprobe-based)
bpf/gotracer/go_amqp091.c— Uprobes for Goamqp091-goclient library (publish, consume, ack, nack, reject)Uses
EVENT_GO_AMQP091 = 17ringbuf event type
Parsers (userspace)
Parser |
File |
|---|---|
AMQP 0-9-1 |
|
AMQP 1.0 |
|
OpenWire |
|
STOMP |
|
Kafka |
|
Transform Layer
internal/ebpf/common/amqp_detect_transform.go— AMQP 0-9-1 TCP frame → spaninternal/ebpf/common/amqp10_detect_transform.go— AMQP 1.0 performative → spaninternal/ebpf/common/go_amqp091_transform.go— Go AMQP 091 uprobe event → spaninternal/semconv/messagingsystem_refine.go— Dynamicmessaging.systemresolution
Configuration
Messaging tracing requires no explicit configuration — it is enabled automatically when the generic tracer is active.
To filter messaging spans, use the instrumentation options:
ebpf:
otel_traces_export:
# Naming a subset restricts spans to those protocols. Use "*" for all.
instrumentations:
- kafka
- mqtt
Metrics
Messaging tracing does not produce metrics directly — all data is exported as OTLP traces. For queue depth and consumer lag metrics, use the Kafka consumer group metrics or broker-native metrics exported via JMX/API.
Troubleshooting
AMQP 1.0 system not resolving correctly
Check that the process name or container labels include a hint for the broker type. If using Azure Service Bus, ensure the connection string or hostname includes servicebus.windows.net.
STOMP frames not captured
STOMP requires the client to send the CONNECT frame first. Telegen detects STOMP commands after the connection is established. Ensure the STOMP port (default 61613) is included in the generic tracer’s port filter.
RabbitMQ AMQP 0-9-1 ack spans missing destination
This is expected — ack frames carry no destination. Telegen resolves the destination from the LRU cache of the channel. If the cache is cold (first message), the destination may be empty. Increase the LRU cache size if needed.