Skip to main content

OpenTelemetry tracing for the message-store package via store interception

Project description

message-store-open-telemetry

OpenTelemetry distributed tracing for the message-store package (NATS JetStream event sourcing).

It wraps a message store and layers tracing on top of its public interface — the same interception pattern used in the JavaScript version. No tracing code lives in the message store core; all OpenTelemetry concerns are contained here.

  • Publish → a PRODUCER span is started and W3C trace context is injected into the NATS message headers (not the event body, so application schemas stay clean).
  • Consume → each handler runs inside a CONSUMER span whose parent is extracted from those headers, joining the same trace across the service hop. A backdated queue_wait span captures how long the message sat in the stream before delivery.
  • ensure_stream, fetch and wait_for pass straight through, untouched.

Installation

pip install message-store-open-telemetry
# or: uv add message-store-open-telemetry

Depends on message-store>=0.4.0 (the version that exposes _raw_jetstream_message and the publish headers parameter this package relies on) and opentelemetry-api. nats-py arrives transitively through message-store.

Usage

Wrap the store immediately after building it:

import nats
from message_store import MessageStore
from message_store_open_telemetry import get_message_store_with_open_telemetry

nats_connection = await nats.connect("nats://127.0.0.1:4222")

message_store = get_message_store_with_open_telemetry(
    MessageStore(
        nats_connection,
        prefix="my-service",
        should_create_missing_streams=True,
    )
)

# Use `message_store` exactly as before — publishing and subscriptions are now traced.

The wrapper exposes the same surface as MessageStore. Type code that accepts either the concrete store or a wrapped one against MessageStoreProtocol (exported from message_store):

from message_store import MessageStoreProtocol

def register(store: MessageStoreProtocol) -> None:
    ...

Enabling the SDK

This library only uses the OpenTelemetry API. Spans are emitted only once the host process registers an OpenTelemetry SDK and tracer provider. With no SDK registered, every API call is a cheap no-op, so the wrapper is safe to apply in services that are not exporting traces yet.

A minimal SDK setup (configure the exporter for your collector):

from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter

provider = TracerProvider(resource=Resource.create({"service.name": "my-service"}))
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
trace.set_tracer_provider(provider)

Emitted spans and attributes

Publish — nats publish <subject> (PRODUCER)

Attribute Source
messaging.system "nats"
messaging.operation "publish"
messaging.destination.name published subject
messaging.message.body.type message.type
messaging.nats.stream from the returned PubAck
messaging.message.seq from the returned PubAck

Consume — nats process <subject> (CONSUMER)

Parented to (and linked to) the producer span when trace headers are present.

Attribute Source
messaging.system "nats"
messaging.operation "process"
messaging.destination.name message subject
messaging.message.seq message sequence
messaging.message.body.type message.type
messaging.nats.consumer consumer (durable) name
messaging.nats.stream raw JetStream message
messaging.nats.redelivery_count raw JetStream message

queue_wait — a child span backdated to the moment JetStream stored the message and ended at delivery, so its duration is the stream dwell time (tagged with messaging.nats.dwell_ms and messaging.nats.redelivery_count).

Handler errors are recorded on the consumer span and re-raised, so the message store core keeps full ownership of ack/nak/term.

How context propagates

The publish seam injects the active context into a NATS headers dict via inject; the consume seam reads them back via extract. Whatever propagator your SDK installs (W3C tracecontext by default) is honoured — no propagator is forced here. Trace context never touches the persisted event payload.

Exports

  • get_message_store_with_open_telemetry(store: MessageStoreProtocol) -> MessageStoreProtocol
  • tracer — the library's Tracer instance, exported for advanced use.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

message_store_open_telemetry-0.1.0.tar.gz (5.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

message_store_open_telemetry-0.1.0-py3-none-any.whl (6.6 kB view details)

Uploaded Python 3

File details

Details for the file message_store_open_telemetry-0.1.0.tar.gz.

File metadata

  • Download URL: message_store_open_telemetry-0.1.0.tar.gz
  • Upload date:
  • Size: 5.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: Hatch/1.17.0 {"ci":null,"cpu":"x86_64","distro":{"id":"jammy","libc":{"lib":"glibc","version":"2.35"},"name":"Ubuntu","version":"22.04"},"implementation":{"name":"CPython","version":"3.11.15"},"installer":{"name":"hatch","version":"1.17.0"},"openssl_version":"OpenSSL 3.5.5 27 Jan 2026","python":"3.11.15","system":{"name":"Linux","release":"6.8.0-124-generic"}} HTTPX2/2.5.0

File hashes

Hashes for message_store_open_telemetry-0.1.0.tar.gz
Algorithm Hash digest
SHA256 7e47763b7aa695a84aa82713847cc117b569fd7f52fe5a388f51fa150bae9dbd
MD5 b098036b863ab0b8b01b9be795ca6da9
BLAKE2b-256 f0aafa41af348f499c322e5846c39ce850fb50cd79bc38b83d4badf32940988c

See more details on using hashes here.

File details

Details for the file message_store_open_telemetry-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: message_store_open_telemetry-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 6.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: Hatch/1.17.0 {"ci":null,"cpu":"x86_64","distro":{"id":"jammy","libc":{"lib":"glibc","version":"2.35"},"name":"Ubuntu","version":"22.04"},"implementation":{"name":"CPython","version":"3.11.15"},"installer":{"name":"hatch","version":"1.17.0"},"openssl_version":"OpenSSL 3.5.5 27 Jan 2026","python":"3.11.15","system":{"name":"Linux","release":"6.8.0-124-generic"}} HTTPX2/2.5.0

File hashes

Hashes for message_store_open_telemetry-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ae317def4ceda2f524a500713e2607ab9cb1ff84128a7ee7c56749ca3977d47b
MD5 227a90adf3b086cd0a3ecc0e041db458
BLAKE2b-256 27b9d1333abf2eff6ad36fc6b7a39eb861bb9588af8bb5c231db1283f8a18714

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page