Help Instance Help

m8ty_crash_facade

A crash reporting facade that decouples app code from specific providers (Firebase Crashlytics, Dynatrace, Sentry). Uses rxdart PublishSubject to broadcast events — provider adapters subscribe and forward to their platform SDK.

Architecture

  • M8tyCrashFacade.instance is the singleton entry point.

  • Provider adapters subscribe to M8tyCrashFacade.instance.stream.

  • Multiple providers can subscribe simultaneously.

  • Providers handle their own SDK initialization independently.

API Surface

Event

Method

Purpose

RecordError

recordError(exception, stackTrace:, fatal:)

Report a live exception

RecordFlutterError

recordFlutterError(details, fatal:)

Report a Flutter framework error

ReportError

reportError(errorName, errorCode)

Report a named non-crashing error

ReportCrash

reportCrash(errorName, reason, stackTrace)

Report a named crash with strings

ReportAction

reportAction(actionName, values)

Report a user action with key-value data

LogMessage

log(message)

Log a free-form message

SetUserId

setUserId(userId)

Identify the user

SetCustomKey

setCustomKey(key, value)

Attach metadata to future reports

Key Rules

  • Always use M8tyCrashFacade.instance — do not construct it directly.

  • Use reportAction for user actions with key-value data (maps to Dynatrace's enterAction/leaveAction pattern).

  • Use recordError for live exceptions, reportError for named non-crashing errors, reportCrash for pre-formatted crash strings.

  • Wire both FlutterError.onError and PlatformDispatcher.instance.onError for global crash capture.

  • Provider adapters must handle all CrashEvent subtypes (sealed class ensures exhaustiveness).

  • setUserId(null) clears the user context.

Examples

Report from app code

final crash = M8tyCrashFacade.instance; crash.recordError(exception, stackTrace: stackTrace, fatal: true); crash.reportError('checkout_validation_failed', 422); crash.reportCrash('NullPointerException', 'reason', 'stackTrace'); crash.reportAction('Changed theme mode', {'ui_mode': 'dark'}); crash.log('User tapped checkout'); crash.setUserId('user-123'); crash.setUserId(null); // clear user crash.setCustomKey('screen', 'home');

Wire global Flutter error handlers

void main() { FlutterError.onError = (details) { M8tyCrashFacade.instance.recordFlutterError(details, fatal: true); }; PlatformDispatcher.instance.onError = (error, stack) { M8tyCrashFacade.instance.recordError(error, stackTrace: stack, fatal: true); return true; }; runApp(const MyApp()); }

Write a provider adapter

M8tyCrashFacade.instance.stream.listen((event) { switch (event) { case RecordError(:final exception, :final stackTrace, :final fatal): // forward to provider SDK case RecordFlutterError(:final details, :final fatal): // forward flutter error case ReportError(:final errorName, :final errorCode): // forward named error case ReportCrash(:final errorName, :final reason, :final stackTrace): // forward crash case ReportAction(:final actionName, :final values): // forward action case LogMessage(:final message): // forward log case SetUserId(:final userId): // forward user id case SetCustomKey(:final key, :final value): // forward metadata } });
03 June 2026