Infrastructure SDKs
How to add crash reporting and monitoring to a Flutter app
Free Reference for monitoring_sdk: every variable, option and package it generates. Command: archipelago generate monitoring_sdk
Generate the Monitoring SDK, add a vendor brick, log errors and transactions through AppMonitoring, and see how consent gating and PII scrubbing work.
What you'll learn
- Generating the Monitoring SDK and adding vendor bricks
- Using
AppMonitoringfor logs, errors and transactions - Understanding consent gating and PII scrubbing
- Knowing what ships in release builds
Prerequisites
- An existing Archipelago monorepo (see Monorepo Scaffolding)
- A vendor account (Crashlytics, Sentry, Grafana or New Relic) for real reports
Step 1: Generate the Monitoring SDK
flutter_modular_monorepo always generates monitoring_sdk, even with no vendor. To add it to an older project, run:
archipelago generate monitoring_sdkThe prompts are:
- appName: your app name, for example
MyApp - isForMonorepo: leave this as
true
Or use a config file:
{
"appName": "MyApp",
"isForMonorepo": true
}archipelago generate monitoring_sdk --config monitoring_config.jsonChoose vendors with monitoringVendors when you create the project. Each vendor is its own brick:
Generate monitoring_sdk before you add a vendor to an existing project. The vendor imports monitoring_api.
Step 2: Understand the Three-Package Structure
infrastructure/
├── monitoring_api/ # AppMonitoring, AppMonitoringVendor, MonitoringLevel
├── monitoring_impl/ # Fanout, consent decorator, vendor collection
│ └── lib/src/
│ ├── monitoring_fanout_impl.dart
│ ├── consent_aware_monitoring.dart
│ └── di/
└── monitoring_noop/ # Inert stub for tests or an explicit opt-outA vendor implements AppMonitoringVendor and registers under a @Named key. MonitoringFanoutImpl sends each call to every enabled vendor. One vendor that throws does not stop the others.
With no vendor installed, AppMonitoring still works. isEnabled is false and every call does nothing.
Step 3: Check the Registration
The post-generation hook adds the package to the app pubspec.yaml. It registers MonitoringImplPackageModule in lib/di/injector.dart. getIt<AppMonitoring>() returns ConsentAwareMonitoring, which wraps the fanout. You never resolve the fanout directly.
Step 4: Use AppMonitoring
Features take AppMonitoring from monitoring_api by constructor:
class PaymentRepository {
PaymentRepository(this._monitoring);
final AppMonitoring _monitoring;
Future<Payment> processPayment(PaymentRequest request) async {
_monitoring.log('Payment started', tag: 'PAY', level: MonitoringLevel.info);
try {
return await _monitoring.recordTransaction(
'process_payment',
() => _remote.process(request),
operation: 'http.post',
);
} catch (e, st) {
await _monitoring.recordError(e, st);
rethrow;
}
}
}The other methods are breadcrumb, setUserContext, clearUserContext and recordFlutterError.
Step 5: Understand Consent and Scrubbing
ConsentAwareMonitoring checks ConsentPurpose.diagnostics on every call. Until the user grants it, nothing reaches a vendor, and initialize() does not start the vendor SDKs.
recordTransactionstill runs your action when consent is denied. Only the report is skipped.clearUserContextanddisposeare never gated.- When the user withdraws diagnostics consent later, every vendor stops collecting and drops what it buffered. A later grant starts the vendors again.
recordTransactionkeeps aduration_msyou pass indata. It measures one only when you give none.- Exception messages pass through the telemetry scrubber before they leave the device.
Step 6: Know the Global Error Handlers
The fanout installs no global handlers. bootstrap.dart owns FlutterError.onError and PlatformDispatcher.instance.onError. Both report through AppMonitoring, so consent gates every uncaught error.
Step 7: Release Builds
Monitoring ships in release builds. Crash reporting matters most in production, and the consent gate is the privacy control. The generated build_prepare.yaml has no monitoring mapping. The debug tooling (app_debugger, app_blackbox) is what the production flavor strips.
To strip monitoring from release anyway, add this mapping by hand:
build_prepare:
mappings:
- debug: monitoring_impl
release: monitoring_noopThen run dart run monorepo_toolkit build-prepare --flavor production before the build.
Step 8: Test
monitoring_impl needs no test prerequisite. A vendor that cannot be built in a test, such as Crashlytics without Firebase, is skipped. getIt<AppMonitoring>() still resolves. Run the composition-root test:
cd apps/<appName>
flutter test test/di/injector_test.dartKey Customization Points
| Customization | Where to Change |
|---|---|
| Add a vendor | Generate its brick |
| Strip monitoring in release | The build_prepare.yaml mapping above |
| Scrubbing rules | The app TelemetryScrubber from shared_consent |
Next Steps
- Set up authentication with crash tracking on auth failures
- Configure networking to log HTTP errors to monitoring