Skip to content

Agent Debug: Converge debug data with JSONL as single source of truth#4954

Draft
vijayupadya wants to merge 6 commits intomainfrom
vijayu/dgbEventsConvergence
Draft

Agent Debug: Converge debug data with JSONL as single source of truth#4954
vijayupadya wants to merge 6 commits intomainfrom
vijayu/dgbEventsConvergence

Conversation

@vijayupadya
Copy link
Copy Markdown
Contributor

@vijayupadya vijayupadya commented Apr 3, 2026

Converges the two independent chat debug event systems (in-memory span store for debug panel + JSONL file logger for troubleshoot skill) into a single architecture where JSONL is the source of truth and the debug panel reads from it.

Chat Debug Event System: Convergence

Problem (Before)

Two independent systems consumed OTel debug events via separate subscriptions and separate conversion paths:

  1. OTelChatDebugLogProvider — in-memory 10K span array → Debug Panel UI
  2. ChatDebugFileLoggerService — JSONL on disk → Troubleshoot Skill

Architecture (Before)

┌─────────────────────────────────────────────────────────────────────────────┐
│                        IOTelService (Event Source)                          │
│                                                                             │
│          onDidCompleteSpan              onDidEmitSpanEvent                  │
│               │    │                        │    │                          │
└───────────────┼────┼────────────────────────┼────┼──────────────────────────┘
                │    │                        │    │
       ┌────────┘    └──────────┐    ┌────────┘    └──────────┐
       │                        │    │                        │
       ▼                        ▼    ▼                        ▼
┌──────────────────────────────────────┐  ┌──────────────────────────────────┐
│  OTelChatDebugLogProvider            │  │  ChatDebugFileLoggerService      │
│  (Debug Panel)                       │  │  (File Logger)                   │
│                                      │  │                                  │
│  ┌──────────────────────────┐        │  │  ┌──────────────────────────┐    │
│  │ Direct OTel Subscription │        │  │  │ Direct OTel Subscription │    │
│  └────────────┬─────────────┘        │  │  └────────────┬─────────────┘    │
│               │                      │  │               │                  │
│               ▼                      │  │               ▼                  │
│  ┌──────────────────────────┐        │  │  ┌──────────────────────────┐    │
│  │ _allSpans[]              │        │  │  │ _spanToEntry()           │    │
│  │ (in-memory, max 10K)     │        │  │  └────────────┬─────────────┘    │
│  │                          │        │  │               │                  │
│  └────────────┬─────────────┘        │  │               ▼                  │
│               │                      │  │  ┌──────────────────────────┐    │
│  ┌────────────┼─────────────┐        │  │  │ Buffer (4s flush)        │    │
│  │ _sessionSpanIndices      │        │  │  └────────────┬─────────────┘    │
│  │ _spanIdIndex             │        │  │               │                  │
│  │ _sessionOrder            │        │  │               ▼                  │
│  └────────────┬─────────────┘        │  │  ┌──────────────────────────┐    │
│               │                      │  │  │ JSONL on disk            │    │
│  ┌────────────┼─────────────┐        │  │  │ + system_prompt_N.json   │    │
│  │ LRU Eviction +           │        │  │  │ + tools_N.json           │    │
│  │ Async Compaction         │        │  │  │ + models.json            │    │
│  │                          │        │  │  └────────────┬─────────────┘    │
│  └────────────┬─────────────┘        │  │               │                  │
│               │                      │  └───────────────┼──────────────────┘
│               ▼                      │                  │
│  ┌──────────────────────────┐        │                  ▼
│  │ completedSpanToDebugEvent│        │  ┌──────────────────────────────────┐
│  │ extractConversationEvents│        │  │  Troubleshoot Skill              │
│  │ spanEventToUserMessage   │        │  │  (reads JSONL via grep/jq)       │
│  └────────────┬─────────────┘        │  └──────────────────────────────────┘
│               │                      │
│               ▼                      │
│  ┌──────────────────────────┐        │   ┌─────────────────────────────────┐
│  │ Debug Panel UI           │        │   │ VS Code Core API                │
│  └──────────────────────────┘        │   │ onDidReceiveChatDebugEvent      │
│                                      │   │ (discovery, skills)             │
└──────────────────────────────────────┘   │         │                       │
                                           └─────────┼───────────────────────┘
                                                     │
                                                     └──► File Logger only
                                                          (panel doesn't get these)

Architecture (After)

┌─────────────────────────────────────────────────────────────────────────────┐
│                        IOTelService (Event Source)                          │
│          onDidCompleteSpan              onDidEmitSpanEvent                  │
│                    │                           │                            │
└────────────────────┼───────────────────────────┼────────────────────────────┘
                     │                           │
                     └──────────┬────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│  ChatDebugFileLoggerService (unchanged OTel subscription)                   │
│                                                                             │
│  ┌──────────────────────────┐     ┌──────────────────────────────────────┐  │
│  │ OTel Subscription        │     │ VS Code Core API                     │  │
│  │ (same as before)         │     │ onDidReceiveChatDebugEvent           │  │
│  └────────────┬─────────────┘     │ (discovery events)                   │  │
│               │                   └──────────────┬───────────────────────┘  │
│               │                                  │                          │
│               ▼                                  │                          │
│  ┌──────────────────────────┐                    │                          │
│  │ _spanToEntry()           │◄───────────────────┘                          │
│  └────────────┬─────────────┘                                               │
│               │                                                             │
│               ▼                                                             │
│  ┌──────────────────────────┐     ┌──────────────────────────────────┐      │
│  │ _bufferEntry()           │────►│ onDidEmitEntry(sessionId, entry) │      │
│  └────────────┬─────────────┘     │ (Emitter, fires sync pre-flush)  │      │
│               │                   └────────────────┬─────────────────┘      │
│               ▼                                    │                        │
│  ┌──────────────────────────┐                      │                        │
│  │ Flush → JSONL on disk    │                      │                        │
│  │ + system_prompt_N.json   │                      │                        │
│  │ + tools_N.json           │                      │                        │
│  └──────────────────────────┘                      │                        │
│                                                    │                        │
│  Read APIs:                                        │                        │
│  ┌──────────────────────────┐                      │                        │
│  │ readTailEntries(sid, N)  │  ← reads last N      │                        │
│  │ streamEntries(sid, cb)   │  ← streaming parser  │                        │
│  │ readEntries(sid)         │  ← full read         │                        │
│  └────────────┬─────────────┘                      │                        │
│               │                                    │                        │
└───────────────┼────────────────────────────────────┼────────────────────────┘
                │                                    │
                │  (on panel open:                   │  (while panel open:
                │   read history from JSONL)         │   live events)
                │                                    │
                ▼                                    ▼
┌─────────────────────────────────────────────────────────────────────┐
│  OTelChatDebugLogProvider (STATELESS)                               │
│                                                                     │
│        1 — Fast initial load:                                       │
│    readTailEntries(sid, 500) → latest 500 events → return to core   │
│                                                                     │
│        2 — Background backfill:                                     │
│    streamEntries(sid, cb) → stream older events via progress        │
│    (deduplicated; core binary-inserts by timestamp)                 │
│                                                                     │
│        3 — Live events:                                             │
│    onDidEmitEntry → filter by session → stream to UI                │
│                                                                     │
│  Detail resolution:                                                 │
│    LRU cache (1000 entries) → on miss, scan JSONL on disk           │
│    Reads details (e.g. system_prompt_N.json / tools_N.json on demand|
│                                                                     │
│  On panel close: clear all caches → zero memory                     │
└─────────────────────────────────────────────────────────────────────┘

Unchanged:
┌──────────────────────────────────┐
│  Troubleshoot Skill              │
│  (reads JSONL via grep/jq)       │
│  (same files, no changes)        │
└──────────────────────────────────┘

Extensibility

Future consumer requires one subscription:

//IDebugLogEntry is now the canonical event format. Future consumers (e.g., SQLite projection) subscribe with one line:
fileLogger.onDidEmitEntry(({ sessionId, entry }) => store.insert(sessionId, entry));

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Converges agent/chat debug logging onto a single JSONL-on-disk source of truth by extending the debug file logger contract (read/stream + live entry events) and updating the VS Code chat debug panel provider to read/stream from those JSONL logs instead of maintaining its own in-memory span store.

Changes:

  • Extends IChatDebugFileLoggerService with onDidEmitEntry plus read/stream APIs and promotes IDebugLogEntry to the platform layer as the canonical schema.
  • Refactors the chat debug panel provider to load history from JSONL (tail-first + background backfill) and stream live events from the logger’s new event.
  • Updates the node logger implementation to support entry streaming/tail reads and to better handle resumed sessions and early tool definition events.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
src/platform/chat/common/chatDebugFileLoggerService.ts Adds canonical IDebugLogEntry type and new logger APIs for live emission + reading/streaming JSONL.
src/extension/chat/vscode-node/chatDebugFileLoggerService.ts Implements onDidEmitEntry + JSONL read/tail/stream methods; adjusts session resume + tools handling.
src/extension/trajectory/vscode-node/otelSpanToChatDebugEvent.ts Adds converters from IDebugLogEntry to VS Code debug panel event types and detail resolvers.
src/extension/trajectory/vscode-node/otelChatDebugLogProvider.ts Replaces in-memory span storage with JSONL-backed loading/streaming, deduping, and detail resolution from disk.

@OrenMe
Copy link
Copy Markdown

OrenMe commented Apr 3, 2026

Will this ensure that sessions are kept even between restarts so they can be viewed in the agent debug logs?

@vijayupadya
Copy link
Copy Markdown
Contributor Author

Will this ensure that sessions are kept even between restarts so they can be viewed in the agent debug logs?

Yes, that is one of the main benefits of this change.

@OrenMe
Copy link
Copy Markdown

OrenMe commented Apr 3, 2026

Nice, thanks for working on this!
I originally created https://marketplace.visualstudio.com/items?itemName=OrenMelamed.chat-workflow-viewer

It is using the jsonl files so you can access the data as long as files are there so this is a really good addition

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR converges the chat debug event system so JSONL files become the single source of truth for both the Debug Panel UI and the troubleshoot/diagnostics flows, removing the prior split between in-memory span storage and file logging.

Changes:

  • Adds a canonical IDebugLogEntry schema plus realtime + read APIs (onDidEmitEntry, readEntries, readTailEntries, streamEntries) to the chat debug file logger service.
  • Refactors OTelChatDebugLogProvider to be stateless and backed by JSONL (fast tail load + streamed backfill + live streaming via onDidEmitEntry).
  • Updates settings UX to deprecate the old toggle and document the canonical file-logging toggle.
Show a summary per file
File Description
src/platform/configuration/common/configurationService.ts Marks debug logging toggle relationship and deprecates the old setting during transition.
src/platform/chat/common/chatDebugFileLoggerService.ts Extends the service interface with canonical entry schema + live/read APIs.
src/extension/chat/vscode-node/chatDebugFileLoggerService.ts Implements the new APIs, adds realtime emission, and resume behavior changes.
src/extension/chat/vscode-node/test/chatDebugFileLoggerService.spec.ts Adds unit coverage for the new read/stream APIs and realtime emitter.
src/extension/trajectory/vscode-node/otelSpanToChatDebugEvent.ts Adds converters/resolvers from IDebugLogEntry to VS Code debug panel events.
src/extension/trajectory/vscode-node/otelChatDebugLogProvider.ts Switches debug panel provider to read/stream from JSONL and subscribe to live entries.
src/extension/trajectory/vscode-node/test/debugLogEntryConverters.spec.ts Adds tests for the new entry→event converter and dedup key behavior.
package.nls.json Updates setting descriptions and introduces deprecation messaging text.
package.json Adds a deprecationMessage for the deprecated setting.

Copilot's findings

  • Files reviewed: 9/9 changed files
  • Comments generated: 2

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR converges the agent/chat debug pipeline so JSONL log files become the single source of truth: the debug panel now reads historical + live events from the file logger instead of maintaining its own in-memory span store.

Changes:

  • Extends IChatDebugFileLoggerService with live-entry events and read APIs (onDidEmitEntry, readEntries, readTailEntries, streamEntries) and updates the node implementation accordingly.
  • Reworks OTelChatDebugLogProvider to be stateless: initial tail load + background backfill from JSONL, plus live streaming via onDidEmitEntry, with on-demand detail resolution from disk.
  • Adds child-session routing attributes for tool/subagent spans and updates settings metadata (deprecation messaging + canonical toggle).
Show a summary per file
File Description
src/platform/configuration/common/configurationService.ts Marks legacy debug setting as deprecated; clarifies canonical toggle.
src/platform/chat/common/chatDebugFileLoggerService.ts Expands file logger interface to support live streaming + read APIs; defines canonical IDebugLogEntry.
src/extension/chat/vscode-node/chatDebugFileLoggerService.ts Implements new interface APIs, child-session routing, resume/run-index stamping, and emits entries pre-flush.
src/extension/chat/vscode-node/test/chatDebugFileLoggerService.spec.ts Adds/adjusts tests to cover the new read/stream/emit behaviors.
src/extension/trajectory/vscode-node/otelSpanToChatDebugEvent.ts Adds converters from IDebugLogEntry → VS Code debug panel events + detail resolution helpers.
src/extension/trajectory/vscode-node/otelChatDebugLogProvider.ts Switches provider to JSONL-backed loading/streaming and disk-based detail resolution; keeps OTLP export/import support.
src/extension/trajectory/vscode-node/test/debugLogEntryConverters.spec.ts Adds unit coverage for entry conversion/dedup key behavior.
src/extension/tools/vscode-node/toolsService.ts Stamps parent session / label attributes onto tool spans for child-session routing.
src/extension/intents/node/toolCallingLoop.ts Registers subagent sessions as child sessions with the file logger prior to span completion.
package.nls.json Updates setting descriptions and adds deprecation text.
package.json Adds deprecation message to legacy setting contribution.

Copilot's findings

  • Files reviewed: 11/11 changed files
  • Comments generated: 4

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.

3 participants