Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/workflows/audit-errors.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Audit and client errors
on:
pull_request:
push:
branches: [main, master]
permissions:
contents: read
jobs:
javascript:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: npm
cache-dependency-path: js/package-lock.json
- run: npm ci
working-directory: js
- run: npm run typecheck:errors && npx vitest run && npm run build:errors
working-directory: js
laravel:
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: Select runner PHP 8.3
run: |
sudo update-alternatives --set php /usr/bin/php8.3
php -r 'exit(PHP_VERSION_ID >= 80300 && PHP_VERSION_ID < 80400 && extension_loaded("pdo_sqlite") ? 0 : 1);'
- run: composer install --no-interaction --prefer-dist
working-directory: php/laravel
- run: vendor/bin/phpunit --testsuite=Unit
working-directory: php/laravel
33 changes: 30 additions & 3 deletions js/ERRORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ a short flush when leaving the foreground. Set the current screen with
Promise rejection hooks differ across React Native versions and engines. Pass
`subscribeUnhandledRejection(listener)`, returning an unsubscribe function, from
your runtime integration when available. `coverage.unhandledRejections` is false
without it. The SDK does not replace Hermes's rejection tracker or claim automatic
without it. Set `requireCoverage: ['globalErrors', 'unhandledRejections']` in
the hooks argument to reject startup configuration that lacks a required hook;
failed installation restores the previous handler and removes subscriptions. The SDK does not replace Hermes's rejection tracker or claim automatic
coverage where no compatible subscription is supplied. Handled promise failures
can always use `captureException`.

Expand Down Expand Up @@ -119,8 +121,13 @@ Events exceeding 60 KB or a full queue are dropped. Delivery retries network
failures, `408`, `429` and `5xx` up to five attempts, preserving exact bytes and ID.
It respects `Retry-After` and uses exponential backoff. Events older than five
minutes are discarded; other `4xx` responses are terminal. `getStats()` returns
sent, dropped, retried and queued counts. No delivery failure creates another
telemetry error. Browser visibility changes request a flush with `keepalive`.
sent, dropped, retried and queued counts, plus `droppedByReason`. An optional
`onDiagnostic` callback reports drops and retries without event payloads. Its
exceptions are ignored and error capture inside that callback is suppressed to
avoid recursion. Use a separate health channel to monitor delivery losses. No delivery failure creates another
telemetry error. Browser visibility changes request a flush with `keepalive`. Flush deadlines
apply even if a custom transport ignores abort; late replies are ignored. Closing
the client cancels its pending wait and accounts for queued events once.

This is best-effort delivery. Closing a tab, terminating an app, prolonged offline
use or fatal JS errors can lose queued events. There is no persistent offline queue.
Expand All @@ -145,3 +152,23 @@ Upload every generated chunk with its exact URL path. For mobile use
actual iOS stack) and the matching composed map. All identity fields must match
the event. Maps may be uploaded after an error; refreshing its detail resolves
the new map. Group membership remains build-scoped and unchanged.

## Validate a mobile release

Hook availability is not proof that a runtime emits every error. Before enabling
this as the only reporter, test on each supported Android/iOS release build:

1. Trigger a global JS error, a rejected promise, and a React render failure.
Confirm the corresponding mechanism, context and one occurrence in Traceflow.
2. Upload that build's composed map and verify a known source filename and line.
Repeat after an OTA update with a different `dist`.
3. Test offline/reconnect, background/foreground, and a fatal JS error. The fatal
hook starts delivery before invoking the previous handler, but process exit can
still lose the event. Native crashes are not captured.
4. Verify required coverage flags, handler restoration on disposal, and delivery
diagnostics when ingestion returns `429` or `503`.

The repository tests cover hook contracts, stack parsing, retries and cancellation.
They do not certify a specific React Native/Expo/Hermes version or physical device.
Run `npm run typecheck:errors`, `npm run test:errors`, and `npm run build:errors`
to check the frontend distributions without the optional native Kafka dependency.
Loading
Loading