chore(tracing): extract format, reader, and writer (TracingSession) into packages/tracing#40671
Open
dgozman wants to merge 6 commits intomicrosoft:mainfrom
Open
chore(tracing): extract format, reader, and writer (TracingSession) into packages/tracing#40671dgozman wants to merge 6 commits intomicrosoft:mainfrom
dgozman wants to merge 6 commits intomicrosoft:mainfrom
Conversation
Move the trace format types from packages/trace/ and the reader/model from packages/isomorphic/trace/ into a new packages/tracing/ library (format/ + reader/ + versions under format/). Drop the @trace/* alias in favor of @tracing/*; @isomorphic/trace/* path is gone (callers repointed to @tracing/reader/*). Local copies of small protocol types (StackFrame, Point, SerializedError, ClientSideCallMetadata) live in packages/tracing/src/format/protocolTypes.ts so the new package has no @protocol/* dependency. This is a pure code motion + import rename. Phase 1 of a larger refactor that will also extract a TracingSession writer (server-side trace recording state machine) into packages/tracing/src/writer/.
Move the trace zip assembly (`zip`) and call-stack session bookkeeping
(`tracingStarted`, `traceDiscarded`, `addStackToTracingNoReply`) out of
`packages/playwright-core/src/server/localUtils.ts` and into
`packages/tracing/src/writer/`. The library functions take an
`AbortSignal` instead of a `Progress`; a tiny `race(signal, promise)`
helper in `packages/tracing/src/writer/race.ts` does the
abort-vs-promise race. The dispatcher passes `progress.signal` and
keeps the outer `progress.race(...)` so the eslint progress-rule
stays satisfied. HAR functions in `localUtils.ts` are left untouched.
The new package has no package.json; sources are bundled and
deps live in the root devDependencies. Per-file
\`node_modules/{fs,os,path,events,yauzl,yazl,mime}\` declarations
in \`packages/tracing/src/DEPS.list\` cover what writer/ needs.
…kages/tracing/writer snapshotterInjected.ts is pure DOM logic (no Playwright internals) and now lives next to the rest of the writer; snapshotter.ts imports it via @tracing/writer/snapshotterInjected. mergeTraceFiles, previously a private helper at the bottom of testTracing.ts, is now a generic library function. The test-trace-entry-name special case is exposed as an optional `keepEntryName` parameter; the test runner passes `testTraceEntryName`.
…nto it Extract the disk-backed writer state machine — RecordingState (traceFile/networkFile/resourcesDir/chunkOrdinal/sha1 sets/recording/groupStack), the SerializedFS and tmp-dir lifecycle, the appendTraceEvent / appendResource / appendNetworkEntry path-and-flush logic, the chunk-allocate / change-trace-name routines, and group / groupEnd / closeAllGroups bookkeeping — out of packages/playwright-core/src/server/trace/recorder/tracing.ts and into packages/tracing/src/writer/tracingSession.ts. The session takes an AbortSignal (not a Progress) on stopChunk/stop and uses the local race() helper. A small `replacer` callback handles non-JSON-serializable values (Dispatcher, Buffer, Date) so the session itself stays free of Playwright server types. Server-side Tracing keeps its InstrumentationListener / Snapshotter / HarTracer / screencast roles and forwards every event into the session. _callIds and the original start() options (needed for snapshotter/screencast wiring) move from the recording state onto Tracing as plain fields. tracing.ts drops from ~830 lines to ~530; the rest is the listener methods and screencast/snapshotter glue that genuinely depend on Playwright internals.
Drop the in-memory _traceEvents[] buffer and the separate _liveTraceFile
plumbing in packages/playwright/src/worker/testTracing.ts. Test-runner
events now stream to disk through a TracingSession (one chunk per test,
trace name "<testId>[-retry<N>]-test" so the live viewer's testId-prefix
scan still finds the on-disk .trace file). The final trace.zip is built
by session.stopChunk('archive') and merged with playwright-core's
per-context chunks via mergeTraceFiles.
Attachments and source files are now resolved at append time (sync
fs.readFileSync) and stored as session resources keyed by content sha1
(or src@<pathSha1>.txt for sources). The _options.attachments=false /
sources=false toggles work by skipping the resource step before
emitting the trace event, instead of via a finalize-time filter pass.
testTimeout can change late in the test, so testTracing emits
context-options twice: once at chunk start (with the value at that
point, possibly undefined) and once again in stopIfNeeded with the
final testInfo.timeout. The reader processes events in order and
overwrites context-entry fields, so last-write-wins gives the right
testTimeout in the model.
Two TracingSession tweaks went alongside:
- New `traceEntryName` option (default 'trace.trace'). The test runner
passes 'test.trace' so its main entry survives mergeTraceFiles
unrenamed.
- startChunk no longer auto-emits contextCreatedEvent. Callers
(server Tracing and TestTracing) now appendTraceEvent it
explicitly — server patches walltime/monotonic at chunk start;
TestTracing emits the constructor-time copy and re-emits at stop.
When `sources: true` is set on TracingSession.start(), the session now
walks event.stack[].file for the two event types that carry a stack
('before' and 'error') and accumulates unique source-file paths
per-chunk. At stopChunk time those files are embedded as
`resources/src@<pathSha1>.txt` entries directly from disk (no copy
through resourcesDir).
testTracing.ts loses its _appendSourcesFromStack helper and the
_emittedSourceFiles dedup set: it now just passes
`sources: !!_options.sources` to session.start() and the session does
the rest. As a side effect the per-step sync fs.readFileSync on every
appendBeforeActionForStep / appendForError goes away — source reads
happen once at chunk stop.
Server-side Tracing opts out explicitly with `sources: false`
(per-context source embedding is owned by LocalUtils.zip via the
StackSession callStacks, not the session, so leaving it on would
have been redundant — and worse, would have started pulling
source files in for tracing.group event stacks).
A new tiny helper packages/tracing/src/writer/sourceFiles.ts owns
the `resources/src@<pathSha1>.txt` naming convention so both
TracingSession.stopChunk and LocalUtils.zip use the same form.
pavelfeldman
approved these changes
May 6, 2026
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.
Summary
Pulls the trace format types, the reader/model, and a new disk-backed
TracingSessionwriter out ofplaywright-coreand the test runner into a self-containedpackages/tracing/library with no@protocol/*or Playwright-server dependency.packages/tracing/src/format/— waspackages/trace/src/. NewprotocolTypes.tscarries local copies of the small structural types previously imported from@protocol/channels(StackFrame,Point,SerializedError,ClientSideCallMetadata).packages/tracing/src/reader/— waspackages/isomorphic/trace/.packages/tracing/src/writer/— new.TracingSessionis the disk-backed state machine extracted from servertracing.ts(RecordingState,SerializedFS, append/resource/network/zip lifecycle, group stack, source-file collection).zip.ts/stackSession.tsare the trace-related halves ofLocalUtils.mergeTraceFiles.tsandsnapshotterInjected.tsco-locate here too.tracing.tsand workertestTracing.tsare now thin wrappers overTracingSession. The test runner's in-memory_traceEvents[]buffer and separate live-trace file are gone — events stream to disk through the session.localUtils.tsare intentionally left untouched (not strictly trace-related).progress: Progressparameters in the moved zip / stack-session functions becomesignal: AbortSignal+ a small localrace(signal, promise)helper.The branch is split into seven self-contained commits, each green on
flintand the trace + library + artifacts test suites.