getsentry / getsentry/sentry-react-native

Keep the native session's error count correct when a JS error is dropped by sampling

Aperta
#6,660 1 commento 0 reazioni 0 assegnatari Vedi su GitHub
Android Feature Platform: React Native React-Native
Lingua principale
TypeScript
Stelle
1.8k
Fork
366
Merge medio
1g 5h
PR unite (30g)
93

Descrizione

### Summary

When an error event is dropped **by sampling** on the JS side (`sampleRate`), the envelope is never forwarded to native, so the native session never records that an error occurred — a session that should be `errored` (or `unhandled`) can finalize as healthy/`exited`. Adopt `updateSessionForDroppedEventNonTerminating` to update the native session's error count in that path, without sending an envelope.

This is the **sampling-path counterpart to #6659** (which handles unhandled errors that *do* produce an envelope). It is the RN equivalent of Flutter [#4008](https://github.com/getsentry/sentry-dart/pull/4008).

Targeted at the **next RN SDK major** and **stacked after #6659** — see *Sequencing* below.

### The drift

RN sessions are owned by the native SDK; JS forwards envelopes. The only native session signal is via `captureEnvelope` (`wrapper.ts:196-235` → `RNSentryModuleImpl.java:500-511`). So when JS drops an error by `sampleRate` before it reaches `captureEnvelope`, native never learns an error occurred, and the session's `errors` count / status drifts. Same motivation as Flutter #4008: without a separate update, a gracefully ending session is reported as `exited` instead of `errored`/`unhandled`.

### Scope — sampling only, NOT `beforeSend`

Call this **only for events dropped by sampling**. The native API contract is explicit (sentry-cocoa `SentryInternalEnvelopeApi`):

> "Do not call this for events dropped by `beforeSend` or ignored exception types, and do not call it in addition to `captureNonTerminating` for the same event."

So this path must fire for `sampleRate` drops only — not `beforeSend` returning `null`, not ignored/denied exception types. Flutter #4008 does the same: it "receives only final events accepted by processors and `beforeSend`." (This corrects the original issue text, which mentioned `beforeSend`.)

The API takes an `unhandled: boolean` — set it from the dropped event's `mechanism.handled === false`.

### Native API (available now)

- **Android** — sentry-java 8.55.0 ([#5990](https://github.com/getsentry/sentry-java/pull/5990)), merged via #6658: `InternalSentrySdk.updateSessionForDroppedEventNonTerminating`.
- **iOS** — sentry-cocoa 9.27.0 (pinned in `RNSentry.podspec`): `SentrySDK.internal.envelope.updateSessionForDroppedEventNonTerminating(unhandled:)`.

### Design sketch

- **JS** — a "sampled-out event" hook in the client path: when an error event is dropped specifically by `sampleRate` (not `beforeSend`/ignored), call a new `NATIVE` method with the `unhandled` flag. Mirror Flutter #4008's internal lifecycle-hook design once it settles.
- **Bridge** — new bridge method `updateSessionForDroppedEventNonTerminating(unhandled: boolean)` (additive, backward-compatible; older cached native binaries simply no-op it).
- **Android / iOS** — forward to the respective native API; catch at the boundary, off-main where the native call persists.
- **Guard** — never call this for an event that also went through the #6659 capture path (double-count).

### Sequencing

- **Stacked after #6659.** Shares the non-terminating session plumbing and the no-double-count rule; #6659's capture path is the stable base.
- **Hold on the JS hook design** until Flutter #4008 (still open/unmerged) settles — it's the novel part most likely to be reshaped in review.
- **Same milestone as #6659** (next major).

### Release classification

Not an API/ABI break (additive bridge method, no public JS API change). It **is** a Release Health behavior shift — `errored`/`unhandled` session rates become more accurate under error sampling — so it belongs in the next major with a CHANGELOG note.

Follow-up from the 8.55.0 bump (#6658). Pairs with #6659.

Guida per i contributori

Apri la guida per i contributori

Direzione di ricerca

Inizia dal percorso client degli eventi campionati e dal flusso bridge esistente in wrapper.ts:196-235 e RNSentryModuleImpl.java:500-511, quindi esamina il plumbing impilato di #6659 e RNSentry.podspec. Conferma le API native di forwarding per Android e iOS prima di definire il design dell’hook JS. Il lavoro è completato quando gli errori campionati scartati aggiornano la sessione nativa con il valore unhandled del meccanismo, mentre gli scarti di beforeSend, i tipi ignorati e gli eventi già catturati non vengono conteggiati due volte né inviano un envelope.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
android, ios, react-native, typescript
Ambito
mobile, observability
Tipo di issue
Funzionalità
Difficoltà
5/5
Tempo stimato
Più di una settimana
Stato di attività
Attiva
Chiarezza
Abbastanza chiara
Idoneità per principianti
45/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.