Skip to content

feat(miner): add portfolio-queue Prometheus metrics + stuck/backlog alerts - #5603

Merged
JSONbored merged 1 commit into
mainfrom
prometheus-portfolio-queue-governor-alerts
Jul 13, 2026
Merged

feat(miner): add portfolio-queue Prometheus metrics + stuck/backlog alerts#5603
JSONbored merged 1 commit into
mainfrom
prometheus-portfolio-queue-governor-alerts

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

  • Adds gittensory-miner queue metrics, a Prometheus text-exposition endpoint for the local portfolio-queue: gittensory_miner_portfolio_queue_items{status=...} (gauge, one series per queue status) and gittensory_miner_portfolio_queue_oldest_in_progress_lease_age_seconds (gauge, age of the oldest still-claimed lease, 0 when nothing is in-flight).
  • Adds two alert rules in a new gittensory-miner-portfolio-queue Prometheus rule group: GittensoryMinerPortfolioQueueItemStuck (oldest in-progress lease age > 1h, sustained 15m) and GittensoryMinerPortfolioQueueBacklogHigh (queued-item count > 200, sustained 30m).
  • Mirrors the existing gittensory-miner-prediction metrics/alerts pattern already shipped for calibration drift: same escaping helpers, deterministic sorted output, always-emit HELP/TYPE, pure renderer (caller supplies nowMs), and a fixture test that parses the real prometheus/rules/alerts.yml and pins expr/for/labels/annotations to the renderer's exported metric-name constants (the config-side equivalent of promtool test rules).

Scope note

#5186 lists #4827 and #5134 as dependencies and describes this as "just add an alert rule." Neither of those issues actually produced a portfolio-queue Prometheus renderer or a scrapeable metric — the only existing miner-side renderer was renderMinerPredictionMetrics for a different subsystem. An alert rule with no backing metric can't be validated or fire, so this PR includes the renderer + queue metrics CLI command as a prerequisite, following the same local-package-only convention event-ledger-cli.js's renderEventLedgerMetrics already established (avoids touching the separately-published engine package for a miner-only metric).

Closes #5186

Test plan

  • npm run test:ci (unit + typecheck)
  • npm run build:miner
  • npm run selfhost:validate-observability (alerts.yml bracket/operator sanity check)
  • New fixture test (test/unit/alerts-miner-portfolio-queue-backlog.test.ts) parses the real alerts.yml and pins both rules' expr/for/severity/annotations to the renderer's exported metric-name constants
  • New unit tests for renderPortfolioQueueMetrics/runQueueMetrics cover empty queue, multiple statuses, oldest-lease selection (including the "younger lease must not replace the running max" branch), and malformed leasedAt timestamps

…lerts

Neither #4827 (lease/timeout/reclaim CLI logic) nor #4840 (alerting
guidance docs) actually produces a scrapeable metric for claimed-but-not-
completed portfolio-queue items -- this issue's own stated dependency was
on the metric existing, but no portfolio-queue metrics renderer existed
anywhere in the codebase yet. Adds one, mirroring event-ledger-cli.js's
renderEventLedgerMetrics / the engine's renderMinerPredictionMetrics
conventions (HELP/TYPE, deterministic sorted series, well-formed on an
empty queue):

- gittensory_miner_portfolio_queue_items{status} -- current count per
  status (queued/in_progress/done).
- gittensory_miner_portfolio_queue_oldest_in_progress_lease_age_seconds --
  age of the oldest still-in-flight claim lease, 0 when nothing is
  in-flight. The concrete "is anything stuck" signal.

Exposed via a new `gittensory-miner queue metrics` subcommand (mirrors
`gittensory-miner metrics` / `gittensory-miner ledger metrics`'s existing
pattern -- local + offline, no network).

Adds two Prometheus alert rules in the same dormant-until-a-scrape-target-
exists posture as the existing gittensory-miner-prediction group (#5188):
absent gittensory_miner_portfolio_queue_* series yield no result, so they
load cleanly via selfhost:validate-observability and never false-fire on
an install with no miner scrape configured.

- GittensoryMinerPortfolioQueueItemStuck: oldest in-flight lease age past
  1h (a generous multiple of the 30m self-heal default), sustained 15m --
  the self-heal isn't running or is itself stuck.
- GittensoryMinerPortfolioQueueBacklogHigh: queued backlog past 200,
  sustained 30m -- claiming is falling behind discovery.

A dedicated fixture test (alerts-miner-portfolio-queue-backlog.test.ts,
mirroring alerts-miner-prediction-calibration-drift.test.ts) pins each
rule's formula/threshold/metric-names to the real renderer's exported
constants, so a future rename can't silently drift the alert away from
what the renderer actually produces.

Closes #5186.
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
loopover-ui 7a07f93 Commit Preview URL

Branch Preview URL
Jul 13 2026, 08:38 AM

@codecov

codecov Bot commented Jul 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.00%. Comparing base (3de6e1b) to head (7a07f93).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #5603   +/-   ##
=======================================
  Coverage   95.00%   95.00%           
=======================================
  Files         573      573           
  Lines       45600    45629   +29     
  Branches    14661    14661           
=======================================
+ Hits        43321    43350   +29     
  Misses       1528     1528           
  Partials      751      751           
Flag Coverage Δ
shard-1 43.98% <0.00%> (-0.04%) ⬇️
shard-2 35.83% <100.00%> (+0.04%) ⬆️
shard-3 31.88% <0.00%> (-0.25%) ⬇️
shard-4 31.74% <10.34%> (-1.08%) ⬇️
shard-5 32.69% <0.00%> (+0.88%) ⬆️
shard-6 44.50% <10.34%> (+0.36%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
packages/gittensory-miner/lib/cli.js 100.00% <ø> (ø)
...ckages/gittensory-miner/lib/portfolio-queue-cli.js 94.50% <100.00%> (+0.60%) ⬆️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@JSONbored JSONbored self-assigned this Jul 13, 2026
@loopover-orb loopover-orb Bot added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jul 13, 2026
@JSONbored
JSONbored merged commit 7e55ebc into main Jul 13, 2026
19 checks passed
@JSONbored
JSONbored deleted the prometheus-portfolio-queue-governor-alerts branch July 13, 2026 08:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.

Development

Successfully merging this pull request may close these issues.

Add a Prometheus alert rule for stuck/stale portfolio-queue claimed items

1 participant