Repository navigation
feat(js): propagate metric context into timer callbacks - #6342
Merged
Merged
Conversation
mstoykov
requested review from
joanlopez and
szkiba
and removed request for
a team
August 26, 2026 13:03
6 of 8 tasks
mstoykov
temporarily deployed
to
azure-trusted-signing
August 26, 2026 13:09 — with
GitHub Actions
Inactive
mstoykov
temporarily deployed
to
azure-trusted-signing
August 26, 2026 13:11 — with
GitHub Actions
Inactive
szkiba
previously approved these changes
Sep 11, 2026
mstoykov
force-pushed
the
feature/async-group-timers
branch
from
September 15, 2026 07:53
4146bfc to
dbe88bc
Compare
mstoykov
temporarily deployed
to
azure-trusted-signing
September 15, 2026 07:58 — with
GitHub Actions
Inactive
mstoykov
temporarily deployed
to
azure-trusted-signing
September 15, 2026 07:59 — with
GitHub Actions
Inactive
mstoykov
temporarily deployed
to
azure-trusted-signing
September 15, 2026 08:00 — with
GitHub Actions
Inactive
mstoykov
temporarily deployed
to
azure-trusted-signing
September 15, 2026 08:01 — with
GitHub Actions
Inactive
szkiba
approved these changes
Sep 15, 2026
When async-metric-context is enabled, capture the complete tags and metadata active when setTimeout or setInterval registers a callback. Apply a cloned snapshot for each invocation and restore the interrupted context afterward. Callback mutations remain visible to asynchronous work created by the callback but do not leak into its parent or later interval ticks. Repeating intervals reuse the original registration snapshot when they rearm. Timers run outside Sobek promise reactions and therefore require an explicit snapshot. Disabled runs pass callbacks through the existing path without allocating or applying metric context. Tests cover one-shot and repeating timers, complete tag and metadata restoration, callback-mutation isolation, and reusable interval snapshots.
mstoykov
force-pushed
the
feature/async-group-timers
branch
from
September 15, 2026 09:12
dbe88bc to
e1ca2be
Compare
mstoykov
temporarily deployed
to
azure-trusted-signing
September 15, 2026 09:19 — with
GitHub Actions
Inactive
mstoykov
temporarily deployed
to
azure-trusted-signing
September 15, 2026 09:20 — with
GitHub Actions
Inactive
janHildebrandt98
self-requested a review
September 15, 2026 10:04
janHildebrandt98
approved these changes
Sep 15, 2026
inancgumus
added a commit
to grafana/k6-docs
that referenced
this pull request
Sep 15, 2026
Document how to enable asynchronous groups and keep metrics tied to their operation across promises, timers, and protocol callbacks. Related: grafana/k6#6340 Related: grafana/k6#6341 Related: grafana/k6#6342 Related: grafana/k6#6343 Related: grafana/k6#6344
4 of 5 tasks
4 of 5 tasks
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What?
When
async-metric-contextis enabled,setTimeout()andsetInterval()capture the complete tagsand metadata active when their callback is registered. Each callback invocation applies a clone of
that snapshot and restores the context it interrupted afterward.
For repeating intervals, the already-wrapped callback is rearmed so every tick starts from the
original registration snapshot. Mutations made by one tick remain available to Promise work created
by that tick, through the tracker in stack PR 1, but do not leak into the parent or the next tick.
When the feature is disabled, timers use the existing direct callback path without capturing or
applying metric context.
Tests cover one-shot and repeating timers, group-tag propagation, complete tag and metadata
restoration, callback-mutation isolation, and reuse of the interval's registration snapshot. The
Promise tracker from stack PR 1 separately covers async descendants created by a timer callback.
Why?
Timer callbacks are scheduled by k6's timer and event-loop implementation, not as Sobek Promise
reactions. The Promise tracker therefore cannot infer the context in which
setTimeout()orsetInterval()was called. Without an explicit snapshot, a timer fires under whatever mutable VUcontext happens to be live at dispatch time, which can attribute its checks, custom metrics, and
asynchronous descendants to an unrelated group or set of tags.
Registration time is the stable ownership boundary: it reflects the operation that created the
timer. Dispatch-time capture would preserve the race, while carrying only the group tag would make
custom tags and metadata behave differently from Promise continuations.
Alternatives considered:
timer and would affect unrelated internal tasks. Capturing in the timer API keeps the ownership rule
explicit while reusing the common helper from stack PR 1.
ticks. Reusing the original wrapped callback gives intervals repeatable registration-time
semantics.
group()would miss timers registered under custom tag or metadatacontexts and timers created without importing
k6.Checklist
make check) and all pass.Checklist: Documentation (only for k6 maintainers and if relevant)
Please do not merge this PR until the following items are filled out.
k6-documentation: TBD for async metric-context semantics
TypeScript definitions:
not applicable; timer signatures do not change
Related PR(s)/Issue(s)
groupdoesn't work with async calls well (#2728)โ its callback section describes the per-API boundary
(#5673)