When a native crash happens inside a TurboModule method, today's reports show the C++/ObjC/Java stack but no high-level "RNSentry.captureEnvelope was on the stack" attribution. The perf logger gives us the exact module + method that was active.
Goals:
- Maintain a small in-memory stack of active TurboModule invocations from the perf logger callbacks (
syncMethodCallStart/End, asyncMethodCallExecutionStart/End), keyed by thread.
- On the native crash path, attach the current top of stack as scope context before the crash report is captured:
contexts.turbo_module = { name, method, kind: "sync" | "async", started_at_ms, call_id }
- For async invocations, also include the JS-side call id so the report can be cross-referenced with the breadcrumb trail.
- Add the active module + method as tags (
turbo_module.name, turbo_module.method) so they are filterable in the Sentry UI.
- Cooperate with sentry-cocoa / sentry-java's crash handlers; the data needs to be written in async-signal-safe storage (similar to how scope is mirrored for crashes today). If async-signal-safety is not feasible for the full string, fall back to a small fixed-size ring buffer of
{module_id, method_id} indexes and resolve names post-crash on next launch.
When a native crash happens inside a TurboModule method, today's reports show the C++/ObjC/Java stack but no high-level "RNSentry.captureEnvelope was on the stack" attribution. The perf logger gives us the exact module + method that was active.
Goals:
syncMethodCallStart/End,asyncMethodCallExecutionStart/End), keyed by thread.contexts.turbo_module = { name, method, kind: "sync" | "async", started_at_ms, call_id }turbo_module.name,turbo_module.method) so they are filterable in the Sentry UI.{module_id, method_id}indexes and resolve names post-crash on next launch.