Skip to content

[benchmarks] Log the run id and Datadog trace for each sequential-steps run - #3248

Open
shalabhc wants to merge 4 commits into
mainfrom
shalabhc/bench-histogram-run-trace-links
Open

[benchmarks] Log the run id and Datadog trace for each sequential-steps run#3248
shalabhc wants to merge 4 commits into
mainfrom
shalabhc/bench-histogram-run-trace-links

Conversation

@shalabhc

@shalabhc shalabhc commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Logs the run id and Datadog APM links for each sequential-steps benchmark iteration, in the benchmark job's own output:

[bench] 1020 steps run wrun_41KY… — trace https://app.datadoghq.com/apm/trace/6f1a… — spans https://app.datadoghq.com/apm/traces?query=%40workflow.run.id%3Awrun_41KY…

Follow-up to #3213 (which added the STSO histograms). Uses the run-id/trace capture prototyped on the WIP variance branch, #3107.

Why

The 📈 STSO distribution section shows the shape of the sequential-steps run but not which run produced it. When a bucket looks wrong, the next step is always the same manual hunt: find the run by deployment id + time window, then find its trace. This puts both in the log, next to the run that produced them.

These are debugging aids rather than part of the benchmark's reported result, so they go in the job output rather than the PR comment body. That also covers two cases a comment can't: a local pnpm bench, and a job that fails before the comment step runs.

What

  • workbench/nextjs-turbopack/app/api/bench/route.ts — returns traceId from the span @vercel/otel opened for the trigger request. @opentelemetry/api was already a dependency; no lockfile change.
  • packages/core/e2e/benchmark.test.ts — threads traceId through triggerBenchRunrunSequentialIteration, and logs one line per iteration as soon as the scenario completes.

A deployment built before the route reported a trace id logs the run id and span search, with no trace permalink.

Why two links

This deployment runs the default WORKFLOW_TRACE_MODE=linked — nothing in the workbench or benchmarks.yml sets the mode. Under linked, each workflow/step invocation is its own trace root, and the trigger's trace holds only workflow.start plus span links out to those roots. So the trace permalink is an entry point to the run (one hop through the links, which Datadog renders), not a single trace containing every step's spans.

The @workflow.run.id:<runId> span search lands directly on the run's execution spans instead, which is where an STSO investigation actually goes. It depends on workflow.run.id being an indexed span tag in the org, so it's logged alongside the permalink rather than replacing it — still to be confirmed against a real run.

Notes

The comment renderer is untouched, and the result artifact gains no new fields — the run identities are logged, not serialized.

One thing this deliberately drops relative to putting the line in the comment: there's no link to the main baseline's run. Which run produced the baseline histogram is only knowable at comment-render time, where the two artifacts are matched up; the benchmark job only knows about its own run.

Empty changeset — no package behavior changes.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
example-nextjs-workflow-turbopack Ready Ready Preview Aug 1, 2026 4:04pm
example-nextjs-workflow-webpack Ready Ready Preview Aug 1, 2026 4:04pm
example-workflow Ready Ready Preview Aug 1, 2026 4:04pm
workbench-astro-workflow Ready Ready Preview Aug 1, 2026 4:04pm
workbench-express-workflow Ready Ready Preview Aug 1, 2026 4:04pm
workbench-fastify-workflow Ready Ready Preview Aug 1, 2026 4:04pm
workbench-hono-workflow Ready Ready Preview Aug 1, 2026 4:04pm
workbench-nestjs-workflow Ready Ready Preview Aug 1, 2026 4:04pm
workbench-nitro-workflow Ready Ready Preview Aug 1, 2026 4:04pm
workbench-nuxt-workflow Ready Ready Preview Aug 1, 2026 4:04pm
workbench-sveltekit-workflow Ready Ready Preview Aug 1, 2026 4:04pm
workbench-tanstack-start-workflow Ready Ready Preview Aug 1, 2026 4:04pm
workbench-vite-workflow Ready Ready Preview Aug 1, 2026 4:04pm
workflow-docs Ready Ready Preview, v0 Aug 1, 2026 4:04pm
workflow-swc-playground Ready Ready Preview Aug 1, 2026 4:04pm
workflow-tarballs Ready Ready Preview Aug 1, 2026 4:04pm
workflow-web Ready Ready Preview Aug 1, 2026 4:04pm

@changeset-bot

changeset-bot Bot commented Jul 31, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 6896fb3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 0 packages

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

All tests passed

E2E Test Summary

Summary
Passed Failed Skipped Total
✅ ▲ Vercel Production 1466 0 239 1705
✅ 💻 Local Development 1633 0 227 1860
✅ 📦 Local Production 1633 0 227 1860
✅ 🐘 Local Postgres 1633 0 227 1860
✅ 🪟 Windows 155 0 0 155
✅ 📋 Other 1028 0 212 1240
✅ vercel-multi-region 27 0 0 27
Total 7575 0 1132 8707
Details by Category

✅ ▲ Vercel Production

App Passed Failed Skipped
✅ astro 127 0 28
✅ example 127 0 28
✅ express 127 0 28
✅ fastify 127 0 28
✅ hono 127 0 28
✅ nextjs-turbopack 152 0 3
✅ nextjs-webpack 152 0 3
✅ nitro 127 0 28
✅ nuxt 127 0 28
✅ sveltekit 146 0 9
✅ vite 127 0 28

✅ 💻 Local Development

App Passed Failed Skipped
✅ astro-stable 129 0 26
✅ express-stable 129 0 26
✅ fastify-stable 129 0 26
✅ hono-stable 129 0 26
✅ nextjs-turbopack-canary 136 0 19
✅ nextjs-turbopack-stable 155 0 0
✅ nextjs-webpack-canary 136 0 19
✅ nextjs-webpack-stable 155 0 0
✅ nitro-stable 129 0 26
✅ nuxt-stable 129 0 26
✅ sveltekit-stable 148 0 7
✅ vite-stable 129 0 26

✅ 📦 Local Production

App Passed Failed Skipped
✅ astro-stable 129 0 26
✅ express-stable 129 0 26
✅ fastify-stable 129 0 26
✅ hono-stable 129 0 26
✅ nextjs-turbopack-canary 136 0 19
✅ nextjs-turbopack-stable 155 0 0
✅ nextjs-webpack-canary 136 0 19
✅ nextjs-webpack-stable 155 0 0
✅ nitro-stable 129 0 26
✅ nuxt-stable 129 0 26
✅ sveltekit-stable 148 0 7
✅ vite-stable 129 0 26

✅ 🐘 Local Postgres

App Passed Failed Skipped
✅ astro-stable 129 0 26
✅ express-stable 129 0 26
✅ fastify-stable 129 0 26
✅ hono-stable 129 0 26
✅ nextjs-turbopack-canary 136 0 19
✅ nextjs-turbopack-stable 155 0 0
✅ nextjs-webpack-canary 136 0 19
✅ nextjs-webpack-stable 155 0 0
✅ nitro-stable 129 0 26
✅ nuxt-stable 129 0 26
✅ sveltekit-stable 148 0 7
✅ vite-stable 129 0 26

✅ 🪟 Windows

App Passed Failed Skipped
✅ nextjs-turbopack 155 0 0

✅ 📋 Other

App Passed Failed Skipped
✅ e2e-local-dev-nest-stable 129 0 26
✅ e2e-local-dev-tanstack-start- 129 0 26
✅ e2e-local-postgres-nest-stable 129 0 26
✅ e2e-local-postgres-tanstack-start- 129 0 26
✅ e2e-local-prod-nest-stable 129 0 26
✅ e2e-local-prod-tanstack-start- 129 0 26
✅ e2e-vercel-prod-nest 127 0 28
✅ e2e-vercel-prod-tanstack-start 127 0 28

✅ vercel-multi-region

App Passed Failed Skipped
✅ nextjs-turbopack 27 0 0

📋 View full workflow run

@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

📊 Workflow Benchmarks

commit 6896fb3 · Sat, 01 Aug 2026 16:24:50 GMT · run logs

Backend: vercel · app: nextjs-turbopack

Metric Scenario Best (ms) P75 (ms) P90 (ms) P99 (ms) Samples
TTFS step 504 (-43%) 💚 1368 🔴 (+36%) 🔻 1393 🔴 (+30%) 🔻 1499 🔴 (+21%) 🔻 30
TTFS stream 1301 (+544%) 🔻 1402 🔴 (+39%) 🔻 1414 🔴 (+39%) 🔻 1432 🔴 (+24%) 🔻 30
TTFS hook + stream 1539 (+172%) 🔻 1665 🔴 (+30%) 🔻 1692 🔴 (+28%) 🔻 1889 🔴 (+27%) 🔻 30
STSO 1020 steps (inline) 178 (+9.2%) 475 (+3.5%) 535 (+0.8%) 724 (-2.2%) 1016
STSO 1020 steps (queue-hop) 2394 (+23%) 🔻 3757 (+5.7%) 3757 (+5.7%) 3757 (+5.7%) 3
WO 1020 steps 407889 (+3.5%) 407889 (+3.5%) 407889 (+3.5%) 407889 (+3.5%) 1
SL stream latency 108 (+35%) 🔻 167 🔴 (+38%) 🔻 183 🔴 (+33%) 🔻 3785 🔴 (+2281%) 🔻 30
SO stream overhead (text) 111 (+17%) 🔻 170 (+2.4%) 194 (+3.7%) 203 (-44%) 💚 30
SO stream overhead (structured) 101 (+4.1%) 245 (+35%) 🔻 287 (+46%) 🔻 452 (+71%) 🔻 30
📈 STSO distribution vs main (inline / queue-hop histograms)

1020 steps (inline)

Cumulative STSO time: main 385272ms → this run 397249ms (Δ +11977ms, +3%)

  150-200 ms  █┃████                    main  49  this  18   -31
  200-250 ms  ███████████┃█             main  99  this  92    -7
  250-300 ms  █████████████████░░┃      main 132  this 161   +29
  300-350 ms  █████████████████┃██████  main 189  this 139   -50
  350-400 ms  ████████████████┃█████    main 171  this 135   -36
  400-450 ms  ███████████░░░░░░░┃       main  90  this 148   +58
  450-500 ms  █████████████████┃        main 130  this 144   +14
  500-550 ms  ██████████░┃              main  80  this  97   +17
  550-600 ms  ████┃                     main  40  this  42    +2
  600-650 ms  █┃                        main  11  this  18    +7
  650-700 ms  ┃                         main   9  this   8    -1
  700-750 ms  ┃                         main   6  this   7    +1
  750-800 ms  ┃                         main   4  this   3    -1
  800-850 ms  ┃                         main   1  this   0    -1
  850-900 ms  ┃                         main   1  this   1    +0
  900-950 ms  ┃                         main   0  this   1    +1
1000-1050 ms  ┃                         main   1  this   1    +0
1050-1100 ms  ┃                         main   1  this   1    +0
1700-1750 ms  ┃                         main   1  this   0    -1
2600-2650 ms  ┃                         main   1  this   0    -1

1020 steps (queue-hop)

Cumulative STSO time: main 7646ms → this run 9252ms (Δ +1606ms, +21%)

1500-2000 ms  ┃███████████████████████  main 1  this 0  -1
2000-2500 ms  ███████████████████████┃  main 1  this 1  +0
3000-3500 ms  ░░░░░░░░░░░░░░░░░░░░░░░┃  main 0  this 1  +1
3500-4000 ms  ███████████████████████┃  main 1  this 1  +0
📜 Previous results (4)

08567fd

Fri, 31 Jul 2026 23:21:18 GMT · run logs

vercel / nextjs-turbopack

Metric Scenario Best (ms) P75 (ms) P90 (ms) P99 (ms) Samples
TTFS step 1331 (+97%) 🔻 1437 🔴 (+43%) 🔻 1461 🔴 (+42%) 🔻 1501 🔴 (-4.9%) 30
TTFS stream 1262 (+39%) 🔻 1383 🔴 (+48%) 🔻 1394 🔴 (+47%) 🔻 1425 🔴 (+47%) 🔻 30
TTFS hook + stream 486 (+2.7%) 1626 🔴 (+25%) 🔻 1665 🔴 (+24%) 🔻 1775 🔴 (+29%) 🔻 30
STSO 1020 steps (inline) 160 (+24%) 🔻 452 (±0%) 508 (±0%) 695 (-3.1%) 1016
STSO 1020 steps (queue-hop) 2396 (+61%) 🔻 3482 (+10%) 3482 (+10%) 3482 (+10%) 3
WO 1020 steps 389282 (±0%) 389282 (±0%) 389282 (±0%) 389282 (±0%) 1
SL stream latency 90 (+20%) 🔻 135 🔴 (+17%) 🔻 137 🔴 (+7.9%) 2905 🔴 (+754%) 🔻 30

75e3abe

Fri, 31 Jul 2026 18:10:29 GMT · run logs

vercel / nextjs-turbopack

Metric Scenario Best (ms) P75 (ms) P90 (ms) P99 (ms) Samples
TTFS step 268 (+1.9%) 1435 🔴 (±0%) 1520 🔴 (-5.5%) 1887 🔴 (-6.0%) 30
TTFS stream 260 (+5.3%) 1466 🔴 (+4.6%) 1512 🔴 (-3.9%) 1812 🔴 (-11%) 30
TTFS hook + stream 346 (-14%) 1596 🔴 (+23%) 🔻 1656 🔴 (+22%) 🔻 1845 🔴 (+26%) 🔻 30
STSO 1020 steps (inline) 179 (+1.1%) 502 (-2.3%) 571 (-1.2%) 782 (±0%) 1016
STSO 1020 steps (queue-hop) 2133 (+44%) 🔻 2807 (+0.7%) 2807 (+0.7%) 2807 (+0.7%) 3
WO 1020 steps 438384 (+1.5%) 438384 (+1.5%) 438384 (+1.5%) 438384 (+1.5%) 1
SL stream latency 128 (+45%) 🔻 177 🔴 (+12%) 197 🔴 (+15%) 354 🔴 (+80%) 🔻 30
SO stream overhead (text) 111 (-21%) 💚 221 (+3.3%) 273 (+21%) 🔻 390 (-21%) 💚 30
SO stream overhead (structured) 119 (-11%) 211 (-22%) 💚 242 (-31%) 💚 364 (-23%) 💚 30

c784f6c

Fri, 31 Jul 2026 16:59:19 GMT · run logs

vercel / nextjs-turbopack

Metric Scenario Best (ms) P75 (ms) P90 (ms) P99 (ms) Samples
TTFS step 1248 (+139%) 🔻 1298 🔴 (+25%) 🔻 1316 🔴 (+23%) 🔻 1333 🔴 (-18%) 💚 30
TTFS stream 1250 (+32%) 🔻 1303 🔴 (+30%) 🔻 1317 🔴 (+28%) 🔻 1360 🔴 (+5.5%) 30
TTFS hook + stream 445 (+5.7%) 1576 🔴 (+19%) 🔻 1584 🔴 (+17%) 🔻 1629 🔴 (-8.0%) 30
STSO 1020 steps (inline) 172 (+5.5%) 465 (-1.9%) 522 (-1.7%) 676 (+0.7%) 1016
STSO 1020 steps (queue-hop) 2432 (+17%) 🔻 3265 (+2.1%) 3265 (+2.1%) 3265 (+2.1%) 3
WO 1020 steps 399054 (-1.4%) 399054 (-1.4%) 399054 (-1.4%) 399054 (-1.4%) 1
SL stream latency 90 (+9.8%) 139 🔴 (+5.3%) 175 🔴 (+19%) 🔻 196 🔴 (-8.8%) 30
SO stream overhead (text) 102 (+1.0%) 149 (-13%) 196 (-8.4%) 344 (+38%) 🔻 30
SO stream overhead (structured) 101 (-8.2%) 179 (+5.9%) 215 (+13%) 322 (+41%) 🔻 30

fedfc7a

Fri, 31 Jul 2026 01:20:43 GMT · run logs

vercel / nextjs-turbopack

Metric Scenario Best (ms) P75 (ms) P90 (ms) P99 (ms) Samples
TTFS step 911 (-9.4%) 1286 🔴 (+18%) 🔻 1321 🔴 (+20%) 🔻 1405 🔴 (-12%) 30
TTFS stream 1239 (+236%) 🔻 1279 🔴 (+21%) 🔻 1298 🔴 (+20%) 🔻 1366 🔴 (+23%) 🔻 30
TTFS hook + stream 1387 (+177%) 🔻 1526 🔴 (+9.0%) 1586 🔴 (+8.0%) 1628 🔴 (+8.8%) 30
STSO 1020 steps (inline) 168 (-8.7%) 466 (-5.1%) 525 (-5.9%) 780 (+3.2%) 1016
STSO 1020 steps (queue-hop) 2241 (+9.0%) 3376 (+21%) 🔻 3376 (+21%) 🔻 3376 (+21%) 🔻 3
WO 1020 steps 399756 (-7.5%) 399756 (-7.5%) 399756 (-7.5%) 399756 (-7.5%) 1
SL stream latency 79 (-8.1%) 144 🔴 (-1.4%) 155 🔴 (-16%) 💚 411 🔴 (+61%) 🔻 30
SO stream overhead (text) 105 (-23%) 💚 146 (-71%) 💚 178 (-81%) 💚 205 (-83%) 💚 30
SO stream overhead (structured) 96 (-14%) 162 (-21%) 💚 223 (-15%) 1745 🔴 (+294%) 🔻 30
ℹ️ Metric definitions & methodology

The collapsed STSO distribution section above buckets every step gap of the sequential-steps run (not a sampled window), split by whether the step ending the gap ran inline — in the same warm process as the step before it, so the gap is pure framework overhead — or after a queue-hop — the first step of a fresh process, which pays queue dispatch, client reinit and event-log replay. Bars overlay the two runs: is main, marks where this run lands, bridges the gap when this run has more samples in a bucket.

Best/P75/P90/P99 deltas compare against the most recent benchmark run on main at the time of this run. 🔻 flags a delta worse than +15%, 💚 one better than −15%.

Metrics — TTFS: time to first step body (in-deployment start() → first step body, deployment clocks) · STSO: step-to-step overhead (gap between consecutive step bodies) · WO: workflow overhead (whole-run time outside step bodies, in-deployment anchored) · SL: stream latency (in-deployment write → read propagation, readAt - writtenAt) · SO: stream overhead (end-to-end write+consume time beyond the modelled generation window)

Scenarios — step: one trivial no-op step, no stream; no hooks, so the run stays in turbo mode (in-process fast path) · stream: one streaming step; no hooks, so the run stays in turbo mode (in-process fast path) · hook + stream: registers a hook before one step, which exits turbo mode (dispatch path) · 1020 steps: 1020 trivial sequential steps; STSO is measured between consecutive steps in the given step ranges, and WO is the whole-run overhead outside step bodies · stream latency: parallel reader/writer steps on a dedicated stream; SL is the in-deployment write->read propagation (readAt - writtenAt) · stream overhead (text): writer streams 300 variable-length text token deltas paced at 100/s for 3s (a haiku-size LLM's token throughput) while a parallel reader drains the whole stream; SO is the end-to-end write+consume time beyond the 3s generation window (overhead/backpressure) · stream overhead (structured): same workload as stream overhead (text), but each delta is an AI-SDK-style structured object ({ type: 'text-delta', id, text }) instead of a raw string, so the SO gap vs the text scenario is the added serialization cost

🔴 marks a percentile over its target (within target is left unmarked). Targets (p75/p90/p99, ms) — TTFS 200/300/600 · SL 50/60/125 · SO 250/500/1000

All metrics are measured from deployment-side timestamps only. Runs are triggered by an in-deployment route that stamps the anchor (clientStart) right before start(), so the CI runner’s request and its path through api.vercel.com sit outside every measured window. TTFS = in-deployment start() → first step body (turbo uses the in-process fast path, non-turbo the dispatch path), and includes the VQS dispatch hop plus any /flow cold start. STSO/WO are measured between step bodies on the deployment. SL is measured inside the workflow (parallel reader/writer steps), so it no longer includes the api.vercel.com read path.

Cold starts are kept in the numbers on purpose — they are part of real bursty-workload latency. The workbench deployment cold-starts the /flow invocation for a large fraction of runs, inflating P75+; the Best column shows the fastest (warm-start) sample for comparison.

@shalabhc
shalabhc marked this pull request as ready for review July 31, 2026 01:34
@shalabhc
shalabhc requested review from a team and ijjk as code owners July 31, 2026 01:34

@TooTallNate TooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the capture, the threading, and the renderer. Approving — this closes a real gap in the histogram section (I've done the deployment-id + time-window hunt this replaces), and the degradation matrix is genuinely complete: every optional field falls back the way the table claims, and the three new renderer tests cover the full/degraded/omitted cases (40/40 pass locally).

One correction worth making before merge — the route comment overclaims what the trace contains. route.ts says the trigger request's span "propagates into the workflow's own spans". That's only true under WORKFLOW_TRACE_MODE=continuous. Nothing in the workbench or benchmarks.yml sets the mode, so the benchmark deployment runs the default linked mode — where each workflow/step invocation is its own trace root, and the trigger request's trace contains only the workflow.start span plus span links to the execution roots. The link is still useful (one hop via span links, and Datadog renders those), but:

  • the comment should say what's actually there, so nobody debugging a weird histogram concludes the run "has no spans" when they open a trigger-only trace; and
  • consider making the link a Datadog APM search on workflow.run.id:<runId> instead of (or alongside) the trace permalink — under linked mode that lands on the run's actual execution spans directly, which is where an STSO investigation actually goes. The run id is already in hand.

Fine to take the comment fix now and the search-link idea as a follow-up — the current link is strictly better than nothing either way.

Verified:

  • The capture is correctly optional end-to-end: optional-chained getActiveSpan() (undefined without OTEL → bare run id), type-guarded on the runner side (typeof data.traceId === 'string'), and sequentialRuns omitted rather than [] when the scenario didn't run — so old artifacts, old deployments, and history re-renders all degrade exactly per the table.
  • Recording all iterations' run refs matches the data: the histograms aggregate samples across iterations, so with BENCH_SEQUENTIAL_ITERATIONS > 1 the comma-joined list is the honest answer. The doc phrase "both histograms come out of the same iteration" is only true for the default single-iteration config — worth a "(iterations, when configured)" tweak since the code already handles N correctly.
  • Baseline matching reuses the same methodology/backend/app key the percentile baselines use (resultKeyFor = the metric key minus the row), so the two sides of the diff can't come from mismatched configurations.
  • The empty changeset is correct — e2e runner, CI scripts, and a workbench route; nothing published changes.

One robustness nit, non-blocking: runId/traceId are spliced into the markdown link unvalidated. The artifact-trust model is consistent with the rest of this renderer, so it's not a security gap — but a cheap shape check (/^[a-z0-9_]+$/i) before rendering the link would keep a malformed value from a buggy deployment from breaking the whole comment's markdown, which is this section's own failure story.

CI: the 2 failures are the nextjs-webpack canary HMR rebuild-count test and its required-check aggregator — the long-running baseline flake, unreachable from a benchmark-comment change.

shalabhc added a commit that referenced this pull request Jul 31, 2026
The route comment claimed the trigger request's span "propagates into
the workflow's own spans". That only holds under
WORKFLOW_TRACE_MODE=continuous. Nothing in the workbench or
benchmarks.yml sets the mode, so the benchmark deployment runs the
default `linked` (packages/core/src/telemetry.ts), where each
workflow/step invocation is its own trace root and the trigger's trace
carries `workflow.start` plus span links out to those roots.

The logged link is still the right entry point -- one hop through the
links, which Datadog renders -- but the comment should describe that,
so nobody opening a trigger-only trace while debugging a histogram
concludes the run produced no spans.

Raised by @TooTallNate in review of #3248.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Co-Authored-By: Shalabh Chaturvedi <7066873+shalabhc@users.noreply.github.com>
@vercel
vercel Bot temporarily deployed to Preview – workflow-docs July 31, 2026 22:49 Inactive
vercel Bot and others added 4 commits August 1, 2026 16:00
The STSO distribution section added in #3213 shows the shape of the
sequential-steps run but not which run produced it, so investigating an
odd-looking bucket meant hunting for the run by deployment id and time
window.

Capture the identity alongside the samples (the mechanism prototyped on
the WIP variance branch, #3107): `/api/bench` returns the trace id of the
span @vercel/otel opened for the trigger request, the runner threads it
through the sequential iteration and records `sequentialRuns` in the
result file, and the renderer prints one line under the histograms with
the run id + Datadog trace link for this run and for the `main` run it is
diffed against.

Every part is optional — a deployment predating the route change yields a
bare run id, and a `main` baseline predating this yields only this run's
side — so the section degrades instead of breaking on mixed-vintage
artifacts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Co-Authored-By: Shalabh Chaturvedi <7066873+shalabhc@users.noreply.github.com>

Co-Authored-By: shalabhc <shalabh.chaturvedi@vercel.com>
The run id and Datadog trace are debugging aids, not part of the
benchmark's reported result, so they belong in the job's own output
rather than in the PR comment body.

Logging them where the runs are produced also makes them available in
two cases the comment could never cover: a local `pnpm bench`, and a
job that fails before the comment step runs.

This drops the comment-rendering side entirely -- `renderSequentialRunLinks`,
the `baselineSequentialRuns` baseline plumbing in `annotateWithBaseline`,
and the `sequentialRuns` field on the result artifact, which existed only
to carry the data to the renderer.

The `main`-baseline side of the link goes away with it: which run produced
the baseline histogram is only knowable at comment-render time, where the
two artifacts are matched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Co-Authored-By: shalabhc <shalabh.chaturvedi@vercel.com>
The route comment claimed the trigger request's span "propagates into
the workflow's own spans". That only holds under
WORKFLOW_TRACE_MODE=continuous. Nothing in the workbench or
benchmarks.yml sets the mode, so the benchmark deployment runs the
default `linked` (packages/core/src/telemetry.ts), where each
workflow/step invocation is its own trace root and the trigger's trace
carries `workflow.start` plus span links out to those roots.

The logged link is still the right entry point -- one hop through the
links, which Datadog renders -- but the comment should describe that,
so nobody opening a trigger-only trace while debugging a histogram
concludes the run produced no spans.

Raised by @TooTallNate in review of #3248.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Co-Authored-By: Shalabh Chaturvedi <7066873+shalabhc@users.noreply.github.com>

Co-Authored-By: shalabhc <shalabh.chaturvedi@vercel.com>
Under the default linked trace mode the trigger's trace holds only
`workflow.start` plus span links, so opening it lands one hop away from
the spans an STSO investigation needs. Log an APM search on
`@workflow.run.id:<runId>` next to it, which goes straight to the run's
execution spans.

Both links are logged rather than one replacing the other: the search
depends on `workflow.run.id` being an indexed span tag in the org, and
the permalink works regardless.

Suggested by @TooTallNate in review of #3248.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Co-Authored-By: Shalabh Chaturvedi <7066873+shalabhc@users.noreply.github.com>

Co-Authored-By: shalabhc <shalabh.chaturvedi@vercel.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants