Skip to content
AstorisTheBrave edited this page Jun 22, 2026 · 3 revisions

OTLP (OpenTelemetry push)

Argus is backend-agnostic at the core; the OTLP adapter pushes the same neutral registry to an OpenTelemetry collector, in addition to the Prometheus pull endpoint. Set otlp_endpoint to enable it; install the extra:

pip install "argus-dpy[otlp]"
Argus(bot, otlp_endpoint="http://collector:4317")

OTLP push is outbound-only: it needs no inbound port, so it's the simplest way to get metrics off a Docker bot panel (Pterodactyl, PebbleHost, Railway) where you can't expose /metrics. See Hosting on bot panels.

Mapping (adapters/otlp.py)

Neutral kind OpenTelemetry
counter Counter.add(amount, attributes)
histogram Histogram.record(value, attributes)
scrape-time gauge create_observable_gauge(callbacks=[...]) reading the neutral callback at export
info observable gauge of constant 1 carrying the info as attributes

Labels become OTel attributes (including cluster). Gauges stay pull-based: the observable gauge's callback invokes the neutral gauge callback at export time, so invariant 4 holds across both backends.

Wiring

When otlp_endpoint is set, the cog builds an OTLPAdapter and attaches it to the registry alongside the Prometheus adapter, so every inc/observe/set_info fans out to both. opentelemetry is imported lazily inside _build_meter, so the adapter (and its tests, via an injected meter) work without the dependency installed.

The adapter builds a MeterProvider with a PeriodicExportingMetricReader wrapping OTLPMetricExporter(endpoint=...). Standard OTel env vars (OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_METRIC_EXPORT_INTERVAL, …) apply. The gRPC exporter is the default; the HTTP exporter variant lives at opentelemetry.exporter.otlp.proto.http.

Tracing (tracing/tracer.py)

Set enable_tracing (same argus-dpy[otlp] extra) to emit an OpenTelemetry span per command/interaction lifecycle: a span opens when an application command or prefix command is received and closes on completion or error, carrying discord.command, discord.outcome, cluster, and error.type (plus discord.guild_id only when enable_per_guild is on). Spans export over OTLP to Jaeger/Tempo/Grafana; tracing_endpoint falls back to otlp_endpoint.

It is deliberately a lifecycle span - Argus does not wrap your command callback, so the SDK stays non-invasive (nesting your own spans under it is future work). Export is batched on OpenTelemetry's background thread (nothing on the bot loop, invariant 3), open spans are held in a bounded map, and every span call is wrapped so a tracing fault can never reach the bot (invariant 5). Health shows as argus_subsystem_up{subsystem="tracing"}.

Datadog and friends

Reach Datadog (and most vendors) through their OTLP intake rather than a bespoke client; no core changes are needed.

Clone this wiki locally