Skip to main content

natsio-otel

OpenTelemetry adapter over natsio's zero-dependency instrumentation seam. Exports metrics for a natsio connection, plus trace-context propagation helpers for message headers. Distribution natsio-otel, imported as natsio.otel. Pre-1.0, no API-stability promises.

import natsio
from natsio.otel import OtelInstrumentation

nc = await natsio.connect(
    "nats://localhost",
    instrumentation=OtelInstrumentation(),  # meter_provider=None -> global
)

OtelInstrumentation(meter_provider=None, *, record_subject=False) implements the core Instrumentation protocol. It records into the given meter provider (or the global one). Every hook is allocation-light and cannot raise.

Metrics

Instrument names follow the OpenTelemetry messaging semantic conventions where the spec covers the concept; everything else is namespaced nats.client.* and marked custom below. All instruments carry messaging.system=nats.

Instrument Type Unit Source hook Notes
messaging.client.sent.messages Counter {message} on_message_published semconv; messaging.operation.type=send
messaging.client.consumed.messages Counter {message} on_message_delivered semconv; messaging.operation.type=receive
nats.client.sent.bytes Counter By on_message_published custom; application payload bytes (no framing)
nats.client.consumed.bytes Counter By on_message_delivered custom; application payload bytes (no framing)
nats.client.sent.message.size Histogram By on_message_published custom; payload-size distribution
nats.client.consumed.message.size Histogram By on_message_delivered custom; payload-size distribution
nats.client.network.sent.bytes Counter By on_bytes_sent custom; whole-flush wire bytes, includes framing
nats.client.network.received.bytes Counter By on_bytes_received custom; wire bytes, includes framing
nats.client.connects Counter {event} on_connect custom
nats.client.reconnects Counter {event} on_reconnect custom
nats.client.disconnects Counter {event} on_disconnect custom; error.type when the drop carried an error
nats.client.closes Counter {event} on_close custom
nats.client.errors Counter {error} on_error custom; keyed by error.type
nats.client.slow_consumer.drops Counter {message} on_slow_consumer custom; one increment per dropped message

Semantic-convention attribute keys (messaging.system, messaging.destination.name, messaging.operation.type, error.type) are hardcoded strings rather than imported from opentelemetry-semantic-conventions, which is not a runtime dependency.

Subject cardinality (record_subject)

The message subject maps to messaging.destination.name, but NATS subjects — especially _INBOX.* reply subjects generated per request — are effectively unbounded and will explode a metric backend's cardinality. So subjects are not recorded by default. Pass record_subject=True only when your subject space is known to be small and static:

OtelInstrumentation(record_subject=True)

This adds one dict allocation per message on the hot path (the default reuses a shared attribute dict and allocates nothing per message).

Trace-context propagation

from natsio.otel import inject, extract
  • inject(headers=None, *, context=None) -> Headers — returns a fresh natsio.Headers (the caller's mapping is never mutated) with traceparent / tracestate (and any other configured propagators) written in, ready to pass to publish.
  • extract(source, *, context=None) -> Context — pulls a trace Context out of a received Msg (or a Headers/mapping, or None).
from opentelemetry import trace
from opentelemetry.trace import SpanKind

tracer = trace.get_tracer("myapp")

# producer
with tracer.start_as_current_span("send order", kind=SpanKind.PRODUCER):
    await nc.publish("orders", body, headers=inject())

# consumer
async def handler(msg):
    ctx = extract(msg)
    with tracer.start_as_current_span("process order", context=ctx, kind=SpanKind.CONSUMER):
        ...

The spans story (honest version)

This extension ships metrics, not automatic spans. That is a limitation of the instrumentation seam as it stands, not a design choice, and the propagation helpers above are the clean subset that is expressible.

The seam is a set of fire-and-forget point-event hooks (on_message_published(subject, size) -> None, etc.). Real producer/consumer spans need three things the hooks cannot provide:

  1. A place to inject context into an outgoing publish. on_message_published fires after the frame is already encoded and buffered, and receives only (subject, size) — never the headers, which it also could not mutate. There is no publish-wrapping seam, so a traceparent cannot be attached automatically. Header injection must be done by the caller via inject().
  2. A scope around message processing. on_message_delivered fires at parse time, before dispatch and before the user callback runs, and carries only (subject, size) — no headers, no reply. It cannot bracket the handler, so a consumer/process span cannot be started as the handler's parent, nor its duration measured. Extraction must be done by the caller via extract().
  3. Operation timing. The semconv histograms messaging.client.operation.duration and messaging.process.duration need paired start/stop (or an elapsed argument). The hooks are instantaneous and unpaired, so these two core metrics are not implemented here.

See CHANGELOG.md and the task's friction report for concrete proposals to the core (header-carrying delivery hook, publish start/complete pair, a handler-wrapping seam).

Requirements

  • natsio, opentelemetry-api>=1.20
  • Tests additionally use opentelemetry-sdk and a nats-server binary.

Part of the natsio extension tier. If adopted into orbit.py the move is mechanical (natsio/otel/ -> orbit/otel/).

Download files

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

Source Distribution

natsio_otel-0.1.0.tar.gz (7.4 kB view details)

Uploaded Source

Built Distribution

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

natsio_otel-0.1.0-py3-none-any.whl (8.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: natsio_otel-0.1.0.tar.gz
  • Upload date:
  • Size: 7.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for natsio_otel-0.1.0.tar.gz
Algorithm Hash digest
SHA256 45f096c16ebcbf0b222296a5140f4c200c74e51a20525243cc4e57ad4ea330a7
MD5 f145018800e7e16ee0f9c85644b6d784
BLAKE2b-256 abd6b485227f35c1e1e326071cd0a117920f6164a39dc76cf563d9c847a27781

See more details on using hashes here.

Provenance

The following attestation bundles were made for natsio_otel-0.1.0.tar.gz:

Publisher: release-extension.yml on corruptmane/natsio

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

  • Download URL: natsio_otel-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 8.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for natsio_otel-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 edf3709e340e4e7b3695a2ff51a0e679a4807d893efd3745e699c8cd521d9923
MD5 6ba25e4fd157ec684e60d17834f51fd4
BLAKE2b-256 971d5f11002bcd7c0e28212628089f854618afe49bae2d3b94c641e296b25869

See more details on using hashes here.

Provenance

The following attestation bundles were made for natsio_otel-0.1.0-py3-none-any.whl:

Publisher: release-extension.yml on corruptmane/natsio

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page