initialize static method
Initializes the observability pipeline and attaches automated error hooks.
Implementation
static Future<void> initialize(BloomObservabilityConfig config) async {
if (_isInitialized) {
await reset();
}
_config = config;
_ringBuffer = BloomBreadcrumbRingBuffer(maxCapacity: config.maxBreadcrumbs);
_isInitialized = true;
if (!config.enabled) {
logger.info('BloomObservability: Disabled by configuration.');
return;
}
// 1. Hook Flutter widget error pipeline
if (config.autoCaptureFlutterErrors) {
_originalFlutterOnError = FlutterError.onError;
_flutterHookInstalled = true;
FlutterError.onError = (FlutterErrorDetails details) {
captureException(
details.exception,
stackTrace: details.stack,
context: {
'library': details.library ?? 'flutter_framework',
'context': details.context?.toDescription() ?? 'rendering',
..._config.tags,
},
level: BloomErrorLevel.error,
);
if (_originalFlutterOnError != null) {
_originalFlutterOnError!(details);
}
};
}
// 2. Hook PlatformDispatcher asynchronous unhandled errors
if (config.autoCaptureZoneErrors) {
_originalPlatformOnError = PlatformDispatcher.instance.onError;
_platformHookInstalled = true;
PlatformDispatcher.instance.onError = (Object error, StackTrace stack) {
captureException(
error,
stackTrace: stack,
context: {
'origin': 'platform_dispatcher_async',
..._config.tags,
},
level: BloomErrorLevel.fatal,
);
if (_originalPlatformOnError != null) {
return _originalPlatformOnError!(error, stack);
}
return true;
};
}
// 3. Native platform crash handler hook (Android/iOS)
if (config.autoCaptureNativeCrashes && !kIsWeb) {
try {
await _nativeChannel.invokeMethod<void>('enableNativeCrashReporting');
final pendingCrashes =
await _nativeChannel.invokeListMethod<dynamic>('getPendingNativeCrashes');
if (pendingCrashes != null && pendingCrashes.isNotEmpty) {
for (final crash in pendingCrashes) {
if (crash is Map) {
await captureException(
crash['message'] ?? 'Native Crash',
exceptionType: crash['exceptionType']?.toString() ?? 'NativeCrash',
stackTrace: crash['stackTrace']?.toString(),
context: {
'native': true,
if (crash['signal'] != null) 'signal': crash['signal'],
if (crash['context'] is Map)
...Map<String, dynamic>.from(crash['context'] as Map),
..._config.tags,
},
level: BloomErrorLevel.fatal,
);
}
}
await _nativeChannel.invokeMethod<void>('clearPendingNativeCrashes');
}
} catch (e) {
logger.debug('BloomObservability: Native crash bridge unhandled or stubbed: $e');
}
}
logger.info(
'BloomObservability: Initialized (Sampling: ${(config.sampleRate * 100).toInt()}%, Ring Buffer: ${config.maxBreadcrumbs})');
}