Application: Empower Plant (empower_flutter)
Version: 9.14.0+1 (matches Sentry SDK version)
Purpose: Production-ready Flutter e-commerce app with comprehensive Sentry instrumentation demonstrating best practices for error monitoring, performance tracking, session replay, and user feedback.
Type: Full-featured plant shopping app + Sentry demo platform Platforms: iOS, Android, Web, macOS, Linux, Windows
- Current Branch:
feature/comprehensive-sentry-integration - Main Branch:
main - Latest Commit:
bf17e76- Refactor TTFD tracking to use SentryDisplayWidget strategically
- Secrets in
.env(git-ignored, based on.env.example) - Engineer ID in
lib/se_config.dartfor event separation - Sentry config: DSN, ORG, PROJECT, AUTH_TOKEN required
- Format:
package@version+build(e.g.,com.example.empower_flutter@9.14.0+1) - Version source:
pubspec.yaml - Must match Sentry SDK version for consistency
- Distribution set to build number (currently
'1')
lib/
├── main.dart # Entry point, home page, global setup
├── sentry_setup.dart # Comprehensive Sentry init (280+ lines)
├── se_config.dart # Engineer identifier
├── navbar_destination.dart # Navigation drawer + error triggers
├── product_list.dart # Home screen, catalog, demo triggers (750+ lines)
├── product_details.dart # Product detail view
├── cart.dart # Shopping cart
├── checkout.dart # Checkout flow with metrics/logging
└── models/
└── cart_state_model.dart # Provider-based cart state
assets/
├── images/ # Plant product images
├── config/ # Feature configuration JSONs
└── docs/ # Dummy documentation files
demo.sh # Unified build script for all platforms
| File | Lines | Purpose |
|---|---|---|
lib/main.dart |
~500 | App initialization, home page, navigation, TTFD setup |
lib/sentry_setup.dart |
280+ | Complete Sentry configuration, all features enabled |
lib/product_list.dart |
750+ | Product catalog, API fetching, error/perf triggers |
lib/checkout.dart |
~500 | Checkout flow, metrics, structured logging |
demo.sh |
~940 | Build automation, release management, symbol upload |
Flutter SDK: >= 3.22.0 < 4.0.0
Dart SDK: >= 3.5.0 < 4.0.0
# Sentry
sentry_flutter: ^9.14.0 # Main SDK
sentry_dio: ^9.14.0 # HTTP client integration
sentry_file: ^9.14.0 # File I/O tracking
sentry_logging: ^9.14.0 # Logging integration
# State Management & Utils
provider: ^6.1.5 # State management
flutter_dotenv: ^6.0.0 # Environment variables
dio: ^5.9.1 # HTTP client
logging: ^1.3.0 # Structured logging- Backend API:
https://flask.empower-plant.com/(products, checkout) - Sentry: Error monitoring, performance, session replay
- Sentry CLI: Optional for symbol upload and size analysis
SentryWidgetsFlutterBinding.ensureInitialized()- Set up bindingsdotenv.load()- Load environment variablesinitSentry()- Full Sentry initialization fromsentry_setup.dart- Global scope tags: app name, platform, OS, locale, screen size
// Sampling (100% for demo)
sampleRate: 1.0 # All errors captured
tracesSampleRate: 1.0 # All performance traces
profilesSampleRate: 1.0 # All profiling (iOS/macOS/Android)
// Session Replay (100% for demo)
replay.onErrorSampleRate: 1.0 # All error sessions
replay.sessionSampleRate: 1.0 # All normal sessions
// Performance Tracking
enableAutoPerformanceTracing: true # Automatic spans
enableTimeToFullDisplayTracing: true # TTFD/TTID tracking
enableUserInteractionTracing: true # Tap/swipe tracking
enableUserInteractionBreadcrumbs: true # User action breadcrumbs
// Attachments
attachStacktrace: true # Stack traces on all events
attachScreenshot: false # Disabled for demo
attachViewHierarchy: true # UI hierarchy
attachThreads: true # Thread info
// Crash Handling
enableNativeCrashHandling: true # Native crash capture
enableNdkScopeSync: true # Android NDK scope sync
reportSilentFlutterErrors: true # Report ErrorWidget errors
anrEnabled: true # Android ANR detection (5s)
anrTimeoutInterval: Duration(seconds: 5)
appHangTimeoutInterval: Duration(seconds: 2) # iOS/macOS hang detection
enableWatchdogTerminationTracking: true # iOS/macOS watchdog
// Logging & Metrics
enableLogs: true # Structured logs to Sentry
enableMetrics: true # Custom metrics support
maxBreadcrumbs: 100 # Breadcrumb limit
enableAutoNativeBreadcrumbs: true # Native breadcrumbs
// Privacy (Demo settings)
sendDefaultPii: true # Send PII for demo environmentbeforeSend Hook:
- Adds
setag from engineer config for per-developer separation - Sets fingerprint:
['{{ default }}', 'se:$se']
Session Replay Privacy Masking:
- Masks Text widgets containing BOTH a financial label AND dollar sign
- Financial labels:
items (,shipping & handling,total before tax,estimated tax,order total,subtotal - Ensures labels remain visible, only values with $ are masked
- Everything else in replays is visible
- SentryNavigatorObserver - Navigation tracking, automatic TTID
- SentryHttpClient - HTTP request tracing
- SentryDio - Dio HTTP client integration (
dio.addSentry()) - SentryFile - File I/O instrumentation (
.sentryTrace()) - LoggingIntegration - Captures
Logger()calls as breadcrumbs/events - Spotlight - Local debugging UI (enabled in
kDebugMode)
TTID (Time to Initial Display):
- Automatic via
SentryNavigatorObserver - Triggered when route becomes visible
TTFD (Time to Full Display):
- Manual via
SentryDisplayWidget.of(context).reportFullyDisplayed() - Wrap screen in
SentryDisplayWidgetwidget - Call
reportFullyDisplayed()when content is fully loaded - Currently implemented on home page product list
- Each developer sets their name in
lib/se_config.dart:const se = 'your-name'; - Added as tag on all events:
se: your-name - Added to fingerprint for per-engineer issue grouping
- Allows multiple engineers to use same Sentry project without interference
- Pattern: Provider with
ChangeNotifier - Cart State:
CartModelextendsChangeNotifier - UI Updates:
Consumer<CartModel>for reactive updates - Global Keys:
navigatorKeyfor programmatic navigation
- Named Routes:
/productDetails,/checkout - Arguments: Custom classes (
ProductArguments,CheckoutArguments) - Observer:
SentryNavigatorObservertracks all navigation
try {
// Operation
} catch (error, stackTrace) {
await Sentry.captureException(error, stackTrace: stackTrace);
// Show user feedback dialog if needed
}// Transaction
final transaction = Sentry.startTransaction('operation_name', 'operation_type');
// Span
final span = transaction.startChild('child_operation', description: 'Details');
// ... work ...
await span.finish();
await transaction.finish(status: SpanStatus.ok());// Setup
final log = Logger('ComponentName');
// Usage with Sentry.logger.fmt (captures to Sentry)
Sentry.logger.fmt.info('User %s clicked button', [userId],
attributes: {
'user_id': SentryLogAttribute.string(userId),
'button_name': SentryLogAttribute.string('checkout'),
}
);
// Standard logging (captured as breadcrumbs via LoggingIntegration)
log.info('Standard log message');
log.severe('Error occurred', error, stackTrace);// Counter
Sentry.metrics.count('promo_code_attempts', 1,
attributes: {'code': code, 'result': 'failed'}
);
// Gauge (current value)
Sentry.metrics.gauge('order_value', total,
unit: SentryMetricUnit.none
);
// Distribution (statistical measurement)
Sentry.metrics.distribution('api_latency', latencyMs,
unit: SentryMetricUnit.millisecond
);// Dio integration (automatic tracing)
final dio = Dio();
dio.addSentry(); // Done in sentry_setup.dart
// SentryHttpClient (automatic tracing)
final client = SentryHttpClient();
await client.get(Uri.parse('https://example.com'));# Build for platform (default: release)
./demo.sh build [platform] [build-type]
# Run on device and create Sentry deploy
./demo.sh run [platform]
# Verify setup (Flutter, Sentry CLI, .env)
./demo.sh verify
# Show help
./demo.sh help| Platform | Command | Output Location |
|---|---|---|
| Android APK | ./demo.sh build android |
build/app/outputs/flutter-apk/app-release.apk |
| Android AAB | ./demo.sh build aab |
build/app/outputs/bundle/release/app-release.aab |
| iOS | ./demo.sh build ios |
build/ios/iphoneos/Runner.app |
| Web | ./demo.sh build web |
build/web/ |
| macOS | ./demo.sh build macos |
build/macos/Build/Products/Release/ |
| Linux | ./demo.sh build linux |
build/linux/x64/release/bundle/ |
| Windows | ./demo.sh build windows |
build/windows/x64/runner/Release/ |
release(default) - Obfuscation, symbol upload, release managementprofile- No obfuscation, no release managementdebug- No obfuscation, no release management
- Validates environment (.env variables)
- Checks Flutter and Sentry CLI installation
- Runs
flutter pub get - Builds with obfuscation and debug symbol generation
- Creates Sentry release:
sentry-cli releases new - Uploads debug symbols and source maps
- (Optional) Uploads ProGuard mapping for Android
- (Optional) Uploads build for size analysis
- Finalizes release:
sentry-cli releases finalize
SENTRY_AUTH_TOKEN=sntryu_xxx # Sentry auth token
SENTRY_DSN=https://xxx@xxx.ingest.sentry.io/xxx
SENTRY_RELEASE=com.example.empower_flutter@9.14.0+1
SENTRY_ENVIRONMENT=development # development/staging/production
SENTRY_ORG=your-org-slug
SENTRY_PROJECT=your-project-slug
SENTRY_SIZE_ANALYSIS_ENABLED=true # Optional: enable size trackingDart Errors:
- Dart Exception - Simple throw
- Timeout Exception - Simulated timeout
- Platform Exception - Native communication error
- Missing Plugin Exception - Plugin not found
- Assertion Error - Failed assertion
- State Error - Invalid state
- Range Error - Out of bounds
- Type Error - Type mismatch
Native Errors:
- C++ Segfault - Native crash via method channel
- Kotlin Exception - Android-only native exception
Main Thread Blocking:
- Database query simulation (2M iterations)
- File I/O on main thread
- JSON decoding (15k items)
- Image decoding on main thread
- Complex regex operations
Async Issues:
- N+1 API calls (15 sequential requests)
- Function regression (500ms delay)
- Frame drops (rapid setState calls)
ANR/Hangs:
- Android ANR: 10-second freeze
- iOS/macOS App Hang: 3-second freeze
- Promo code validation with metrics
- API latency tracking with distributions
- Structured logging with attributes
- Order value gauge metrics
- User feedback collection on errors
- Clone repository
- Copy
.env.exampleto.env - Fill in Sentry credentials (DSN, ORG, PROJECT, AUTH_TOKEN)
- Update engineer name in
lib/se_config.dart - Run
./demo.sh verifyto check configuration - Run
./demo.sh build android(or your target platform)
# Get dependencies
flutter pub get
# Run in debug mode (no Sentry release management)
flutter run -d <device-id>
# Verify code quality
flutter analyze
# Build for testing
./demo.sh build android debug
# Build and run with release management
./demo.sh build android
./demo.sh run android- Error Tracking: Use drawer menu to trigger errors
- Performance: Navigate app, check Performance tab in Sentry
- Session Replay: Perform actions, check replay in Sentry Issues
- TTFD: Navigate to home, wait for products to load
- Metrics: Complete checkout flow, check Metrics in Sentry
- Logs: Check Logs section in Sentry Issues
- Spotlight: Run in debug mode, visit
http://localhost:8969for local Sentry events
Update Version:
- Edit
pubspec.yaml- change version - Update
.env- changeSENTRY_RELEASE - Commit changes
- Build:
./demo.sh build android
Add New Error Trigger:
- Add method in
navbar_destination.dart - Add drawer item with trigger
- Implement error scenario
- Use
Sentry.captureException()to capture
Add Performance Instrumentation:
- Start transaction:
Sentry.startTransaction() - Add spans for sub-operations
- Finish with appropriate status
- Add metrics if needed
- NEVER use Bash commands for file operations (cat, sed, awk, echo)
- ALWAYS use dedicated tools: Read, Edit, Write for files
- NEVER run
greporfindcommands - use Grep and Glob tools
- Check with user before destructive operations (force push, reset --hard, etc.)
- Create NEW commits after hook failures (not amend)
- Add files by name when staging, avoid
git add -A - Never skip hooks (--no-verify) unless explicitly requested
- Follow
analysis_options.yamllinting rules - Keep functions focused and single-purpose
- Use meaningful variable names
- Add comments only where logic isn't self-evident
- Don't add features beyond what's requested
- Set
setag consistently fromse_config.dart - Use structured logging with attributes for searchability
- Add context to transactions with tags/data
- Use appropriate span operations for clarity
- Capture user feedback on critical errors
Purpose: Track APK/AAB file size over time in Sentry
Enable:
# In .env
SENTRY_SIZE_ANALYSIS_ENABLED=trueRequirements:
- Sentry CLI installed (
brew install sentry-cli) - Auth token configured
- Release build (not debug/profile)
Automatic Uploads:
- APK:
build/app/outputs/flutter-apk/app-release.apk - AAB:
build/app/outputs/bundle/release/app-release.aab - ProGuard mapping:
build/app/outputs/mapping/release/mapping.txt
Disable: Set to false or comment out in .env for faster local builds
- Run
./demo.sh verifyto check setup - Ensure
.envexists with valid credentials - Check Flutter installation:
flutter doctor - Clean build:
flutter clean && flutter pub get
- Verify DSN in
.env - Check Sentry project settings
- Verify sampling rates (should be 1.0 for demo)
- Check Spotlight in debug mode:
http://localhost:8969
- Verify
SENTRY_AUTH_TOKENhas upload permissions - Check
SENTRY_ORGandSENTRY_PROJECTare correct - Ensure release was created before symbol upload
- Ensure screen is wrapped in
SentryDisplayWidget - Call
reportFullyDisplayed()when content is ready - Check that
enableTimeToFullDisplayTracing = true
- Backend API:
https://flask.empower-plant.com/ - Spotlight (Debug):
http://localhost:8969/ - GitHub (Sentry SDK):
https://github.com/getsentry/sentry-dart
- App Version: 9.14.0+1
- Flutter SDK: >= 3.22.0
- Sentry SDK: ^9.14.0
- Config:
.env,lib/se_config.dart,pubspec.yaml - Sentry Setup:
lib/sentry_setup.dart - Build Output:
build/directory - Debug Symbols:
build/debug-info/,build/app/obfuscation.map.json
Last Updated: Session creating this CLAUDE.md Current Branch: feature/comprehensive-sentry-integration App Version: 9.14.0+1