Skip to content

Support and the Pigeon channel ​

otel_zone is a Flutter plugin registered on Android and iOS. The Dart half runs everywhere Flutter does; the native half — crash capture — only where there is a process for the OS to remember dying.

What runs where ​

FeatureAndroidiOSWebDesktop
runGuarded: framework and zone errorsyesyesyesyes
runGuarded: PlatformDispatcher.onErroryesyesreaches the zone insteadyes
runGuarded: Isolate.addErrorListeneryesyesnot installedyes
Export floor, breadcrumbs, redactyesyesyesyes
Flush when the app is hidden or pausedyesyeson hiddenas Flutter reports it
Native crash recoveryJVM; API 30+ exit recordsMetricKit (14+), NSExceptionno-opno-op
setCrashScreen reaches the platformyesyeskept, not sentkept, not sent

Details: Android, iOS, Web and desktop.

The Pigeon channel ​

Everything between Dart and the native code goes over one Pigeon contract, pigeons/native_crash.dart. It is generated, not written by hand, into three committed files:

OutputLanguage
lib/src/native-crash.g.dartDart
android/src/main/kotlin/com/vaam/otel_zone/NativeCrashApi.g.ktKotlin
ios/otel_zone/Sources/otel_zone/NativeCrashApi.g.swiftSwift

pigeon is a dev dependency only: the output is committed, so building an app does not need it. To regenerate after changing the contract:

bash
dart run pigeon --input pigeons/native_crash.dart && dart format .

NativeCrashApi — reading the previous run's deaths ​

MethodWhat it does
pending()every report the OS holds that has not been acknowledged yet, oldest first (async)
acknowledge(List<String> ids)marks reports as delivered — called only once they are durable (async)

The OS's list cannot be cleared, so the platform side deduplicates by a persisted watermark; Dart only ever sees reports that are new to it.

CrashContextApi — naming the current screen ​

MethodWhat it does
setCrashScreen(String? screen)records the route pattern this process shows (null clears it), on a serial background queue

NativeCrashReport — one death ​

FieldTypeMeaning
idStringthe platform's own id, opaque to Dart, stable across launches
kindStringjvm, native, anr, nsexception, signal or hang
timestampMicrosintwhen the process died, in microseconds since the Unix epoch
typeString?the signal name, the exception class, the exit reason
messageString?the human-readable reason, where the platform keeps one
stacktraceString?the stack trace, symbolised as far as the OS got
threadsList<String>?per-thread frames, for a crash whose stack is only meaningful per thread
sessionIdString?the app session the death happened in
attributesMap<String, String>?anything else the platform knows, flattened

kind is a string rather than an enum so that an unknown future value from a newer OS arrives intact instead of failing the whole call.

On the Dart side, NativeCrashSource is the seam the drain depends on rather than the generated client, and PigeonNativeCrashSource is its default implementation. Likewise CrashScreenSink and PigeonCrashScreenSink for the screen. Both are injection points — see Testing.

Released under the MIT License.