riverpod_devtools_tracker 1.0.7
riverpod_devtools_tracker: ^1.0.7 copied to clipboard
Track Riverpod state changes with detailed call stacks. Debug easily by seeing exactly where state changes originated in your code.
Riverpod DevTools Tracker #
![]()
A powerful Flutter package that automatically tracks Riverpod state changes with detailed call stack information, helping you debug by showing exactly where state changes originated in your code.
繁體中文 | English
Table of Contents #
- Features
- Installation
- Quick Start
- How to Use DevTools Extension
- Configuration
- Console Output
- DevTools Extension Features
- Troubleshooting
- Requirements
Features #
- 🔍 Automatic State Tracking - No manual tracking code needed
- 📍 Code Location Detection - Shows exactly where state changes originated
- 📜 Call Chain Visualization - View the complete call stack
- 🎨 Beautiful DevTools Extension - GitHub-style dark theme UI
- 🔄 Visual Diff Highlighting - GitHub-style diff view for state changes
- 💾 Event Persistence - Optionally persist events to local storage for cross-session debugging
- ⚡ Zero Configuration - Just add the observer and you're done
- 🔧 Highly Configurable - Customize what to track and how
- 🎯 Selective Provider Tracking - Whitelist/blacklist specific providers or use custom filters
- ⚡ Optimized Performance - Skip unchanged values and efficient value serialization
Installation #
Step 1: Add the Package #
Add riverpod_devtools_tracker to your pubspec.yaml:
dependencies:
flutter_riverpod: ^3.1.0 # Required
riverpod_devtools_tracker: ^1.0.2
Step 2: Install Dependencies #
Run the following command in your terminal:
flutter pub get
This package includes two components:
- Core Tracking:
RiverpodDevToolsObserverfor monitoring and recording state changes - DevTools Extension: Visual interface that's automatically discovered by Flutter DevTools
Note: The DevTools extension is automatically included in the package's
extension/devtools/directory. No additional installation or configuration needed.
Quick Start #
Step 1: Import the Package #
In your main.dart file, import the package:
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_devtools_tracker/riverpod_devtools_tracker.dart';
Step 2: Add the Observer #
Add RiverpodDevToolsObserver to your ProviderScope's observers list:
void main() {
runApp(
ProviderScope(
observers: [
RiverpodDevToolsObserver(
config: TrackerConfig.forPackage('your_app_name'), // Replace with your package name
),
],
child: const MyApp(),
),
);
}
Important: Replace
'your_app_name'with your actual package name frompubspec.yaml(thename:field value)
Step 3: Run Your App #
flutter run
Done! Now when you run your app and open DevTools, you'll see the "Riverpod State Inspector" tab.
How to Use DevTools Extension #
Step 1: Open DevTools #
After running your app, you can open Flutter DevTools in several ways:
Method A - From VS Code
- Run your app (press F5 or click Run)
- Click the "Dart DevTools" button in the debug toolbar
- DevTools will automatically open in your browser
Method B - From Android Studio / IntelliJ
- Run your app
- Click "Open DevTools" in the Run panel
- DevTools will automatically open in your browser
Method C - From Command Line
- Run your app:
flutter run - The terminal will display a DevTools URL:
The Flutter DevTools debugger and profiler is available at: http://127.0.0.1:9100?uri=... - Click or copy the URL to open it in your browser
Step 2: Find the Riverpod State Inspector Tab #
Once DevTools is open:
- Look for the "Riverpod State Inspector" tab in the top menu bar
- Click the tab to open the extension interface
![]()
Tip: If you don't see this tab, make sure:
- The package is properly installed and you've run
flutter pub getRiverpodDevToolsObserveris added to yourProviderScope- Your app has been restarted
Step 3: Understand the Interface Layout #
The DevTools extension uses a two-panel layout:
Left Panel - Provider List (400px width)
- Displays all state changes in chronological order
- Each entry shows:
- Provider name and type
- Timestamp
- Change type (add/update/dispose/error)
- Code location where the change was triggered
- Click any entry to view details
Right Panel - State Details
- Shows detailed information about the selected state change:
- Before/after value comparison
- Complete call chain with file locations
- Function names in the call stack
- Clickable file paths for code navigation
![]()
Step 4: Track and Debug State Changes #
As you interact with your app:
- Real-time Monitoring: Watch the left panel update in real-time as providers change
- Locate Issues: Click any change record to see the exact code location that triggered it
- Trace Execution: Use the call chain to understand the execution path
- Compare Values: Compare before/after values to debug state issues
Example Usage #
Let's say you have a counter provider:
final counterProvider = StateProvider<int>((ref) => 0);
// In your widget
ElevatedButton(
onPressed: () => ref.read(counterProvider.notifier).state++,
child: const Text('Increment'),
)
When you click the button:
- The DevTools extension immediately shows a new entry:
UPDATE: counterProvider - The location shows exactly where the button was pressed (e.g.,
widgets/counter_button.dart:42) - Click the entry to see the value changed from
0to1 - The call chain shows the complete path from button press to state update
Configuration #
Basic Configuration #
RiverpodDevToolsObserver(
config: TrackerConfig.forPackage(
'your_app_name',
enableConsoleOutput: true, // Print to console
prettyConsoleOutput: true, // Use formatted output
maxCallChainDepth: 10, // Max stack trace depth
maxValueLength: 200, // Max value string length
),
)
Event Persistence Configuration #
Enable event persistence to preserve state change history across DevTools reconnections:
RiverpodDevToolsObserver(
config: TrackerConfig.forPackage(
'your_app_name',
enablePersistence: true, // Enable event persistence
clearOnStart: true, // Clear old events on app start (default: true)
maxPersistedEvents: 1000, // Max events to load from storage
),
)
| Option | Type | Default | Description |
|---|---|---|---|
enablePersistence |
bool |
false |
Enable persistent storage of events |
clearOnStart |
bool |
true |
Clear stored events when app starts |
maxPersistedEvents |
int |
1000 |
Maximum events to load from storage |
Use Cases:
clearOnStart: true(default) - Only see events from current session, cleaner debuggingclearOnStart: false- Preserve events across app restarts for historical analysis
Advanced Configuration #
RiverpodDevToolsObserver(
config: TrackerConfig(
enabled: true,
packagePrefixes: [
'package:your_app/',
'package:your_common_lib/',
],
enableConsoleOutput: true,
prettyConsoleOutput: true,
maxCallChainDepth: 10,
maxValueLength: 200,
ignoredPackagePrefixes: [
'package:flutter/',
'package:flutter_riverpod/',
'package:riverpod/',
'dart:',
],
ignoredFilePatterns: [
'generated.dart',
'.g.dart',
],
// Memory management settings
enablePeriodicCleanup: true, // Enable automatic cleanup
cleanupInterval: const Duration(seconds: 30), // Cleanup frequency
stackExpirationDuration: const Duration(seconds: 60), // How long to keep stacks
maxStackCacheSize: 100, // Maximum cached stacks
),
)
Selective Provider Tracking #
You can filter which providers to track using whitelists, blacklists, or custom filters.
Pass provider references directly for type-safety and IDE auto-completion:
// Define your providers
final userProvider = StateProvider<User?>((ref) => null);
final cartProvider = StateNotifierProvider<CartNotifier, Cart>(...);
final authProvider = StateProvider<bool>((ref) => false);
final debugProvider = Provider<String>((ref) => 'debug');
final tempProvider = Provider<int>((ref) => 0);
RiverpodDevToolsObserver(
config: TrackerConfig.forPackage(
'your_app',
// Whitelist: Only track these providers (takes precedence over blacklist)
trackedProviders: [userProvider, cartProvider, authProvider],
// Blacklist: Ignore these providers (only works when whitelist is empty)
ignoredProviders: [debugProvider, tempProvider],
// Custom filter: Advanced filtering based on name and type
providerFilter: (name, type) {
// Only track StateNotifierProvider and StateProvider
return type.contains('State');
},
),
)
How filtering works:
- If
trackedProvidersis not empty, only providers in the whitelist are tracked (blacklist is ignored) - If
trackedProvidersis empty, providers inignoredProvidersare filtered out - After whitelist/blacklist filtering,
providerFilterfunction is applied if provided - The
skipUnchangedValuesoption (enabled by default) prevents tracking updates where the value hasn't actually changed
Memory Management #
The tracker automatically manages memory to prevent leaks during long debugging sessions:
- Periodic Cleanup: Automatically removes expired stack traces from memory
- Configurable Retention: Control how long stack traces are kept
- Size Limits: Hard limit on the number of cached stack traces
Default settings work well for most apps, but you can customize them:
TrackerConfig.forPackage(
'your_app',
enablePeriodicCleanup: true, // Enable/disable automatic cleanup
cleanupInterval: Duration(seconds: 30), // How often to run cleanup
stackExpirationDuration: Duration(minutes: 2), // Stack trace lifetime
maxStackCacheSize: 200, // Max number of stacks to cache
)
When to Adjust:
- High-traffic apps: Increase
cleanupIntervalto reduce CPU usage - Long debugging sessions: Increase
stackExpirationDurationto keep more history - Memory-constrained devices: Decrease
maxStackCacheSizeto reduce memory footprint
Memory Usage Estimation:
The tracker's memory footprint depends on your configuration:
- Default config (
maxStackCacheSize: 100): ~50-100 KB- Each stack trace entry: ~500-1000 bytes
- 100 entries ≈ 50-100 KB
- High-traffic config (
maxStackCacheSize: 200): ~100-200 KB - Memory-constrained config (
maxStackCacheSize: 50): ~25-50 KB
The enablePeriodicCleanup: true (default) ensures memory usage stays within these bounds by removing expired entries every 30 seconds.
Resource Cleanup:
If you're manually managing observer lifecycle, call dispose() when done:
final observer = RiverpodDevToolsObserver(
config: TrackerConfig.forPackage('your_app'),
);
// ... use observer ...
// When done (e.g., in a test teardown)
observer.dispose();
Performance Metrics Collection #
You can enable performance metrics collection to analyze the overhead of the tracker itself:
RiverpodDevToolsObserver(
config: TrackerConfig.forPackage(
'your_app_name',
collectPerformanceMetrics: true, // Enable performance tracking
),
)
When enabled, the tracker will collect detailed metrics including:
- Stack trace parsing time: Time spent analyzing call stacks
- Value serialization time: Time spent converting provider values
- Total tracking time: Overall time for each tracking operation
- Call chain depth: Number of stack frames captured
- Value size: Size of serialized values
These metrics are displayed in the Performance tab of the DevTools extension, showing:
- Overall statistics (total operations, total time, average time)
- Per-provider statistics (update count, average/min/max times)
- Breakdown of parsing vs serialization time
Note: Performance metrics collection adds a small overhead. It's recommended to disable it in production builds.
Console Output #
When enableConsoleOutput is true, you'll see formatted output like this:
╔══════════════════════════════════════════════════════
║ 🔄 UPDATE: counterProvider
║ ──────────────────────────────────────────────────────
║ 📍 Location: widgets/counter_button.dart:42 in _onPressed
║ ──────────────────────────────────────────────────────
║ 📜 Call chain:
║ → widgets/counter_button.dart:42 in _onPressed
║ providers/counter_provider.dart:15 in increment
║ ──────────────────────────────────────────────────────
║ Before: 0
║ After: 1
╚══════════════════════════════════════════════════════
DevTools Extension Features #
The extension provides a comprehensive debugging interface with three main tabs:
State Inspector Tab #
- Provider List - Real-time view of all state changes with timestamps
- Timeline View - Visual timeline showing events over time with zoom and pan controls
- Location Info - Shows the exact file and line number where each change originated
- Value Comparison - Before/after values displayed in three view modes:
- Tree View - Hierarchical JSON tree view with syntax highlighting
- Diff View - GitHub-style diff highlighting showing exactly what changed
- Text View - Plain text view with expand/collapse for long values
- Call Chain - Complete call stack for tracing the execution path
- Search & Filter - Quickly find specific providers or changes
- Event Export - Export events to JSON or CSV format for offline analysis and sharing
- Event History - When persistence is enabled, automatically loads previous events when DevTools connects
Performance Tab #
- Overall Statistics - Total operations, total time, and average time across all providers
- Per-Provider Metrics - Detailed performance breakdown for each provider:
- Update count and frequency
- Average, minimum, and maximum tracking time
- Stack trace parsing time
- Value serialization time
- Performance Indicators - Visual feedback (Excellent/Good/Fair/Slow) based on tracking overhead
- Expandable Details - Click on any provider to see comprehensive metrics
Visual Diff Highlighting
The Diff View provides GitHub-style visual diff for state changes:
Features:
- Color-Coded Changes - Green for additions, red for removals, yellow for modifications
- Inline Diff - Shows changes line-by-line with +/- indicators
- Tree Diff - Expandable tree view showing nested changes
- Smart Comparison - Deep object and array comparison
- Copy Support - Double-tap to copy values or paths
How to Use:
- Click any state change in the Provider List
- In the State Details panel, click the view mode toggle button
- Select "Diff View" to see highlighted changes
- For complex objects, switch between Inline and Tree modes
Graph View Tab #
- Provider Dependency Graph - Interactive visualization of provider relationships
- Temporal Dependency Detection - Automatically infers dependencies based on update timing
- Interactive Nodes - Click on providers to see their connections
- Connection Strength - Visual indication of how frequently providers update together
- Color-Coded Nodes - Different colors for different provider types (NotifierProvider, FutureProvider, StreamProvider, etc.)
- Type Statistics - Real-time count of each provider type with color indicators in the toolbar
- Zoom & Pan - Full interactive viewer for exploring complex graphs
- Network Statistics - Real-time stats showing provider counts by type and total connections
Common Features #
- GitHub-style Dark Theme - Easy on the eyes during long debugging sessions
- Tab Navigation - Seamlessly switch between State Inspector, Performance, and Graph views
Provider State Filtering #
You can quickly filter specific Provider state changes using the search box:
![]()
You can also focus on a specific Provider for in-depth analysis:
![]()
Timeline View #
The extension includes a powerful timeline visualization to help you understand when and how your providers change over time.
How to Access:
- Click the Timeline icon in the view mode selector (next to the language switcher)
- Switch between List View (default) and Timeline View as needed
Timeline Features:
- Visual Timeline - See all state changes plotted on a time axis
- Color-Coded Events:
- 🟢 Green: Provider added (ADD)
- 🔵 Purple: Provider updated (UPDATE)
- 🟠 Orange: Provider disposed (DISPOSE)
- 🔴 Red: Provider error (ERROR)
- Provider Lanes - Each provider gets its own horizontal lane for easy tracking
- Interactive Controls:
- 🔍 Zoom In/Out - Magnify specific time periods (properly affects timeline scale)
- ↔️ Pan - Drag horizontally to navigate through time
- 🔄 Reset - Return to default view
- Event Selection - Click any event to view details in the side panel
- Hover Interactions - Move your mouse over event points to:
- 🎯 See a connecting line from the event to its provider label
- 💡 Highlight and enlarge the provider name (turns indigo blue with larger font)
- ✨ Display a glow effect around the event point
- Time Labels - Precise timestamps shown below the timeline
Use Cases:
- 📊 Identify Patterns - Spot high-frequency updates or unusual update sequences
- ⏱️ Performance Analysis - See which providers update most frequently
- 🐛 Debug Timing Issues - Understand the temporal relationship between state changes
- 📈 Visualize State Flow - Track how state propagates through your application
Tips:
- Use zoom to focus on a specific time window
- Hover over event points to quickly identify which provider they belong to
- Look for clusters of events that might indicate performance issues
- Different provider lanes make it easy to track individual provider behavior
- Combine with filters to focus on specific providers or change types
- The timeline shows the top 10 most active providers when many providers exist
Using the Graph View #
The Graph View helps you understand provider relationships in your application:
- Switch to Graph Tab: Click the "Graph" tab in the toolbar
- Interact with Your App: As you use your app, the graph will populate with providers
- View Type Statistics:
- The toolbar shows a count for each provider type with its corresponding color
- Quickly see the distribution of provider types in your app (e.g., "Notifier: 3", "Future: 2", "Stream: 1")
- Each type chip uses the same color as its nodes in the graph
- Explore Relationships:
- Providers that update close together in time (within 100ms) are shown as connected
- Click on a node to highlight its connections
- Stronger connections (more frequent co-updates) have thicker lines
- Understand the Colors:
- 🔴 Red: NotifierProvider, AsyncNotifierProvider, StreamNotifierProvider
- 🟣 Purple: FutureProvider
- 🟢 Green: StreamProvider
- 🟠 Orange: Provider (functional providers)
- 🔵 Light Blue: StateProvider
- 🔷 Lighter Blue: StateNotifierProvider
- 🟪 Light Purple: ChangeNotifierProvider
- ⚪ Gray: Unknown/Other provider types
- Reset View: Use the zoom reset button to return to the default view
- Clear Network: Click the clear button to start fresh
Note: The graph shows inferred dependencies based on temporal proximity of updates, not the actual Riverpod dependency graph (which is not accessible through the public API).
Tips for Using the Extension #
- Finding State Bugs: Look at the call chain to understand why a state changed unexpectedly
- Performance Debugging: Check if providers are updating too frequently
- Understanding Architecture: Use the Graph View to see how providers interact
- Code Navigation: Click on file paths in the call chain to jump to the code (if your IDE supports it)
- Filtering: Use the
packagePrefixesconfig to focus only on your app's code and filter out framework noise
Event Export #
The DevTools extension supports exporting tracked events for offline analysis and sharing with team members.
How to Export:
- Click the Download icon in the top toolbar (next to the language switcher)
- Choose your preferred format:
- JSON Format - Complete event data with metadata, perfect for programmatic analysis
- CSV Format - Timeline format for spreadsheet analysis in Excel, Google Sheets, etc.
- The file will be automatically downloaded with a timestamp in the filename
JSON Export Format:
{
"exportedAt": "2024-01-15T10:30:00.000Z",
"totalEvents": 42,
"events": [
{
"id": "1234567890",
"timestamp": "2024-01-15T10:29:45.123Z",
"changeType": "UPDATE",
"providerName": "counterProvider",
"providerType": "StateProvider<int>",
"previousValue": 0,
"currentValue": 1,
"location": "lib/screens/home_screen.dart:45",
"file": "lib/screens/home_screen.dart",
"line": 45,
"function": "_incrementCounter",
"callChain": [
{
"location": "lib/screens/home_screen.dart:45",
"file": "lib/screens/home_screen.dart",
"line": 45,
"function": "_incrementCounter"
},
{
"location": "lib/widgets/counter_button.dart:23",
"file": "lib/widgets/counter_button.dart",
"line": 23,
"function": "_onPressed"
}
]
}
]
}
CSV Export Format:
Timestamp,Change Type,Provider,Value,Location
2024-01-15T10:29:45.123Z,UPDATE,counterProvider,1,lib/screens/home_screen.dart:45
Use Cases:
- 📊 Offline Analysis - Export events and analyze them in your preferred tools
- 🤝 Team Collaboration - Share debugging sessions with teammates
- 📝 Bug Reports - Attach event logs to bug reports for better context
- 📈 Performance Analysis - Import CSV into spreadsheet tools for data visualization
Troubleshooting #
DevTools Extension Not Showing #
If you don't see the "Riverpod State Inspector" tab in DevTools:
- Make sure the observer is added: Check that
RiverpodDevToolsObserveris in yourProviderScope's observers list - Rebuild your app: Stop and restart your app after adding the package
- Check DevTools version: Make sure you're using a recent version of DevTools
- Verify the extension is built: The extension should be in
extension/devtools/directory
No State Changes Appearing #
If the extension is visible but no state changes show up:
- Check packagePrefixes: Make sure your app's package name is included in the config:
TrackerConfig.forPackage('your_actual_package_name') - Verify providers are actually changing: Try a simple test like a counter to confirm tracking works
- Check console output: Enable
enableConsoleOutput: trueto see if changes are being tracked
Call Chain Shows No Location #
If you see state changes but no file locations:
- Package name mismatch: Your
packagePrefixesmight not match your actual package structure - All locations filtered: Your
ignoredFilePatternsmight be too aggressive - Provider is auto-computed: Some providers update automatically based on dependencies - these won't have a specific trigger location
Performance Issues #
If the tracker is slowing down your app:
- Disable console output: Set
enableConsoleOutput: falsefor better performance - Reduce call chain depth: Lower
maxCallChainDepthto 5 or less - Add more ignored patterns: Filter out high-frequency providers you don't need to track
- Disable in production: Only use the tracker in debug mode:
observers: [ if (kDebugMode) RiverpodDevToolsObserver(...) ]
Best Practices #
For Production Use #
We recommend disabling the tracker in production builds for optimal performance:
import 'package:flutter/foundation.dart';
void main() {
runApp(
ProviderScope(
observers: [
// Only enable tracking in debug mode
if (kDebugMode)
RiverpodDevToolsObserver(
config: TrackerConfig.forPackage('your_app'),
),
],
child: const MyApp(),
),
);
}
Performance Optimization #
If you experience performance issues during development:
- Disable console output: Set
enableConsoleOutput: falsefor better performance - Reduce call chain depth: Lower
maxCallChainDepthto 5-8 for faster tracking - Filter aggressively: Add more patterns to
ignoredFilePatternsto reduce noise - Target specific providers: Use
packagePrefixesto focus only on your app's code
RiverpodDevToolsObserver(
config: TrackerConfig.forPackage(
'your_app',
enableConsoleOutput: false, // Better performance
maxCallChainDepth: 5, // Faster tracking
ignoredFilePatterns: ['.g.dart', '.freezed.dart'], // Less noise
),
)
Advanced Usage #
Tracking Multiple Packages #
If your app uses multiple custom packages:
RiverpodDevToolsObserver(
config: TrackerConfig.forPackage(
'my_app',
additionalPackages: [
'package:my_common/',
'package:my_features/',
],
),
)
Selective Provider Tracking Use Cases #
Use Case 1: Debug Specific Feature
When debugging a specific feature, track only related providers:
// Assume you have defined these providers
final cartProvider = StateNotifierProvider<CartNotifier, Cart>(...);
final cartItemsProvider = Provider<List<CartItem>>(...);
final cartTotalProvider = Provider<double>(...);
final checkoutProvider = StateNotifierProvider<CheckoutNotifier, CheckoutState>(...);
RiverpodDevToolsObserver(
config: TrackerConfig.forPackage(
'my_app',
// Only track providers related to shopping cart
trackedProviders: [
cartProvider,
cartItemsProvider,
cartTotalProvider,
checkoutProvider,
],
),
)
Use Case 2: Exclude Noisy Providers
Filter out high-frequency or debug-only providers:
// Assume you have defined these providers
final mousePositionProvider = StateProvider<Offset>(...);
final timerProvider = StreamProvider<DateTime>(...);
final debugLogProvider = Provider<String>(...);
RiverpodDevToolsObserver(
config: TrackerConfig.forPackage(
'my_app',
// Ignore providers that update frequently and create noise
ignoredProviders: [
mousePositionProvider, // Updates on every mouse move
timerProvider, // Updates every second
debugLogProvider, // Debug-only provider
],
),
)
Use Case 3: Track by Provider Type
Focus on specific types of providers:
RiverpodDevToolsObserver(
config: TrackerConfig.forPackage(
'my_app',
// Only track state-holding providers, ignore computed ones
providerFilter: (name, type) {
return type.contains('StateProvider') ||
type.contains('StateNotifierProvider') ||
type.contains('NotifierProvider');
},
),
)
Use Case 4: Combined Filtering
Use multiple filtering strategies together:
// Assume you have defined these providers
final authProvider = StateProvider<AuthState>(...);
final userProvider = StateProvider<User?>(...);
final sessionProvider = StateProvider<Session?>(...);
final permissionsProvider = Provider<Permissions>(...);
final tokenRefreshProvider = StreamProvider<String>(...);
RiverpodDevToolsObserver(
config: TrackerConfig.forPackage(
'my_app',
// Track only authentication and user-related providers
trackedProviders: [
authProvider,
userProvider,
sessionProvider,
permissionsProvider,
],
// But exclude the token refresh provider (too noisy)
ignoredProviders: [
tokenRefreshProvider,
],
// And apply custom filter for additional control
providerFilter: (name, type) {
// Skip any provider that ends with 'Cache'
return !name.endsWith('Cache');
},
),
)
Custom Filtering #
Create highly customized filtering rules:
RiverpodDevToolsObserver(
config: TrackerConfig(
packagePrefixes: ['package:my_app/'],
ignoredFilePatterns: [
'.g.dart', // Generated files
'.freezed.dart', // Freezed files
'_test.dart', // Test files
'/generated/', // Generated directories
],
ignoredPackagePrefixes: [
'package:flutter/',
'package:flutter_riverpod/',
'package:riverpod/',
'dart:',
'package:go_router/', // Add other packages to ignore
],
),
)
Stack Trace Parsing Cache #
The tracker includes an intelligent caching system for stack trace parsing that significantly improves performance, especially for frequently updated async providers.
How it works:
- Parsed stack traces are cached to avoid redundant parsing
- Uses LRU (Least Recently Used) eviction when cache reaches size limit
- Can reduce parsing time by 80-90% for repeated traces
- Enabled by default with sensible settings
Configuration:
RiverpodDevToolsObserver(
config: TrackerConfig.forPackage(
'your_app',
enableStackTraceCache: true, // Enable caching (default: true)
maxStackTraceCacheSize: 500, // Max cached entries (default: 500)
),
)
When to adjust settings:
- Large apps with many providers: Increase
maxStackTraceCacheSizeto 1000+ for better cache hit rates - Memory-constrained environments: Decrease to 100-200 to reduce memory usage
- Debugging cache issues: Temporarily disable with
enableStackTraceCache: false
Performance impact:
- Typical memory usage: ~100-500 bytes per cached entry
- Cache of 500 entries ≈ 50-250 KB memory
- 80-90% reduction in parsing time for frequently updated providers
Contributors #
Support #
- 📝 Report Issues
- 💬 Discussions
- ⭐ If you find this package useful, please consider giving it a star on GitHub!