What's new in v0.4.2
Feature release wrapping up Phase 6 (cross-trace correlation, query API, source code attributes, Prometheus pg_stat) and Phase 7 (CI templates, actionable framework-specific fixes, diff subcommand, TLS handshake hardening). No breaking changes to the Report JSON shape.
Highlights
- Daemon query API on port 4318 with five endpoints (
/api/status,/api/findings,/api/findings/{trace_id},/api/explain/{trace_id},/api/correlations) and a newperf-sentinel queryCLI subcommand to consume them. Retained findings ring buffer with[daemon] max_retained_findings(default 10k,0disables). Seedocs/QUERY-API.mdfor the full stability contract. perf-sentinel diff --before old.json --after new.jsonsubcommand compares two trace sets and emits new/resolved findings, severity changes, and per-endpoint I/O op deltas. Text, JSON or SARIF output. Primary use case: PR regression detection.- Cross-trace temporal correlation (opt-in via
[daemon.correlation] enabled = true): detects recurring co-occurrences between findings from different services over a rolling window. Output via/api/correlationsand the NDJSON stream. - Actionable framework-specific fixes attached to findings via
code.namespace+ file extension. v1 Java/JPA, v2 Java reactive (WebFlux, Quarkus reactive) + C# EF Core + Rust Diesel/SeaORM, v3 Helidon SE/MP + Quarkus non-reactive. Rendered in text, JSON (suggested_fix: { pattern, framework, recommendation, reference_url }) and SARIF (fixes[0].description.text). - OTel source code attributes: findings now carry a
code_locationwithfunction,filepath,lineno,namespaceextracted fromcode.*span attributes on OTLP, Jaeger and Zipkin. SARIFphysicalLocationsenable inline PR annotations in GitHub/GitLab code scanning. - Automated pg_stat ingestion via
perf-sentinel pg-stat --prometheus http://prometheus:9090, scrapingpostgres_exportermetrics instead of parsing a file. - CI templates in
docs/ci-templates/for GitHub Actions, GitLab CI and Jenkins, SHA-pinned, SARIF-wired, ready to copy-paste.
Security
- OTLP HTTP
/v1/tracesnow validatesContent-Typeand returns HTTP 415 on requests that don't declareapplication/x-protobuf. - Defense-in-depth JSON nesting cap at 32 levels for the native ingest path; protects against pathological
[[[...]]]payloads. - TLS listener handshake hardening:
tls_tcp_incomingruns each handshake in its own task so a stalled peer no longer blocks the accept loop; both TLS listeners (gRPC and HTTP) cap concurrent handshakes and live connections atTLS_MAX_INFLIGHT = 128. Closes a pre-auth DoS surface. read_eventsTOCTOU closed (CLI caps reads via.take(max + 1), same incmd_calibratefor the energy CSV).- Release workflow
permissions:tightened per-job (workflow floor is nowcontents: read).
Fixed
namespace_matchesenforces trailing segment boundaries, not just leading. Hints likeio.helidonno longer false-matchio.helidongrpc.Foo, andMicrosoft.EntityFrameworkCoreno longer matchesMicrosoft.EntityFrameworkCoreCache.Provider.perf-sentinel diff --output <file>no longer leaks ANSI escape codes into the file when launched from an interactive terminal.write_diff_texttakes an explicit palette;emit_diffforcesno_colors()wheneveroutputis set.- Electricity Maps default endpoint harmonized to
https://api.electricitymaps.com/v3across both code paths. - CI templates SHA-pinned (
docs/ci-templates/github-actions.ymlandgitlab-ci.yml); GitLab Code Quality jq was reading non-existentcode_location.code_filepath/code_location.code_linenofields, fixed to the v0.4.1 stability contract (filepath,lineno).
Changed
daemon/mod.rssplit into six focused submodules (sampling.rs,tls.rs,json_socket.rs,listeners.rs,event_loop.rs, plus the existingfindings_store.rsandquery_api.rs). Pure mechanical reorganization.score/mod.rssplit into three focused submodules (carbon_compute.rs,region_breakdown.rs, plus themod.rsorchestrator). Pure mechanical reorganization.score_greenreturns a 3-tuple(Vec<Finding>, GreenSummary, Vec<PerEndpointIoOps>)so the per-endpoint counter is built inline from theendpoint_statsmap already computed fortop_offenders. Single O(N) span pass.count_endpoint_statskeys on(service, endpoint)instead of endpoint-only. Two services serving the same path stay distinct in bothtop_offendersandper_endpoint_io_ops.- Shared
detect::TraceIndicesprecomputeschildren_by_parent+span_indexonce per trace; fanout and serialized detectors reuse it instead of rebuilding. apply_samplingallocation: batches ≤ 16 events use a stack-allocated cache with zero heap allocation.- Correlator cap enforcement:
enforce_pair_capdrops to 90% of the cap in one amortized pass, clones only the evicted keys.
Docs
- New
docs/QUERY-API.md+docs/FR/QUERY-API-FR.mdwith per-endpoint reference, captured curl responses, Prometheus/Grafana use cases and a stability contract. - New
## CI integration recipessection indocs/INTEGRATION.md+ FR linking to the three CI templates. - New
## Actionable fixessection indocs/design/04-DETECTION.md+ FR with the per-language rule tables and the segment-boundary matcher rule. - New
## Diff subcommandsection indocs/design/07-CLI-CONFIG-RELEASE.md+ FR; new## PR regression detectionsection indocs/INTEGRATION.md+ FR with a ready-to-copy GitHub Actions workflow. docs/ARCHITECTURE.md+ FR anddocs/design/00-INDEX.md+ FR updated to reflect the daemon/score submodule splits.- New TLS handshake concurrency cap note in
docs/LIMITATIONS.md+ FR;docs/CONFIGURATION.md+ FR TLS rows mention the 128-handshake cap.
Install
# Prebuilt binaries (Linux amd64/arm64, macOS arm64, Windows amd64)
curl -LO https://github.com/robintra/perf-sentinel/releases/download/v0.4.2/perf-sentinel-linux-amd64
chmod +x perf-sentinel-linux-amd64
sudo mv perf-sentinel-linux-amd64 /usr/local/bin/perf-sentinel# From crates.io
cargo install perf-sentinel# Docker
docker pull robintrassard/perf-sentinel:0.4.2Also available on GHCR: ghcr.io/robintra/perf-sentinel:0.4.2
Verify the binary against SHA256SUMS.txt:
curl -LO https://github.com/robintra/perf-sentinel/releases/download/v0.4.2/SHA256SUMS.txt
sha256sum -c SHA256SUMS.txt --ignore-missingFull diff: v0.4.1...v0.4.2