What's new in v0.37.0
v0.37.0 is about a number nobody could give: how many times a finding actually happened in production. The seen_count of /api/findings counts the detections the daemon's ring still holds, 10,000 entries shared by every finding, so it drops as the ring turns and starts over on restart. The daemon now keeps a real count, per day and per finding, and hands it to PerfSentinelHub, which turns it into a weekly volume in Hub 0.8.6.
A detection ledger beside the ring
Every signed finding the analysis emits is counted in a bounded, in-memory ledger, keyed by UTC day and signature, before the ring sees it. The count still works with max_retained_findings = 0, does not depend on the Hub export, and leaves acknowledgments out of it: an acknowledged finding still happens. Next to each count, the ledger sums the estimated_extra_io_ops of every detection, which gives the exact avoidable I/O rather than a count times one representative trace. Bounds keep it small whatever the traffic. It keeps 8 days by default and 10,000 signatures per day, and a signature over 1024 bytes or with a control character lands in the day's overflow instead of a key. A minute tick seals each finished day, after which nothing can change it. The same tick records analysis shedding and retryable OTLP rejects on the day they hit. [daemon.detections] tunes all of this, and its defaults need no change.
Read it, push it
GET /api/detections serves the ledger page by page, with a <day>:<signature> cursor, behind the same read key as /api/findings, and /api/status gains a detection_ledger summary. The Hub export gains a detection half on POST /api/import/detections. It sends only the rows that changed since the Hub last accepted the day, at most once a minute, and pushes once more on a graceful shutdown. A Hub without the route gets one probe, then silence, while the other exports keep flowing. The lab scenario detection-volume counts 12 planted detections behind a findings ring of 5, gets the same total from a one-row cursor walk, and finds the same 12 in the push. Three more posted just before SIGTERM reach the Hub through the drain.
Honest about what it does not see
The ledger lives in memory. Every daemon start opens a new one, and the restart day is flagged as a gap, since spans sent while the daemon was down are lost unless the collector replays them. Sampling, shedding and rejected ingest are flagged per day, never extrapolated. docs/LIMITATIONS.md lists what is not flagged: 413s, oversized gRPC, the JSON socket, per-trace truncation.
Smaller changes
perf-sentinel hub findingsrelays--from,--to(RFC 3339 UTC or epoch milliseconds),--offset,--include-ackedand--signature, so a client can page through a period.- The findings dashboard's
Tracescolumn is nowRetained, which is what it always showed. ADetections todaypanel reads the ledger, and the overview gains ledger tiles.
Upgrade impact
- New section, nothing to set.
[daemon.detections]is on by default with bounded memory. Setenabled = falseto turn the ledger off. - More Hub traffic when the export is on. The detection half adds at most one round a minute, with only the changed rows. A Hub older than 0.8.6 answers 404, and the half stops after one warning.
- Dashboard column renamed. Panels or alerts that matched the findings table's
Tracescolumn must useRetained. - No configuration key is removed, no existing route, metric or wire format changes, the acknowledgment signatures and the detection verdicts are untouched, the disclosure schema stays v1.8, the embedded reference data keeps its vintages, and MSRV stays 1.99.1.
Full detail in CHANGELOG.md.
Verifying this release
# Binary integrity via SLSA build provenance attestation (Build Level 2)
gh attestation verify perf-sentinel-linux-amd64 \
--repo Institut-du-Numerique-Responsable/perf-sentinel
# A periodic disclosure produced by this binary, with its attestation and bundle
perf-sentinel verify-hash --report perf-sentinel-report.json \
--attestation perf-sentinel-report.intoto.jsonl --bundle perf-sentinel-report.sig \
--expected-identity "https://github.com/Institut-du-Numerique-Responsable/perf-sentinel/.github/workflows/release.yml@refs/tags/v0.37.0" \
--expected-issuer "https://token.actions.githubusercontent.com" \
--verify-binary ./perf-sentinel-linux-amd64gh CLI 2.49 or newer required for gh attestation verify. Releases up to v0.26.2 were attested under robintra/perf-sentinel and keep their own --repo and identity.