Observability & Telemetry
Production engineering requires 24/7 visibility into mobile app health. Production Observability captures uncaught runtime crashes, performance telemetry (HTTP latency, screen rendering times), user analytics, and structured breadcrumbs using tools like Firebase Crashlytics, Sentry, or Datadog.
1. Catching 100% of Production Errors
Flutter applications experience errors across 3 execution zones: Flutter Framework Errors, Asynchronous Dart Errors, and Native Platform Engine Errors.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β UNCAUGHT ERROR BOUNDARIES β
βββββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββ€
β 1. Flutter Framework Errors β 2. Async Dart Errors β 3. Native OS Crashes β
β - Widget build() exceptions β - Un-awaited Future errors β - iOS SIGSEGV β
β - Layout overflow errors β - Isolate event errors β - Android NDK NullPointerβ
βββββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββ€
β `FlutterError.onError` β `PlatformDispatcher.instance` β Native Crashlytics / β
β β `.onError` β Sentry SDK bindings β
βββββββββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββ΄βββββββββββββββββββββββββComplete Error Capture Pipeline Setup
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
void main() async {
runZonedGuarded(() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
// 1. Catch all Flutter Framework UI errors (e.g. build exceptions)
FlutterError.onError = (FlutterErrorDetails details) {
FlutterError.presentError(details);
FirebaseCrashlytics.instance.recordFlutterFatalError(details);
};
// 2. Catch all uncaught Asynchronous Dart errors
PlatformDispatcher.instance.onError = (error, stack) {
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
return true; // Prevents error from crashing process if handled
};
runApp(const MyApp());
}, (error, stack) {
// 3. Catch all Zone boundary errors
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
});
}2. Symbolication of Obfuscated Production Stack Traces
When release builds compile with --obfuscate --split-debug-info=./symbols, production stack traces are mangled into unreadable memory addresses:
# Obfuscated Crash Log (Unreadable):
#0 0x0000000104f2c1b4 in libapp.so (+0x1b4)
#1 0x0000000104f2d8a0 in libapp.so (+0x8a0)Symbolication Workflow
Symbolication maps memory addresses back to human-readable Dart file basenames and line numbers (user_repository.dart:42).
- CI Pipeline Requirement: The symbol map files generated during release compilation (
app.android-arm64.symbolsorDWARFfiles) MUST be uploaded to Sentry or Crashlytics automatically during CI deployment!
# Uploading obfuscation symbol maps to Sentry in CI
sentry-cli debug-files upload --auth-token $SENTRY_AUTH_TOKEN ./symbols3. Breadcrumb Logging & User Telemetry
Breadcrumbs track the sequence of user actions leading up to a crash (e.g. βUser tapped Login -> Navigated to Checkout -> Fired Payment API -> CRASHβ).
void trackUserActionBreadcrumb(String action) {
FirebaseCrashlytics.instance.log('User Action: $action');
// Custom Key-Value attributes for crash context
FirebaseCrashlytics.instance.setCustomKey('user_tier', 'premium');
}4. Performance Monitoring Telemetry
Track screen rendering latency and HTTP request durations in real-time:
- Custom Traces: Measure critical code paths (e.g. DB migration time, image processing speed).
- HTTP Network Tracing: Measures API response latencies, failure rates, and payload sizes across cellular carriers.
final trace = FirebasePerformance.instance.newTrace('checkout_processing_time');
await trace.start();
await executeCheckoutLogic();
await trace.stop(); // Sends execution duration to Firebase Console!5. Trade-offs & Production Considerations
- GDPR & PII Privacy: Never log Personally Identifiable Information (PII) like raw passwords, credit card numbers, or full names in Crashlytics logs or breadcrumbs. Sanitize custom key-value pairs before dispatch.
- Log Batching & Battery: Dispatching crash reports over network connections consumes battery. Telemetry SDKs batch logs locally in storage and upload them in periodic background batches.