Description
Goal
Introduce a Debugging Panel component in the Preswald frontend that displays the live app state, tracked variables, and error messages to assist developers in real-time debugging and iteration.
📌 Motivation
Preswald abstracts away much of the complexity in app state management and component interactions. However, when things go wrong (e.g. a workflow fails, a component isn't rendering, or variable values are unexpected), there's currently no visibility into the internal state of the app. This makes debugging opaque and time-consuming.
A built-in debugging panel will:
- Surface variables and their current values
- Show error messages and stack traces in context
- Display execution flow and component states
- Improve developer confidence and iteration speed
✅ Acceptance Criteria
- Add a toggleable Debug Panel (
DebugPanel.jsx
) in the frontend (floating bottom-right or sidebar) - Display:
- Tracked variables (e.g. from
Service.get_state()
) - Component hierarchy and props
- Error messages and stack traces (from WebSocket/API layer)
- Current DAG execution status (optional)
- Tracked variables (e.g. from
- Provide a
debug=True
flag inpreswald.toml
or environment variable to enable/disable panel - Capture and display exceptions in workflows, Python code, or frontend component resolution
- Ensure minimal performance impact when disabled
- Style for readability and collapsibility (e.g. Tailwind + accordion view)
🛠 Implementation Plan
1. Backend – Surface State and Errors
In preswald/service.py
, expose get_state_snapshot()
:
def get_state_snapshot(cls):
return {
"components": cls.get_instance().components,
"variables": cls.get_instance().variable_store,
"errors": cls.get_instance().error_log,
"execution_graph": cls.get_instance().workflow_graph.serialize(),
}
Update server_service.py
to stream state snapshots and errors over WebSocket via special __debug__
channel when debug=True
.
2. Frontend – Add Debug Panel UI
Create frontend/src/components/common/DebugPanel.jsx
:
import React, { useState, useEffect } from 'react';
import { Card } from '@/components/ui/card';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Button } from '@/components/ui/button';
const DebugPanel = ({ state }) => {
const [visible, setVisible] = useState(false);
return (
<div className="fixed bottom-4 right-4 z-50">
<Button onClick={() => setVisible(!visible)} className="mb-2">
{visible ? "Hide Debug" : "Show Debug"}
</Button>
{visible && (
<Card className="w-[400px] h-[500px] overflow-hidden shadow-lg border bg-white dark:bg-gray-900 text-sm">
<ScrollArea className="p-4 h-full">
<pre className="whitespace-pre-wrap">{JSON.stringify(state, null, 2)}</pre>
</ScrollArea>
</Card>
)}
</div>
);
};
export default DebugPanel;
Mount this component inside App.jsx
only if debugMode
is true
.
3. WebSocket Layer – Stream State Updates
Update websocket.js
to subscribe to __debug__
messages and store in global state. Example:
socket.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.channel === "__debug__") {
window.__DEBUG_STATE__ = msg.payload;
}
};
4. Toggle Debug Panel Based on Flag
Allow enabling via:
preswald.toml
:
[debug]
enabled = true
- Or ENV:
PRESWALD_DEBUG=true
Expose this flag from backend via branding/metadata payload (/api/config
).
📄 Example Output
{
"variables": {
"threshold": 0.75,
"selected_region": "Europe"
},
"components": [
{"id": "slider-abc123", "type": "slider", "label": "Threshold"},
{"id": "table-def456", "type": "table", "rows": 200}
],
"errors": [
{"timestamp": "2025-03-23T19:42Z", "message": "KeyError: 'value'"}
]
}
📚 Documentation Updates
- Add
docs/coreconcepts/debugging.mdx
- Mention in CLI/dev tools docs
- Add a config flag section in
preswald.toml
docs
🧪 Testing Plan
- Trigger runtime Python errors in workflows
- Confirm they surface in Debug Panel
- Add/modify variables and ensure they update live
- Confirm debug panel does not show in
debug=false
mode
🧩 Files Involved
preswald/service.py
preswald/server_service.py
frontend/src/components/common/DebugPanel.jsx
frontend/src/components/App.jsx
websocket.js
💡 Future Enhancements
- Interactive state editing in debug mode (like Redux DevTools)
- Toggle logs per component
- DAG viewer with live execution steps
- Attach profiler/trace mode