Skip to content

Add in-memory trace analysis for user timings and custom DevTools tracks #12

@V3RON

Description

@V3RON

Trace capture currently stops at raw event collection. trace start / trace stop can record and optionally save traceEvents, but agents cannot inspect performance.measure, performance.mark, console.timeStamp, or DevTools custom track/group data through the CLI while the daemon is running. This makes trace support much less useful for agent workflows, because the only artifact is a potentially huge raw trace file that is expensive to inspect and too large to dump into stdout.

Observed Findings

  • The current trace surface is limited to trace start and trace stop [--file PATH] in packages/agent-cdp/src/cli.ts.
  • packages/agent-cdp/src/trace.ts contains a small TraceRecorder that starts CDP tracing, collects Tracing.dataCollected payloads, and optionally writes { traceEvents: [...] } JSON to disk.
  • The recorder already enables categories that are relevant for this feature, including blink.user_timing and blink.console.
  • packages/agent-cdp/src/daemon.ts currently routes start-trace and stop-trace directly to TraceRecorder, and stop-trace only returns a simple summary with eventCount and optional filePath.
  • There is no in-memory trace session store, no CLI navigation commands for traces, and no parsing layer for user timings or custom DevTools performance extensions.
  • Chrome DevTools frontend handles this in layers: UserTimingsHandler parses performance.mark, performance.measure, and console.timeStamp, and ExtensionTraceDataHandler extracts custom track/group metadata from Performance API detail.devtools payloads and from console.timeStamp arguments.
  • We should keep the explicit trace lifecycle: tracing must not start on daemon startup. Recording should begin only when the user or agent runs trace start.
  • Token efficiency matters: this feature must provide navigable summaries, filtering, pagination, and drill-down commands instead of dumping all trace entries into stdout.

Suggested Behavior

Keep packages/agent-cdp/src/trace.ts as the raw recorder and introduce a new nested trace analysis module under packages/agent-cdp/src/trace/.

User-facing CLI

Extend the existing trace command family with in-memory analysis commands:

  • trace start
  • trace stop [--file PATH]
  • trace status
  • trace list [--limit N] [--offset N]
  • trace summary [--session ID]
  • trace tracks [--session ID] [--limit N] [--offset N] [--text TEXT] [--group NAME]
  • trace entries [--session ID] [--track NAME] [--type measure|mark|stamp] [--text TEXT] [--start-ms N] [--end-ms N] [--limit N] [--offset N] [--sort time|duration|name]
  • trace entry --id ENTRY_ID [--session ID]

Core behavior

  • trace start starts raw tracing only. Do not auto-start tracing on daemon startup.
  • trace stop stops tracing, analyzes the collected traceEvents, stores an analyzed trace session in daemon memory, and optionally exports the raw trace JSON to --file.
  • All query commands should default to the latest analyzed trace session when --session is omitted.
  • Keep multiple stored trace sessions in memory behind a bounded session store. Initial default retention can be small, for example 10 sessions.
  • Default outputs must be compact and paginated.

Data model

Treat all performance.measure entries the same regardless of whether they use a custom track. Tracks should be a navigation/filtering concept, not a separate primary entry model.

Use a unified normalized entry shape that can represent:

  • plain performance.measure
  • custom-track performance.measure
  • plain performance.mark
  • extension-marker performance.mark
  • console.timeStamp

Suggested normalized fields:

  • entryId
  • type: "measure" | "mark" | "stamp"
  • source: "performance" | "console"
  • name
  • track
  • trackKind: "default" | "custom"
  • trackGroup?
  • startMs
  • durationMs
  • color?
  • tooltipText?
  • properties?
  • userDetail?
  • isExtension

Also build a normalized track model with fields such as:

  • trackId
  • name
  • kind: "default" | "custom"
  • group?
  • entryCount
  • measureCount
  • markCount
  • stampCount
  • startMs
  • endMs

Module layout

Add a new feature directory under packages/agent-cdp/src/trace/:

  • index.ts - main trace service class used by the daemon
  • types.ts - analyzed session, entry, track, and query result types
  • store.ts - bounded in-memory trace session store
  • load.ts - raw trace loading and validation helpers
  • user-timings.ts - parsing and pairing logic for user timing and console timestamp events
  • extensions.ts - extraction of DevTools custom track/group/color/tooltip/properties metadata
  • query.ts - summary, tracks, entries, and single-entry queries
  • formatters.ts - compact CLI output formatters

Keep packages/agent-cdp/src/trace.ts focused on raw trace capture and file export.

Parsing expectations

Model the parsing logic after Chrome DevTools frontend semantics where correctness depends on it.

Required parsing support:

  • performance.measure() events, including the paired event semantics used by DevTools
  • performance.mark() events
  • console.timeStamp() events
  • custom DevTools Performance API payloads from detail.devtools
  • custom track metadata from console.timeStamp(..., trackName, trackGroup, color)
  • console.timeStamp duration semantics where start and end can be tracing-clock numbers or references to previously named timestamps

Track and group extraction should support:

  • detail.devtools.track
  • detail.devtools.trackGroup
  • detail.devtools.color
  • detail.devtools.tooltipText
  • detail.devtools.properties
  • console.timeStamp track, trackGroup, color

Implementation should be best-effort for unknown trace events. Unsupported or malformed individual events should not fail the entire trace analysis unless the overall trace structure is invalid.

IPC and daemon integration

Extend packages/agent-cdp/src/types.ts IPC command union with trace query commands, for example:

  • trace-status
  • trace-list-sessions
  • trace-summary
  • trace-tracks
  • trace-entries
  • trace-entry

Keep existing:

  • start-trace
  • stop-trace

Update packages/agent-cdp/src/daemon.ts to route these commands to a trace service object rather than to TraceRecorder directly.

stop-trace should evolve from returning only { eventCount, filePath? } to returning a richer stop result that includes at least:

  • sessionId
  • eventCount
  • filePath?
  • trackCount
  • entryCount
  • durationMs

Token-efficient output design

This feature should optimize for agent navigation rather than completeness of one command.

Recommended defaults:

  • trace summary: small session summary with session metadata, event count, entry counts by type, track count, group count, and top tracks.
  • trace tracks: paginated one-line-per-track list with track name, kind, group, entry count, and time span.
  • trace entries: latest session by default, type=measure by default, limit=20 by default, sort=duration by default, compact one-line rows.
  • trace entry: full detail for one selected item only.

Do not print all properties, tooltips, or nested detail payloads in list commands unless verbose output is explicitly requested.

CLI responsibilities

packages/agent-cdp/src/cli.ts should remain a thin parser/dispatcher/formatter. Add usage text, flag parsing, and formatter calls for the new trace subcommands, but keep parsing and query logic inside the new src/trace/ module.

Testing plan

Keep recorder tests focused on raw capture. Add new analysis/query tests with fixture traces that cover:

  • plain performance.measure
  • plain performance.mark
  • performance.measure with detail.devtools.track and trackGroup
  • performance.mark with extension marker payloads
  • console.timeStamp custom track entries
  • console.timeStamp entries that derive duration from named start and end references
  • mixed built-in and custom tracks in the same session

Add CLI tests for:

  • usage text updates
  • new flag parsing
  • default command behavior where practical

Acceptance criteria

  • Tracing still does not start automatically on daemon startup.
  • trace start explicitly begins recording and fails if a trace is already active.
  • trace stop stores an analyzed trace session in daemon memory and can still optionally export the raw trace file.
  • Query commands work against the latest trace session by default and support explicit --session selection.
  • trace tracks lists both built-in/default and custom tracks.
  • trace entries includes plain performance.measure entries and can filter by track.
  • trace entry --id ... returns a single entry with full details.
  • Default outputs are compact, paginated, and suitable for agent consumption without flooding the context window.
  • Parsing logic remains separate from TraceRecorder.

Resolution Summary

The trace feature should continue to use explicit start/stop capture, but gain a separate in-memory analysis layer that parses user timings and custom DevTools track metadata into bounded, queryable trace sessions. After this change, agents should be able to inspect trace summaries, tracks, and filtered entries directly from the running daemon without relying on large raw trace dumps.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions