@wuguishifu/crash-observer

View on GitHub

@wuguishifu/crash-observer is an Expo native module that captures crashes at the native layer — uncaught exceptions and (optionally) POSIX signals — and delivers them to your logging system on the next launch.

Unlike Sentry/Crashlytics-style SDKs, this library has no networking and no opinions about where reports go. A native crash kills the process, so a report can't reliably be sent in-process anyway — instead the native layer persists each crash as a file in app-private storage, and on the next launch your JS handler receives the pending reports and sends them wherever you like: your analytics pipeline, a plain HTTP endpoint, anything.

Installation

npm install @wuguishifu/crash-observer
# or
pnpm add @wuguishifu/crash-observer

Requires an Expo project (bare or prebuild workflow — the native module is autolinked by Expo Modules). After installing, rebuild the native app:

npx expo prebuild
npx expo run:ios    # or run-android

Usage

import * as CrashObserver from '@wuguishifu/crash-observer';

// at app startup
CrashObserver.start({
  onReport: async (report) => {
    // plug in your own transport - throwing keeps the report for a retry
    await myLogger.send('native-crash', report);
  },
});

// attach whatever identifies the session in your system
CrashObserver.setContext({
  userId: user.id,
  sessionId,
});

// leave a trail for debugging
CrashObserver.addBreadcrumb({
  message: 'opened reader',
  category: 'navigation',
});

Delivery semantics

  • Reports are written to disk at crash time, one file per crash — multiple undelivered crashes don't overwrite each other.
  • On start({ onReport }), every pending report is passed to your handler, oldest first.
  • Handler resolves → the report is deleted. Handler throws → the report is kept and retried on the next start or flushPendingReports call. Delivery is at-least-once, so make your sink idempotent (report.id is stable).
  • start() resolves after delivery finishes; call it without await if you don't want delivery to block startup.

API overview

FunctionDescription
start(options)Installs crash handlers and delivers pending reports to options.onReport.
flushPendingReports(handler?)Re-runs delivery (e.g. after connectivity returns).
getPendingReports()Returns undelivered reports without deleting them.
deleteReport(id) / deleteAllReports()Manual cleanup if you manage delivery yourself.
setContext(values) / clearContext()Key-value context attached to future reports.
addBreadcrumb(crumb) / clearBreadcrumbs()Breadcrumb trail attached to future reports.
simulateCrash(type?)Actually crashes the app to test the pipeline. Test builds only.

See the package README for the full API, CrashReport shape, StartOptions, and the list of things this library deliberately does not do (JS error handling, symbolication, watchdog/OOM kills).