Skip to content
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
f080f0b
feat: add core graph execution debugging infrastructure
ogabrielluiz Oct 18, 2025
8bce7cc
test: add comprehensive test suite for execution debugger
ogabrielluiz Oct 18, 2025
c61d063
feat: add interactive debugging examples
ogabrielluiz Oct 18, 2025
121d940
feat: centralize graph mutations with async event system
ogabrielluiz Oct 20, 2025
0ab3248
refactor: remove deprecated debugging utilities
ogabrielluiz Oct 20, 2025
b2063cf
feat: add pure observer pattern event recorder
ogabrielluiz Oct 20, 2025
52c711c
docs: add comprehensive event debugging notebook
ogabrielluiz Oct 20, 2025
4246754
refactor: enhance event debugging notebook with structured outputs
ogabrielluiz Oct 20, 2025
6e2f430
chore: update ruff exclusion list to include Jupyter notebook examples
ogabrielluiz Oct 20, 2025
a2c2e65
refactor: replace direct access to _run_queue with getter method
ogabrielluiz Oct 20, 2025
44a3b4b
chore: update ruff exclusion list and add new init file
ogabrielluiz Oct 20, 2025
a0f4e56
refactor: remove marimo notebook
ogabrielluiz Oct 20, 2025
b948f1b
refactor: remove obsolete test files and debugging utilities
ogabrielluiz Oct 20, 2025
866ea49
feat: add event saving and loading functionality to EventBasedRecording
ogabrielluiz Oct 20, 2025
9d73199
update
HimavarshaVS Nov 10, 2025
25aa1f2
add md files
HimavarshaVS Nov 10, 2025
b93eeca
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 10, 2025
0a7c61c
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Nov 10, 2025
3294dfd
Merge branch main into graph-debugger
ogabrielluiz Nov 26, 2025
66aa46e
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 26, 2025
d136c33
chore: remove PR description files from repo root
ogabrielluiz Nov 26, 2025
dbf8d8b
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 26, 2025
46e138a
feat: update save and load methods to use JSON serialization for even…
ogabrielluiz Nov 26, 2025
8d117f7
fix: update event list types to use GraphMutationEvent for better typ…
ogabrielluiz Nov 26, 2025
a9a0195
feat: convert item_output and update_dependency methods to async for …
ogabrielluiz Nov 26, 2025
18739ff
feat: add tests for event-based graph recorder and mutation event system
ogabrielluiz Nov 26, 2025
6904ea2
fix: remove marimo dependency from development requirements
ogabrielluiz Nov 26, 2025
7584b3c
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 26, 2025
892c742
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Nov 26, 2025
e879125
export debug classes in dunder init
ogabrielluiz Nov 26, 2025
103cec3
feat: refactor summary and timeline display methods to return strings…
ogabrielluiz Nov 26, 2025
3106ac6
feat: make remove_from_predecessors and remove_vertex_from_runnables …
ogabrielluiz Nov 26, 2025
c128c6f
Merge branch 'main' into graph-debugger
ogabrielluiz Dec 18, 2025
2268e97
[autofix.ci] apply automated fixes
autofix-ci[bot] Dec 18, 2025
5d75fe5
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Dec 18, 2025
f0cf5f5
[autofix.ci] apply automated fixes (attempt 3/3)
autofix-ci[bot] Dec 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions PR_DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# Graph Execution Debugging and Event System

## Overview

This PR introduces a comprehensive event-based debugging system for Langflow graph execution, enabling detailed tracking and analysis of graph state mutations during execution. The implementation uses a pure observer pattern that provides zero overhead when not in use, making it production-safe.

## Key Features

### 🎯 Graph Mutation Event System

- **Event Infrastructure**: New `GraphMutationEvent` system that tracks all graph state changes with before/after snapshots
- **Observer Pattern**: Pure observer pattern implementation with `register_observer()` and `unregister_observer()` methods
- **Zero Overhead**: Fast path when no observers are registered, ensuring no performance impact in production
- **Serializable Events**: Events can be serialized to dictionaries for replay and storage

### 📊 Event-Based Recording

- **EventRecorder**: Observer that captures all graph mutations during execution
- **EventBasedRecording**: Rich recording object with analysis methods:
- `get_events_by_type()` - Filter events by type
- `get_events_for_vertex()` - Get all events for a specific vertex
- `get_queue_evolution()` - Track how the execution queue changes over time
- `get_dependency_changes()` - Monitor dependency modifications
- `show_summary()`, `show_timeline()`, `show_events_for_component()` - Visualization methods
- **Save/Load**: Recordings can be saved to and loaded from files for later analysis

### 🔧 Graph Execution Improvements

#### Loop Component Enhancements
- **Synchronized Dependencies**: Loop component now properly updates both `run_predecessors` and `run_map` to keep dependency structures synchronized
- **State Reset**: New `reset_loop_state()` method for clean loop state management between executions
- **Better Documentation**: Added critical comments explaining the relationship between dependency structures

#### Graph Manager Refactoring
- **Async Methods**: Made `remove_from_predecessors()` and `remove_vertex_from_runnables()` async for consistency
- **Sync Variants**: Added `mark_branch_sync()` for synchronous contexts (used by custom components)
- **Centralized Mutations**: All graph mutations now go through centralized methods that emit events

### 🧪 Testing Infrastructure

#### Execution Path Validation
- **Path Equivalence Testing**: New test suite that validates both `async_start()` and `arun()` execution paths produce identical results
- **Test Data Flows**: Uses test flows that don't require API keys for reliable CI testing
- **Comprehensive Tracing**: `ExecutionTracer` captures complete execution traces for comparison

#### Event System Tests
- **Mutation Event Tests**: Tests for queue operations, dependency updates, and event emission
- **Event Recorder Tests**: Tests for event capture, queue evolution tracking, and recording analysis
- **Graph Mutation Tests**: Tests ensuring both dependency structures stay synchronized

### 🛠️ Component Validation Improvements

- **TYPE_CHECKING Block Support**: Component validation now properly handles `TYPE_CHECKING` blocks, extracting imports needed for `get_type_hints()` to work correctly
- **Better Error Handling**: Improved error handling for components defined in notebooks or REPL environments
- **Source Code Extraction**: More robust source code extraction with graceful fallbacks

## Technical Details

### Event Types Tracked

- `queue_extended` - When vertices are added to the execution queue
- `queue_dequeued` - When vertices are removed from the queue
- `dependency_added` - When dynamic dependencies are added
- `vertex_marked` - When vertex states change (ACTIVE/INACTIVE)

### Architecture

```
Graph
├── register_observer() / unregister_observer()
├── _emit_event() - Emits events to all observers
└── All mutations → emit before/after events
├── extend_run_queue()
├── add_dynamic_dependency()
├── mark_branch_sync()
└── remove_from_predecessors()
```
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Specify a language on this fence to satisfy markdownlint.

markdownlint (MD040) is flagging this block because the fence lacks a language hint. Adding something like text keeps the ASCII diagram readable and unblocks the lint job.

-```
+```text
 Graph
   ├── register_observer() / unregister_observer()
   ├── _emit_event() - Emits events to all observers
   └── All mutations → emit before/after events
        ├── extend_run_queue()
        ├── add_dynamic_dependency()
        ├── mark_branch_sync()
        └── remove_from_predecessors()

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.18.1)</summary>

68-68: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

In PR_DESCRIPTION.md around lines 66 to 77, the fenced code block containing the
ASCII architecture diagram lacks a language hint which triggers markdownlint
MD040; update the opening fence to include a language (for example change totext) so the block becomes a ```text fenced block, keep the diagram content
unchanged, save the file and re-run the linter to confirm the warning is
resolved.


</details>

<!-- fingerprinting:phantom:medusa:sabertoothed -->

<!-- This is an auto-generated comment by CodeRabbit -->


### Usage Example

```python
from lfx.graph.graph.base import Graph
from lfx.debug.event_recorder import record_graph_with_events

# Record graph execution
graph = Graph.from_payload(flow_data)
recording = await record_graph_with_events(graph, "My Flow")

# Analyze the recording
recording.show_summary()
recording.show_timeline()

# Get specific insights
queue_evolution = recording.get_queue_evolution()
dependency_changes = recording.get_dependency_changes()

# Save for later analysis
recording.save("flow_recording.pkl")
```

## Files Changed

### New Files
- `src/lfx/src/lfx/debug/__init__.py` - Debug module initialization
- `src/lfx/src/lfx/debug/events.py` - GraphMutationEvent and observer types
- `src/lfx/src/lfx/debug/event_recorder.py` - EventRecorder and EventBasedRecording
- `src/backend/tests/unit/graph/test_execution_path_validation.py` - Execution path equivalence tests
- `src/backend/tests/unit/graph/test_execution_path_equivalence.py` - Execution tracing utilities
- `src/backend/tests/unit/graph/test_event_recorder.py` - Event recorder tests
- `src/backend/tests/unit/graph/test_graph_mutation_events.py` - Mutation event tests

### Modified Files
- `src/lfx/src/lfx/graph/graph/base.py` - Added observer pattern, event emission
- `src/lfx/src/lfx/graph/graph/runnable_vertices_manager.py` - Made methods async
- `src/lfx/src/lfx/components/logic/loop.py` - Improved dependency synchronization
- `src/lfx/src/lfx/custom/custom_component/component.py` - Better error handling
- `src/lfx/src/lfx/custom/custom_component/custom_component.py` - Use mark_branch_sync
- `src/lfx/src/lfx/custom/validate.py` - TYPE_CHECKING block support
- `pyproject.toml` - Added marimo dependency for debugging notebooks

## Benefits

1. **Debugging**: Comprehensive visibility into graph execution state changes
2. **Testing**: Better test coverage with execution path validation
3. **Reliability**: Synchronized dependency structures prevent bugs
4. **Performance**: Zero overhead when debugging is not active
5. **Extensibility**: Easy to add new event types and observers

## Testing

- ✅ All existing tests pass
- ✅ New execution path validation tests pass
- ✅ Event system tests pass
- ✅ Loop component tests pass with improved dependency handling

## Breaking Changes

None - This is a purely additive change. The event system is opt-in and has zero overhead when not used.

## Future Work

- [ ] Add more event types (vertex execution start/end, memory updates, etc.)
- [ ] Create visualization tools for event recordings
- [ ] Add event filtering and querying capabilities
- [ ] Integrate with Langflow UI for real-time debugging

44 changes: 44 additions & 0 deletions PR_DESCRIPTION_SHORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Graph Execution Debugging and Event System

## Summary

Introduces a comprehensive event-based debugging system for Langflow graph execution with zero overhead when not in use. Uses a pure observer pattern to track all graph state mutations during execution.

## Key Changes

### 🎯 Event System
- New `GraphMutationEvent` system tracking all graph state changes
- Observer pattern with `register_observer()` / `unregister_observer()`
- Zero overhead fast path when no observers registered
- Serializable events for replay and analysis

### 📊 Event Recording
- `EventRecorder` captures all graph mutations
- `EventBasedRecording` with analysis methods (queue evolution, dependency changes, etc.)
- Save/load recordings for later analysis

### 🔧 Graph Improvements
- **Loop Component**: Synchronized `run_predecessors` and `run_map` dependencies
- **Graph Manager**: Made `remove_from_predecessors()` async, added `mark_branch_sync()` for sync contexts
- **Component Validation**: Better `TYPE_CHECKING` block handling

### 🧪 Testing
- Execution path validation tests (`async_start()` vs `arun()` equivalence)
- Event system tests
- Comprehensive test coverage

## Usage

```python
from lfx.debug.event_recorder import record_graph_with_events

recording = await record_graph_with_events(graph, "My Flow")
recording.show_summary()
recording.get_queue_evolution()
recording.save("recording.pkl")
```

## Breaking Changes

None - purely additive, opt-in feature.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ dev = [
"pytest-timeout>=2.3.1",
"pyyaml>=6.0.2",
"pyleak>=0.1.14",
"marimo>=0.17.0",
]

[tool.uv.sources]
Expand Down
Loading
Loading