Operational Prometheus/OpenTelemetry metrics for discord.py bots, in one line.
Project description
argus-dpy
Operational Prometheus / OpenTelemetry metrics for discord.py bots, in one line.
from discord.ext import commands
from argus import Argus
bot = commands.AutoShardedBot(command_prefix="!", intents=...)
Argus(bot) # that's the whole integration
Argus(bot) instruments shard latency, interaction and command throughput and
outcomes, command duration, gateway throughput, and rate-limit pressure, then
serves a Prometheus /metrics endpoint on the bot's own event loop — no
extra process, no thread, no glue code. It ships Grafana dashboards and a
one-command compose stack, stays backend-agnostic at the core, and never puts
a guild, user, or channel id on a metric label.
Status: alpha. The metric surface is stable; OTLP push and the per-guild analytical sink are planned for 1.1.
Install
pip install argus-dpy
Requires Python 3.10+ and discord.py >= 2.4.
Use it
Argus(bot)
Metrics are served at http://0.0.0.0:9191/metrics once the bot starts. That is
the entire required integration. You can also load it as a cog if you prefer:
from argus import ArgusCog
await bot.add_cog(ArgusCog(bot))
Built-in dashboard
Argus(bot) also serves a live web dashboard at / on the same port (a React
SPA bundled into the wheel, so no extra setup). Open http://localhost:9191/.
It reads metrics live (Server-Sent Events, with polling fallback) and has
sections for an overview, interactions, the gateway, your Grafana dashboards,
and per-guild analytics.
Argus(
bot,
dashboard=True, # default; set False to disable
dashboard_auth_token="secret", # optional; gates the dashboard + APIs
grafana_url="http://localhost:3000", # optional; embeds your Grafana boards
)
Security: with no token, the dashboard exposes the same operational data as
/metricsdoes, to anyone who can reach the port. Setdashboard_auth_token(and put the bot behind a proxy or bind to localhost) for anything public. The per-guild analytics section is served only whenenable_per_guildplus aclickhouse_dsnare set, and it fails closed without a token.
Dashboards in one command
docker compose up -d # Prometheus on :9090, Grafana on :3000 (admin/admin)
Compose auto-provisions the Prometheus datasource and three dashboards
(Overview, Interactions, Gateway). Prometheus scrapes the bot at
host.docker.internal:9191 out of the box — edit prometheus/prometheus.yml if
your bot listens elsewhere. The bot itself stays out of compose; it is your
application.
Configuration
Constructor kwargs override ARGUS_* environment variables override defaults.
| Kwarg | Env | Default | Meaning |
|---|---|---|---|
port |
ARGUS_PORT |
9191 |
/metrics port |
host |
ARGUS_HOST |
0.0.0.0 |
bind host |
metrics_path |
ARGUS_METRICS_PATH |
/metrics |
endpoint path |
cluster_id |
ARGUS_CLUSTER_ID |
default |
low-cardinality label for clustered deploys |
namespace |
ARGUS_NAMESPACE |
discord |
metric name prefix |
enable_per_guild |
ARGUS_ENABLE_PER_GUILD |
false |
analytical sink only; never adds a Prometheus label |
otlp_endpoint |
ARGUS_OTLP_ENDPOINT |
— | reserved for the 1.1 OTLP push path |
Metrics
Names use the namespace prefix (default discord); argus_* internals are
never prefixed.
State gauges (read live at scrape time)
| Metric | Labels |
|---|---|
discord_shard_latency_seconds |
shard |
discord_shards_connected |
cluster |
discord_shards_configured |
cluster |
discord_guilds |
cluster |
discord_cached_users |
cluster |
discord_bot_info |
discord_py_version, argus_version |
argus_up |
— |
Counters
| Metric | Labels |
|---|---|
discord_interactions_total |
type, status |
discord_app_commands_total |
command, status |
discord_commands_total |
command, status |
discord_command_errors_total |
command, error_type |
discord_gateway_events_total |
event |
discord_shard_disconnects_total |
shard |
discord_shard_reconnects_total |
shard |
discord_log_records_total |
logger, level |
discord_ratelimits_total |
— |
argus_instrumentation_errors_total |
hook |
Histograms
| Metric | Labels |
|---|---|
discord_app_command_duration_seconds |
command |
discord_cached_usersreflects the cache and is only meaningful with the members intent enabled. Command duration is approximated from the interaction timestamp to completion in this version.
Why no per-guild metrics?
Cardinality. Every unique label-value combination is its own time series. Shard,
cluster, command, event and status are bounded sets — fine. A guild_id on a
bot in tens of thousands of guilds is tens of thousands of series per metric,
which is what makes Prometheus fall over at scale, and per-entity series are not
even useful to visualise. So Argus forbids guild_id, user_id and
channel_id as labels by construction. Per-guild, per-user questions belong in
an analytical store (a planned, strictly separate path), never in the
operational metrics.
Clustered bots
Run one Argus per process, each with a distinct cluster_id and port:
Argus(bot, cluster_id="0", port=9191) # process 0
Argus(bot, cluster_id="1", port=9192) # process 1
List every port in prometheus/prometheus.yml. State gauges carry the distinct
cluster label; counter rates aggregate across the fleet at query time. See
examples/clustered_bot.py.
Licensing
Argus is licensed under AGPL-3.0-or-later — see LICENSE.
Because the AGPL treats network use as distribution, anyone who runs a modified version of Argus as a network service must make their modified source available to that service's users.
Contributions are accepted under the Developer Certificate of Origin; see CONTRIBUTING.md.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file argus_dpy-0.2.1.tar.gz.
File metadata
- Download URL: argus_dpy-0.2.1.tar.gz
- Upload date:
- Size: 166.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c4038f982e16f1e7665fe2d31da4816a8f9a68ada07c701c52479c977cf3dec1
|
|
| MD5 |
bde26d600cec99dd655fb80dfe7e2a4e
|
|
| BLAKE2b-256 |
963a1ea012b83b364e4a937ed692ec5ffb5e44b5f273a7e978f207495b8637e6
|
Provenance
The following attestation bundles were made for argus_dpy-0.2.1.tar.gz:
Publisher:
publish.yml on AstorisTheBrave/argus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
argus_dpy-0.2.1.tar.gz -
Subject digest:
c4038f982e16f1e7665fe2d31da4816a8f9a68ada07c701c52479c977cf3dec1 - Sigstore transparency entry: 1869865208
- Sigstore integration time:
-
Permalink:
AstorisTheBrave/argus@ff3f856652c4e028b1bd8c0e79bc65df6b2b5f42 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/AstorisTheBrave
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ff3f856652c4e028b1bd8c0e79bc65df6b2b5f42 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file argus_dpy-0.2.1-py3-none-any.whl.
File metadata
- Download URL: argus_dpy-0.2.1-py3-none-any.whl
- Upload date:
- Size: 228.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c6a8d6850d6d432f3bd570f098bd0f43c9bbee83dbb6e9de2a66ddeac28b2227
|
|
| MD5 |
a80eb0bb0aac181a6554d3d03055bb26
|
|
| BLAKE2b-256 |
4cace3bb9776685f78779146220d829c6867486f4067d56b53409159d7049831
|
Provenance
The following attestation bundles were made for argus_dpy-0.2.1-py3-none-any.whl:
Publisher:
publish.yml on AstorisTheBrave/argus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
argus_dpy-0.2.1-py3-none-any.whl -
Subject digest:
c6a8d6850d6d432f3bd570f098bd0f43c9bbee83dbb6e9de2a66ddeac28b2227 - Sigstore transparency entry: 1869865242
- Sigstore integration time:
-
Permalink:
AstorisTheBrave/argus@ff3f856652c4e028b1bd8c0e79bc65df6b2b5f42 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/AstorisTheBrave
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ff3f856652c4e028b1bd8c0e79bc65df6b2b5f42 -
Trigger Event:
workflow_dispatch
-
Statement type: