A Flutter package that tracks error provenance by capturing causal chains of events leading to errors. Includes a local dashboard for visualizing and analyzing error origins during development.
- Automatic Event Tracking: Captures user actions, navigation, async operations, and errors
- Causal Chain Analysis: Tracks which events caused which errors
- Local Dashboard: Visualize provenance data in a web-based dashboard (dev mode only)
- Session Comparison: Compare different app sessions to identify patterns
- Zero Production Impact: Automatically disabled in release builds
Add errord to your pubspec.yaml:
dependencies:
errord: ^0.1.0Then run:
flutter pub get-
Local Provenance Service: The dashboard requires a local service to be running. This service:
- Runs on
localhost:4040(dev only) - Stores provenance data locally in
~/.provenance/ - Can be started automatically using pub global command (like DevTools) or scripts
- Runs on
-
Development Mode Only: This package only operates in debug/profile builds. It automatically disables itself in release builds.
Import the package and initialize the provenance tracker:
import 'package:errord/errord.dart';
void main() {
// Initialize provenance tracking
ProvenanceTracker.initialize(
appVersion: '1.2.3',
enableLocalService: true, // Connect to local service (dev only)
);
runApp(MyApp());
}The tracker automatically captures many events, but you can also manually track custom events:
// Track a user action
ProvenanceTracker.trackUserAction(
widget: 'CheckoutButton',
action: 'tap',
context: {'screen': '/checkout'},
);
// Track navigation
ProvenanceTracker.trackNavigation(
from: '/home',
to: '/checkout',
);
// Track async operation start
final asyncId = ProvenanceTracker.trackAsyncStart(
scope: 'fetchOrder',
context: {'orderId': '12345'},
);
// Track async operation end
ProvenanceTracker.trackAsyncEnd(
asyncId: asyncId,
success: true,
);Errors are automatically captured when they occur. The tracker attaches the full causal chain:
try {
await processOrder();
} catch (e, stackTrace) {
// Error is automatically tracked with full provenance
ProvenanceTracker.trackError(
error: e,
stackTrace: stackTrace,
context: {'orderId': orderId},
);
rethrow;
}You can export provenance data as JSON:
// Export current session
final sessionData = await ProvenanceTracker.exportSession();
print(sessionData); // JSON string
// Export to file
await ProvenanceTracker.exportSessionToFile('/path/to/session.json');The dashboard provides a visual interface for inspecting provenance data. It runs locally and connects to the provenance service.
Option 1: Pub Global Command (Recommended - Like DevTools):
# Install as global command (first time only)
dart pub global activate --source path /path/to/errord
# Start the service
dart pub global run errord:provenance_service --dev
# Start the dashboard
dart pub global run errord:provenance_dashboard --devOption 2: Shell Scripts:
# Start service
./scripts/start-provenance-service.sh dev
# Start dashboard
./scripts/start-dashboard.sh dev- Service API:
http://127.0.0.1:4040 - Dashboard UI:
http://localhost:3000
View all captured provenance sessions:
- Filter by app version
- Filter by error presence
- Sort by time or error count
- Click to inspect a session
Visualize the causal chain of events:
- Vertical timeline showing all events
- Causality lines connecting related events
- Click any event to see details and parent/child events
- Filter by event type
- Search by event ID or context
Understand why errors occurred:
- Select any error from a session
- See the full causal chain leading to the error
- Unrelated events are dimmed for clarity
- View stack traces and error context
- See the root event that triggered the chain
Compare two sessions side-by-side:
- Select two sessions to compare
- See missing events in each session
- Identify divergent causal paths
- Compare async operation timing
- Highlight differences with color coding
Configure tracking behavior (dev mode only):
- Async scope tracking: Enable/disable async operation tracking
- Verbosity level: Control detail level of captured events
- Auto-export rules: Automatically export sessions matching criteria
Note: Configuration changes only affect future events. The dashboard never modifies app state or runtime behavior.
ProvenanceTracker.initialize(
appVersion: '1.2.3',
enableLocalService: true, // Connect to local service (default: false)
asyncScopeTracking: true, // Track async operations (default: true)
verbosity: VerbosityLevel.normal, // normal | minimal | verbose
autoExport: AutoExportRules(
onError: true, // Auto-export sessions with errors
maxSessions: 10, // Keep last N sessions
),
);Configuration can be updated through the dashboard (dev mode only). Changes take effect on the next app connection to the service.
Each event captured by the tracker:
{
"id": "evt_123",
"type": "user_action | navigation | async_start | async_end | error",
"timestamp": "2026-01-26T10:30:00Z",
"context": {
"route": "/checkout",
"widget": "PayButton",
"asyncScope": "fetchOrder"
},
"causedBy": ["evt_120", "evt_121"]
}A complete session of app usage:
{
"sessionId": "sess_abc",
"appVersion": "1.2.3",
"device": "android",
"startedAt": "2026-01-26T10:00:00Z",
"endedAt": "2026-01-26T10:30:00Z",
"events": [ ... ],
"errors": [ ... ]
}An error with its causal chain:
{
"errorId": "err_42",
"message": "Network timeout",
"stack": "...",
"rootEvent": "evt_120",
"causalChain": ["evt_120", "evt_121", "evt_130"]
}- Local Only: All data stays on your machine. No network requests outside localhost.
- Release Build Safety: The tracker automatically disables itself in release builds.
- No Production Data: The SDK refuses to send data in release builds.
- Explicit Dev Mode: Clear indicators show when tracking is active.
- Development Tool Only: This package is designed for development and debugging, not production use.
- Local Service Required: The dashboard requires the local provenance service to be running.
- Debug/Profile Builds Only: Tracking only works in debug and profile builds.
- Verify the local provenance service is running on
localhost:4040 - Check that your app is running in debug/profile mode
- Ensure
enableLocalService: trueis set in initialization
- Verify you're running in debug or profile mode (not release)
- Check that tracking is initialized before app startup
- Review verbosity settings - some events may be filtered
- Enable auto-export to limit session retention
- Disable async scope tracking if not needed
See LICENSE file for details.