What's new in v0.25.4
v0.25.4 is about the code location perf-sentinel prints under a finding. An instrumentation that follows the stable OpenTelemetry code conventions sends code.function.name already qualified, as in com.foo.OrderService.findItems, and perf-sentinel derives the namespace from that name. The text outputs then joined the two back together, so the line read com.foo.OrderService.com.foo.OrderService.findItems. The same line joined every namespace to its function with a dot, which spells a PHP method App\Jobs\PurgeJob.handle, and an empty attribute left a stray separator behind. This is the Source: line of analyze, the Location: line of diff, the location: line of explain and the detail panel of the TUI.
A qualified name prints once
When the function starts with the namespace followed by a separator (., \, : or #), it now prints alone. The endpoint fallback, which names a job or a consumer without HTTP attributes after its code frame, already applied that rule, and both now go through the same function. A legacy code.namespace and code.function pair collapses the same way when its function already carries the namespace, and is joined as before otherwise: a namespace and a function both named handler still print handler.handler.
:: where the language writes it
A namespace that holds \ or :: now joins its function with ::, the separator the endpoint fallback already used. PHP qualifies its namespaces with \ but attaches a method with ::, so the legacy pair App\Jobs\PurgeJob and handle prints App\Jobs\PurgeJob::handle. Rust, C++ and Ruby namespaces join the same way, crate::db::load where it read crate::db.load. Every other namespace still joins with a dot.
An empty attribute is an absent one
An empty code.function, code.namespace or code.filepath no longer prints as an empty part. A namespace sent with a file but no function printed com.foo.OrderService. (OrderService.java:42), an empty namespace .find and an empty file path com.foo.Svc.find (:42). They now print com.foo.OrderService (OrderService.java:42), find and com.foo.Svc.find.
Compared with the 0.25.3 binary on eleven code location shapes, from the stable name to an empty file path, seven printed one of the spellings above and now print the corrected one, and the other four print as they did. perf-sentinel demo changes four of its eighteen Source: lines, diesel::query_builder::OrderService::create_order where it read diesel::query_builder.OrderService::create_order. On the eleven shapes, both versions emit the same findings, signatures, endpoints and SARIF locations.
Upgrade impact
- The code location of some findings prints differently in the text outputs and the TUI. A script that reads the
Source:line ofanalyzesees the new spelling. The JSON report keepscode_locationas the four fields the span sent. - Nothing a finding is keyed on moves. Signatures, endpoints and SARIF locations are unchanged, so acknowledgments keep matching and no finding appears or disappears.
- No configuration key is added or removed, no route, metric name or wire format changes, no public signature in
perf-sentinel-coremoves, the embedded reference data keeps its vintages, and MSRV stays 1.98.1.
Full detail in CHANGELOG.md.
Verifying this release
# Binary integrity via SLSA Build L3 attestation
gh attestation verify perf-sentinel-linux-amd64 \
--repo robintra/perf-sentinel
# A periodic disclosure produced by this binary
perf-sentinel verify-hash --report perf-sentinel-report.json \
--expected-identity "https://github.com/robintra/perf-sentinel/.github/workflows/release.yml@refs/tags/v0.25.4" \
--expected-issuer "https://token.actions.githubusercontent.com" \
--verify-binary ./perf-sentinel-linux-amd64gh CLI 2.49 or newer required for gh attestation verify.