Repository navigation
Conversation
Merging this PR will not alter performance2 warnings
Comparing Footnotes
|
33db967 to
cf0d278
Compare
cf0d278 to
7058ea3
Compare
7058ea3 to
5c8bbe0
Compare
[Medium impact] The change affects runs that enable telemetry mode and the profile data they upload. The harness release and download pin need updating before telemetry works for plain commands.
|
Add the files holding the OpenTelemetry spans and logs the benchmarks emit, shared by the runner that writes them and the parsers that read them: `otel/spans.msgpack.zst` and `otel/logs.msgpack.zst` in the profile folder. Each file is a zstd stream of positional MessagePack records, one per span or log, like the memtrack artifacts. Rows are flattened for the tables they are loaded into: ids as hex, attribute values as text, and the times of a span or log on the monotonic clock of the benchmark markers, when the benchmark recorded them, in their own fields. zstd runs with a 16 MB window and long-distance matching, since rows repeat their resource attributes far apart. Versions follow `UnwindData`: each record is wrapped in a versioned enum (`SpanRecord`, `LogRecord`), `SpanRow` and `LogRow` alias the current version, and older versions are upgraded through `From`. Version 1 fixtures must keep decoding. `TelemetryReader` decodes a file from any `Read`, such as an archive entry, as its bytes arrive. Unlike a truncated memtrack stream, a file cut in the middle of a row ends with an error. Refs COD-3863 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5c8bbe0 to
f33f3d6
Compare
d870617 to
c5290f2
Compare
Add `codspeed run --mode telemetry`, an experimental mode collecting the OpenTelemetry spans and logs the benchmarks export. It is a separate pass, so nothing has to keep the export out of the measured runs, and the benchmarks run once each instead of once per walltime iteration. The mode runs on a new analysis executor: it runs the benchmarks once each without a profiler, answering the integration as an analysis mode, with analysis instruments hooked onto it. An instrument sets up before the process is spawned, gets the integration's start and stop profiler commands, and stops once the process exits, with the benchmark markers. The executor saves those markers as `ExecutionTimestamps.msgpack` in the profile folder, and fails when no benchmark ran, unless `--allow-empty` is set. Uploads carry `executor: "analysis"` and the enabled instruments, so later analysis instruments only add an instrument. The telemetry mode enables the telemetry instrument: - It starts an OTLP/HTTP receiver on a free localhost port, passed to the benchmark in CODSPEED_OTEL_ENDPOINT. The receiver accepts protobuf and JSON exports, plain or gzipped, and writes each trace and log request to disk as received. Metrics are acknowledged and dropped. - Once the process exits, the requests are decoded and written as the runner-shared telemetry files, one row per span or log, formatted like the OpenTelemetry Collector's ClickHouse exporter. A request that fails to decode is skipped with a warning. - The `codspeed.monotonic_start_ns` and `codspeed.monotonic_end_ns` attributes of a span and the `codspeed.monotonic_time_ns` attribute of a log, their times on the monotonic clock of the benchmark markers, move to their own fields of the rows: along with the markers, they tell the benchmark that emitted each span or log. A warning counts the spans and logs without a start or time. `CODSPEED_RUNNER_MODE` is `telemetry` in this mode, which `cargo codspeed run` reads to pick its telemetry build. exec-harness runs it like memory mode. Refs COD-3863 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Build the divan `telemetry` bench of a codspeed-rust checkout next to this repository with `cargo codspeed build -m telemetry`, run it through `codspeed run --mode telemetry`, and read back its telemetry files. Its benchmarks emit `tracing` spans and events, a `tracing` event outside of any span, records of the `log` crate, and nothing at all. Each span and log is timestamped within the run on the wall clock, and falls within the rounds of the benchmark that emitted it by its time on the monotonic clock. Records keep their severity and call site, the ones below `info` are filtered out, and the benchmark without telemetry has no rows. The test is ignored by default since CI has no codspeed-rust checkout. Run it with `cargo test --test telemetry -- --ignored`. `scripts/run-telemetry-example.sh` runs the same example and uploads it. Refs COD-3863 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… folder A profile folder passed with `--profile-folder` is reused as-is. The spans and logs files are only created when rows arrive, so a run exporting no logs kept the logs file of the previous run, which was uploaded with the new results. Remove the previous files before writing. The receiver also removes request files left by an interrupted run before listening: their sequence numbers restart at zero, so they were decoded along with the new requests. Refs COD-3863 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
c5290f2 to
c40417d
Compare
| match measurement_mode { | ||
| MeasurementMode::Walltime => walltime::perform(commands), | ||
| MeasurementMode::Memory => analysis::perform(commands), | ||
| MeasurementMode::Memory | MeasurementMode::Telemetry => analysis::perform(commands), |
There was a problem hiding this comment.
Plain Exec targets still use the downloaded exec-harness version 1.4.1. AnalysisExecutor passes CODSPEED_RUNNER_MODE=telemetry, but that released harness only accepts the old modes, so it exits before running the command. Adding support in this workspace does not update the downloaded binary.
Release the updated harness and bump its version and installer pin.
Knowledge Base Used:
Prompt To Fix With AI
This is a comment left during a code review.
Path: crates/exec-harness/src/lib.rs
Line: 72
Comment:
**Plain telemetry commands fail**
Plain `Exec` targets still use the downloaded `exec-harness` version `1.4.1`. `AnalysisExecutor` passes `CODSPEED_RUNNER_MODE=telemetry`, but that released harness only accepts the old modes, so it exits before running the command. Adding support in this workspace does not update the downloaded binary.
Release the updated harness and bump its version and installer pin.
**Knowledge Base Used:**
- [Benchmark execution engine](https://app.greptile.com/codspeed/-/custom-context/knowledge-base/codspeedhq/codspeed/-/docs/benchmark-execution.md)
- [Execution harness and instrumentation bindings](https://app.greptile.com/codspeed/-/custom-context/knowledge-base/codspeedhq/codspeed/-/docs/execution-harness-and-instrumentation.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
Add
codspeed run --mode telemetry, an experimental mode that collects the OpenTelemetry spans and logs the benchmarks export, and uploads them with the results.It is a separate pass rather than a flag on the walltime run: nothing has to keep the export out of the measured runs, and each benchmark runs once instead of once per walltime iteration. Combine it with a measuring mode, e.g.
--mode telemetry,walltime.Analysis executor. The mode runs on a new generic analysis executor: it runs the benchmarks once each without a profiler, answering the integration as an analysis mode, with analysis instruments hooked onto it. An instrument sets up before the process is spawned, receives the integration's start and stop commands, and stops once the process exits. The executor saves the benchmark markers as
ExecutionTimestamps.msgpack, and fails when no benchmark ran unless--allow-emptyis set. Uploads carryexecutor: "analysis"and the enabled instruments, so later analysis instruments only add an instrument.CODSPEED_RUNNER_MODEistelemetryin this mode, whichcargo codspeed runreads to pick its telemetry build.Telemetry instrument.
CODSPEED_OTEL_ENDPOINT. The receiver accepts protobuf and JSON exports, plain or gzipped, on/v1/{traces,logs,metrics}. Each trace and log request is decompressed and written to disk before it is acknowledged, so everything an exited process sent is kept. Metrics are acknowledged and dropped.otel/spans.msgpack.zstandotel/logs.msgpack.zstin the profile folder, one row per span or log, formatted like the OpenTelemetry Collector's ClickHouse exporter. A request that fails to decode is skipped with a warning, and a file is only written when it has rows. The output of a previous run in a reused--profile-folderis removed first.codspeed.monotonic_start_ns/codspeed.monotonic_end_nsspan attributes and thecodspeed.monotonic_time_nslog attribute, set by the integrations on the monotonic clock of the benchmark markers, move to their own row fields. With the markers, they tell which benchmark emitted each span or log. A warning counts the rows that lack them.File format.
runner_shared::telemetrydefines the files, shared by the runner and the parsers: a zstd stream (16 MB window, long-distance matching, since rows repeat their resource attributes far apart) of positional MessagePack records. Records are versioned likeUnwindData, with v1 fixtures that must keep decoding.TelemetryReaderdecodes a file from anyReadas its bytes arrive.Testing.
tests/telemetry.rsbuilds the divantelemetrybench of a codspeed-rust checkout next to this repository, runs it throughcodspeed run --mode telemetry, and checks that every span and log falls within the rounds of the benchmark that emitted it, keeps its severity and call site, and that the benchmark without telemetry has no rows. CI has no codspeed-rust checkout, so it is ignored by default:cargo test --test telemetry -- --ignored. SetCODSPEED_OTEL_TEST_PROFILE_FOLDERto keep the profile folder for inspection.scripts/run-telemetry-example.shruns the same example with--mode telemetry,walltimeand uploads it.Closes COD-3863