There is no /metrics endpoint. An operator running this next to BTCPay on one
VPS has GET /readyz for a yes-or-no answer, the hourly reconciliation report,
and log lines — but no way to graph anything, and no way to alert on a trend
before it becomes an incident.
Most of the numbers already exist and are already computed.
What to build
A Prometheus text-format /metrics endpoint. A suggested starting set, all of
which have a source in the code today:
- Worker heartbeat age per job. Already computed in
src/crypto_processing_api/api/health.py:104 (_worker_components), where
it is turned into a human sentence. Export the seconds instead.
- Outbound queue depth by status —
pending, dead. One GROUP BY over
outbound_events; the read endpoint is outbound_events in
src/crypto_processing_api/api/admin.py.
- Withdrawals by status. How many sit in
pending_approval is the
operator's real workload number.
- HTTP request counts by route and status.
RequestContextMiddleware
(src/crypto_processing_api/api/middleware.py:92) already sees every request
and its status code.
Constraints
- The endpoint must not be public. Everything else unauthenticated answers
in a fixed shape; this one leaks volume, queue depths and counts that sit
close to balances. Require the admin scope, or bind it on a separate port.
Say which you chose and why.
- No balances or amounts in labels. A metric label is high-cardinality
storage that ends up inside somebody's third-party monitoring account. Counts
and ages, not money.
- Avoid a new dependency if you can. The text format is a few lines of
string building. prometheus_client is a reasonable choice too, but this
project pins every dependency exactly and each one is a supply-chain
decision — make the case in the pull request, not in the lockfile.
Scope
No money code. Read-only queries.
There is no
/metricsendpoint. An operator running this next to BTCPay on oneVPS has
GET /readyzfor a yes-or-no answer, the hourly reconciliation report,and log lines — but no way to graph anything, and no way to alert on a trend
before it becomes an incident.
Most of the numbers already exist and are already computed.
What to build
A Prometheus text-format
/metricsendpoint. A suggested starting set, all ofwhich have a source in the code today:
src/crypto_processing_api/api/health.py:104(_worker_components), whereit is turned into a human sentence. Export the seconds instead.
pending,dead. OneGROUP BYoveroutbound_events; the read endpoint isoutbound_eventsinsrc/crypto_processing_api/api/admin.py.pending_approvalis theoperator's real workload number.
RequestContextMiddleware(
src/crypto_processing_api/api/middleware.py:92) already sees every requestand its status code.
Constraints
in a fixed shape; this one leaks volume, queue depths and counts that sit
close to balances. Require the
adminscope, or bind it on a separate port.Say which you chose and why.
storage that ends up inside somebody's third-party monitoring account. Counts
and ages, not money.
string building.
prometheus_clientis a reasonable choice too, but thisproject pins every dependency exactly and each one is a supply-chain
decision — make the case in the pull request, not in the lockfile.
Scope
No money code. Read-only queries.