Skip to content

Conversation

@sy-nico
Copy link
Contributor

@sy-nico sy-nico commented Jan 14, 2026

Issue Pull Request

Linear Issue

SY-3420

Description

Adds CDP profiling. Can be enabled for integration tests or run manually using the console_pprof.py script, which mirrors to go profiling tool.

To run manually, simply

  • Run the Console (either standalone or emebedded in the Core`)
  • cd integration
  • uv run console-pprof
    • --heap will save the heap snapshot
    • --trace will save the playwright trace

The script will automatically open the cpu profile using speedscope.
image

Greptile Summary

Added Chrome DevTools Protocol (CDP) profiling capabilities for Console integration tests and standalone use. The implementation provides CPU profiling, heap snapshots, and Playwright tracing with a clean, modular architecture.

Key Changes:

  • Created console.profiling package with CDPProfiler, ProfilerConfig, ProfileWriter, and Profiler protocol
  • Integrated profiler into ConsoleCase test base class with proper lifecycle management (tracing starts before page creation, CDP profiling after)
  • Added standalone console-pprof script mirroring go pprof tool with automatic speedscope integration
  • Extended test conductor CLI with --console-profile, --console-trace, and --console-heap flags
  • Profiles saved to integration/profiles/ directory (added to gitignore)

Architecture:
The profiler uses CDP for CPU profiles and heap snapshots, and Playwright's built-in tracing API. The design properly separates configuration, client logic, and file writing with clean protocol definitions.

Issue Found:

  • Documentation in console/case.py:30-37 incorrectly states defaults are True when they're actually False per config.py:41-47

Confidence Score: 4/5

  • Safe to merge with one minor documentation correction needed
  • Well-architected implementation with clean separation of concerns, proper error handling, and comprehensive documentation. The only issue is incorrect default values in documentation comments. Code quality is high with type annotations, proper resource cleanup, and follows Python best practices.
  • integration/console/case.py needs documentation fix for default values

Important Files Changed

Filename Overview
integration/console/profiling/config.py Configuration dataclass for profiler settings with environment variable support
integration/console/profiling/client.py CDPProfiler implementation with proper CDP session lifecycle management
integration/console/case.py Integrated CDP profiling into ConsoleCase with context-based page creation and profiler lifecycle, documentation has incorrect default values
integration/scripts/console_pprof.py Standalone profiling script mirroring go pprof tool with automatic speedscope integration
integration/framework/test_conductor.py Added CLI arguments for console profiling features (--console-profile, --console-trace, --console-heap)

Sequence Diagram

sequenceDiagram
    participant User
    participant TestConductor
    participant ConsoleCase
    participant ProfilerConfig
    participant BrowserContext
    participant CDPProfiler
    participant CDPSession
    participant ProfileWriter

    User->>TestConductor: Run test with --console-profile
    TestConductor->>TestConductor: Set PLAYWRIGHT_CONSOLE_PROFILE=1
    TestConductor->>ConsoleCase: setup()
    
    ConsoleCase->>ProfilerConfig: from_params(params)
    ProfilerConfig-->>ConsoleCase: config (cpu_profiling=True)
    
    ConsoleCase->>BrowserContext: new_context()
    BrowserContext-->>ConsoleCase: context
    
    alt Tracing enabled
        ConsoleCase->>BrowserContext: tracing.start()
    end
    
    ConsoleCase->>BrowserContext: new_page()
    BrowserContext-->>ConsoleCase: page
    
    ConsoleCase->>CDPProfiler: new(page, context, config)
    CDPProfiler-->>ConsoleCase: profiler
    
    ConsoleCase->>CDPProfiler: start_cdp_profiling()
    CDPProfiler->>BrowserContext: new_cdp_session(page)
    BrowserContext-->>CDPProfiler: cdp_session
    CDPProfiler->>CDPSession: send("Profiler.enable")
    CDPProfiler->>CDPSession: send("Profiler.start")
    
    Note over ConsoleCase: Test execution
    
    ConsoleCase->>CDPProfiler: stop(test_name)
    
    alt Heap snapshot enabled
        CDPProfiler->>CDPSession: send("HeapProfiler.enable")
        CDPProfiler->>CDPSession: on("HeapProfiler.addHeapSnapshotChunk")
        CDPProfiler->>CDPSession: send("HeapProfiler.takeHeapSnapshot")
        CDPSession-->>CDPProfiler: heap chunks
        CDPProfiler->>ProfileWriter: write_heap_snapshot()
        ProfileWriter-->>CDPProfiler: heapsnapshot path
    end
    
    CDPProfiler->>CDPSession: send("Profiler.stop")
    CDPSession-->>CDPProfiler: profile data
    CDPProfiler->>ProfileWriter: write_cpu_profile()
    ProfileWriter-->>CDPProfiler: cpuprofile path
    
    alt Tracing enabled
        CDPProfiler->>BrowserContext: tracing.stop(path)
        BrowserContext-->>CDPProfiler: trace.zip path
    end
    
    ConsoleCase->>CDPProfiler: close()
    CDPProfiler->>CDPSession: detach()
Loading

@sy-nico sy-nico requested a review from emilbon99 January 14, 2026 18:56
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

11 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@sy-nico
Copy link
Contributor Author

sy-nico commented Jan 14, 2026

Mentioned previously offline, another profiling avenue to explore is the using WebView2 remote debugging of the Tauri desktop app. However, this is only supported on Windows (Chromium) and not Linux or macOS (WebKit).

A third alternative is rust native profiling, which was explored in the other SY-3420 pull request.

Copy link
Contributor

@emilbon99 emilbon99 left a comment

Choose a reason for hiding this comment

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

Seems like there are some comments that are redundant

from console.profiling.config import ProfilerConfig


class Profiler(Protocol):
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the plan to shift this out of the console eventually? I.e. to use the same protocol for the go,C++ tooling?

Copy link
Contributor Author

@sy-nico sy-nico Jan 16, 2026

Choose a reason for hiding this comment

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

Removed the Profiler Protocol since it was dead code

A shared Python Protocol for Go/C++ profiling wouldn't provide meaningful value since they are fundamentally different.

  • Console uses CDP WebSocket commands vs HTTP endpoints (net/http/pprof) vs system calls (perf)
  • .cpuprofile (JSON) vs .pprof (protobuf) vs perf.data (binary)
  • Dependencies: Playwright vs built-in Go vs platform tools

If we add C++ profiling, they could be separate implementations unified at the CLI level (e.g., synnax-profile console|server|driver) rather than via a shared abstract interface.

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