@grafana/faro-react-native 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +176 -30
- package/android/build.gradle +17 -12
- package/android/src/main/java/com/grafana/faro/reactnative/FaroCrashIds.kt +44 -0
- package/android/src/main/java/com/grafana/faro/reactnative/FaroCrashReporter.kt +134 -38
- package/android/src/main/java/com/grafana/faro/reactnative/FaroCrashSessionStore.kt +433 -0
- package/android/src/main/java/com/grafana/faro/reactnative/FaroCrashTraceCache.kt +11 -2
- package/android/src/main/java/com/grafana/faro/reactnative/FaroReactNativeModule.kt +128 -17
- package/android/src/main/java/com/grafana/faro/reactnative/FaroSessionProcess.kt +88 -0
- package/android/src/main/java/com/grafana/faro/reactnative/FrameMonitor.kt +34 -42
- package/android/src/test/java/com/grafana/faro/reactnative/FaroCrashReporterBelowApi30Test.kt +21 -0
- package/android/src/test/java/com/grafana/faro/reactnative/FaroCrashReporterTest.kt +59 -0
- package/android/src/test/java/com/grafana/faro/reactnative/FaroCrashSessionStoreTest.kt +268 -0
- package/android/src/test/java/com/grafana/faro/reactnative/FaroCrashTraceCacheTest.kt +52 -0
- package/android/src/test/java/com/grafana/faro/reactnative/FaroSessionProcessTest.kt +127 -0
- package/dist/cjs/config/getRNInstrumentations.js +6 -8
- package/dist/cjs/config/getRNInstrumentations.js.map +1 -1
- package/dist/cjs/config/sampling.js.map +1 -1
- package/dist/cjs/config/types.js.map +1 -1
- package/dist/cjs/dataCollection/DataCollectionPolicy.js +1 -2
- package/dist/cjs/dataCollection/DataCollectionPolicy.js.map +1 -1
- package/dist/cjs/generated/faroRNPackageMeta.js +1 -1
- package/dist/cjs/generated/faroRNPackageMeta.js.map +1 -1
- package/dist/cjs/index.js +8 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/instrumentations/anr/instrumentation.js +10 -1
- package/dist/cjs/instrumentations/anr/instrumentation.js.map +1 -1
- package/dist/cjs/instrumentations/appState/index.js +8 -2
- package/dist/cjs/instrumentations/appState/index.js.map +1 -1
- package/dist/cjs/instrumentations/crashReporting/BaseCrashReportingInstrumentation.js +19 -6
- package/dist/cjs/instrumentations/crashReporting/BaseCrashReportingInstrumentation.js.map +1 -1
- package/dist/cjs/instrumentations/crashReporting/RecoveredCrashReportingInstrumentation.js +331 -0
- package/dist/cjs/instrumentations/crashReporting/RecoveredCrashReportingInstrumentation.js.map +1 -0
- package/dist/cjs/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.js +2 -2
- package/dist/cjs/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.js.map +1 -1
- package/dist/cjs/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.js +2 -2
- package/dist/cjs/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.js.map +1 -1
- package/dist/cjs/instrumentations/crashReporting/types.js.map +1 -1
- package/dist/cjs/instrumentations/errors/index.js +8 -3
- package/dist/cjs/instrumentations/errors/index.js.map +1 -1
- package/dist/cjs/instrumentations/frameMonitoring/instrumentation.js +20 -31
- package/dist/cjs/instrumentations/frameMonitoring/instrumentation.js.map +1 -1
- package/dist/cjs/instrumentations/frameMonitoring/types.js.map +1 -1
- package/dist/cjs/instrumentations/performance/index.js +2 -6
- package/dist/cjs/instrumentations/performance/index.js.map +1 -1
- package/dist/cjs/instrumentations/session/FaroSessionActivityBoundary.js +48 -0
- package/dist/cjs/instrumentations/session/FaroSessionActivityBoundary.js.map +1 -0
- package/dist/cjs/instrumentations/session/directSessionActivity.js +37 -0
- package/dist/cjs/instrumentations/session/directSessionActivity.js.map +1 -0
- package/dist/cjs/instrumentations/session/index.js +214 -45
- package/dist/cjs/instrumentations/session/index.js.map +1 -1
- package/dist/cjs/instrumentations/session/sessionActivity.js +43 -0
- package/dist/cjs/instrumentations/session/sessionActivity.js.map +1 -0
- package/dist/cjs/instrumentations/session/sessionAttributes.js +8 -8
- package/dist/cjs/instrumentations/session/sessionAttributes.js.map +1 -1
- package/dist/cjs/instrumentations/session/sessionManager/MmkvPersistentSessionsManager.js +199 -24
- package/dist/cjs/instrumentations/session/sessionManager/MmkvPersistentSessionsManager.js.map +1 -1
- package/dist/cjs/instrumentations/session/sessionManager/VolatileSessionManager.js +31 -13
- package/dist/cjs/instrumentations/session/sessionManager/VolatileSessionManager.js.map +1 -1
- package/dist/cjs/instrumentations/session/sessionManager/persistentSessionRecord.js +72 -0
- package/dist/cjs/instrumentations/session/sessionManager/persistentSessionRecord.js.map +1 -0
- package/dist/cjs/instrumentations/session/sessionManager/sessionConstants.js +1 -1
- package/dist/cjs/instrumentations/session/sessionManager/sessionConstants.js.map +1 -1
- package/dist/cjs/instrumentations/session/sessionManager/sessionManagerUtils.js +124 -96
- package/dist/cjs/instrumentations/session/sessionManager/sessionManagerUtils.js.map +1 -1
- package/dist/cjs/instrumentations/session/sessionManager/types.js.map +1 -1
- package/dist/cjs/instrumentations/session/sessionProcess.js +96 -0
- package/dist/cjs/instrumentations/session/sessionProcess.js.map +1 -0
- package/dist/cjs/instrumentations/startup/index.js +2 -6
- package/dist/cjs/instrumentations/startup/index.js.map +1 -1
- package/dist/cjs/navigation/utils.js +3 -1
- package/dist/cjs/navigation/utils.js.map +1 -1
- package/dist/cjs/transports/fetch/index.js.map +1 -1
- package/dist/cjs/transports/fetch/transport.js +56 -25
- package/dist/cjs/transports/fetch/transport.js.map +1 -1
- package/dist/cjs/transports/fetch/types.js.map +1 -1
- package/dist/cjs/transports/offline/ConnectivityService.js +1 -1
- package/dist/cjs/transports/offline/ConnectivityService.js.map +1 -1
- package/dist/cjs/transports/offline/OfflineCache.js +2 -2
- package/dist/cjs/transports/offline/OfflineCache.js.map +1 -1
- package/dist/cjs/transports/offline/transport.js +3 -4
- package/dist/cjs/transports/offline/transport.js.map +1 -1
- package/dist/cjs/userPersistence/UserPersistence.js +1 -2
- package/dist/cjs/userPersistence/UserPersistence.js.map +1 -1
- package/dist/esm/config/getRNInstrumentations.js +6 -8
- package/dist/esm/config/getRNInstrumentations.js.map +1 -1
- package/dist/esm/config/sampling.js.map +1 -1
- package/dist/esm/config/types.js.map +1 -1
- package/dist/esm/dataCollection/DataCollectionPolicy.js +1 -2
- package/dist/esm/dataCollection/DataCollectionPolicy.js.map +1 -1
- package/dist/esm/generated/faroRNPackageMeta.js +1 -1
- package/dist/esm/generated/faroRNPackageMeta.js.map +1 -1
- package/dist/esm/index.js +4 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/instrumentations/anr/instrumentation.js +6 -1
- package/dist/esm/instrumentations/anr/instrumentation.js.map +1 -1
- package/dist/esm/instrumentations/appState/index.js +8 -2
- package/dist/esm/instrumentations/appState/index.js.map +1 -1
- package/dist/esm/instrumentations/crashReporting/BaseCrashReportingInstrumentation.js +15 -4
- package/dist/esm/instrumentations/crashReporting/BaseCrashReportingInstrumentation.js.map +1 -1
- package/dist/esm/instrumentations/crashReporting/RecoveredCrashReportingInstrumentation.js +230 -0
- package/dist/esm/instrumentations/crashReporting/RecoveredCrashReportingInstrumentation.js.map +1 -0
- package/dist/esm/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.js +2 -2
- package/dist/esm/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.js.map +1 -1
- package/dist/esm/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.js +2 -2
- package/dist/esm/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.js.map +1 -1
- package/dist/esm/instrumentations/crashReporting/types.js.map +1 -1
- package/dist/esm/instrumentations/errors/index.js +8 -3
- package/dist/esm/instrumentations/errors/index.js.map +1 -1
- package/dist/esm/instrumentations/frameMonitoring/instrumentation.js +17 -32
- package/dist/esm/instrumentations/frameMonitoring/instrumentation.js.map +1 -1
- package/dist/esm/instrumentations/frameMonitoring/types.js.map +1 -1
- package/dist/esm/instrumentations/performance/index.js +2 -6
- package/dist/esm/instrumentations/performance/index.js.map +1 -1
- package/dist/esm/instrumentations/session/FaroSessionActivityBoundary.js +34 -0
- package/dist/esm/instrumentations/session/FaroSessionActivityBoundary.js.map +1 -0
- package/dist/esm/instrumentations/session/directSessionActivity.js +32 -0
- package/dist/esm/instrumentations/session/directSessionActivity.js.map +1 -0
- package/dist/esm/instrumentations/session/index.js +207 -46
- package/dist/esm/instrumentations/session/index.js.map +1 -1
- package/dist/esm/instrumentations/session/sessionActivity.js +38 -0
- package/dist/esm/instrumentations/session/sessionActivity.js.map +1 -0
- package/dist/esm/instrumentations/session/sessionAttributes.js +7 -7
- package/dist/esm/instrumentations/session/sessionAttributes.js.map +1 -1
- package/dist/esm/instrumentations/session/sessionManager/MmkvPersistentSessionsManager.js +190 -27
- package/dist/esm/instrumentations/session/sessionManager/MmkvPersistentSessionsManager.js.map +1 -1
- package/dist/esm/instrumentations/session/sessionManager/VolatileSessionManager.js +31 -14
- package/dist/esm/instrumentations/session/sessionManager/VolatileSessionManager.js.map +1 -1
- package/dist/esm/instrumentations/session/sessionManager/persistentSessionRecord.js +56 -0
- package/dist/esm/instrumentations/session/sessionManager/persistentSessionRecord.js.map +1 -0
- package/dist/esm/instrumentations/session/sessionManager/sessionConstants.js +1 -1
- package/dist/esm/instrumentations/session/sessionManager/sessionConstants.js.map +1 -1
- package/dist/esm/instrumentations/session/sessionManager/sessionManagerUtils.js +120 -44
- package/dist/esm/instrumentations/session/sessionManager/sessionManagerUtils.js.map +1 -1
- package/dist/esm/instrumentations/session/sessionManager/types.js.map +1 -1
- package/dist/esm/instrumentations/session/sessionProcess.js +89 -0
- package/dist/esm/instrumentations/session/sessionProcess.js.map +1 -0
- package/dist/esm/instrumentations/startup/index.js +2 -6
- package/dist/esm/instrumentations/startup/index.js.map +1 -1
- package/dist/esm/navigation/utils.js +2 -1
- package/dist/esm/navigation/utils.js.map +1 -1
- package/dist/esm/transports/fetch/index.js.map +1 -1
- package/dist/esm/transports/fetch/transport.js +38 -14
- package/dist/esm/transports/fetch/transport.js.map +1 -1
- package/dist/esm/transports/fetch/types.js.map +1 -1
- package/dist/esm/transports/offline/ConnectivityService.js +1 -1
- package/dist/esm/transports/offline/ConnectivityService.js.map +1 -1
- package/dist/esm/transports/offline/OfflineCache.js +2 -2
- package/dist/esm/transports/offline/OfflineCache.js.map +1 -1
- package/dist/esm/transports/offline/transport.js +3 -4
- package/dist/esm/transports/offline/transport.js.map +1 -1
- package/dist/esm/userPersistence/UserPersistence.js +1 -2
- package/dist/esm/userPersistence/UserPersistence.js.map +1 -1
- package/dist/types/config/getRNInstrumentations.d.ts +1 -2
- package/dist/types/config/sampling.d.ts +0 -3
- package/dist/types/config/types.d.ts +5 -3
- package/dist/types/dataCollection/DataCollectionPolicy.d.ts +1 -2
- package/dist/types/generated/faroRNPackageMeta.d.ts +1 -1
- package/dist/types/index.d.ts +4 -1
- package/dist/types/instrumentations/crashReporting/BaseCrashReportingInstrumentation.d.ts +14 -4
- package/dist/types/instrumentations/crashReporting/RecoveredCrashReportingInstrumentation.d.ts +27 -0
- package/dist/types/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.d.ts +2 -2
- package/dist/types/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.d.ts +2 -2
- package/dist/types/instrumentations/crashReporting/types.d.ts +6 -0
- package/dist/types/instrumentations/frameMonitoring/instrumentation.d.ts +2 -2
- package/dist/types/instrumentations/frameMonitoring/types.d.ts +4 -6
- package/dist/types/instrumentations/performance/index.d.ts +0 -2
- package/dist/types/instrumentations/session/FaroSessionActivityBoundary.d.ts +8 -0
- package/dist/types/instrumentations/session/directSessionActivity.d.ts +13 -0
- package/dist/types/instrumentations/session/index.d.ts +20 -1
- package/dist/types/instrumentations/session/sessionActivity.d.ts +9 -0
- package/dist/types/instrumentations/session/sessionAttributes.d.ts +6 -3
- package/dist/types/instrumentations/session/sessionManager/MmkvPersistentSessionsManager.d.ts +16 -3
- package/dist/types/instrumentations/session/sessionManager/VolatileSessionManager.d.ts +9 -3
- package/dist/types/instrumentations/session/sessionManager/persistentSessionRecord.d.ts +4 -0
- package/dist/types/instrumentations/session/sessionManager/sessionManagerUtils.d.ts +19 -7
- package/dist/types/instrumentations/session/sessionManager/types.d.ts +6 -0
- package/dist/types/instrumentations/session/sessionProcess.d.ts +17 -0
- package/dist/types/instrumentations/startup/index.d.ts +2 -6
- package/dist/types/navigation/utils.d.ts +1 -0
- package/dist/types/transports/fetch/index.d.ts +1 -1
- package/dist/types/transports/fetch/transport.d.ts +8 -1
- package/dist/types/transports/fetch/types.d.ts +5 -0
- package/dist/types/transports/offline/ConnectivityService.d.ts +1 -1
- package/dist/types/transports/offline/OfflineCache.d.ts +2 -2
- package/dist/types/transports/offline/transport.d.ts +3 -4
- package/dist/types/userPersistence/UserPersistence.d.ts +1 -2
- package/ios/FaroCrashReporter.swift +214 -21
- package/ios/FaroReactNative.swift +24 -0
- package/ios/FaroReactNativeModule.h +2 -1
- package/ios/FaroReactNativeModule.mm +121 -6
- package/ios/RefreshRateVitals.swift +34 -38
- package/package.json +7 -5
- package/src/config/getRNInstrumentations.ts +6 -8
- package/src/config/makeRNConfig.test.ts +6 -0
- package/src/config/sampling.ts +0 -3
- package/src/config/types.ts +5 -3
- package/src/dataCollection/DataCollectionPolicy.ts +1 -2
- package/src/generated/faroRNPackageMeta.ts +1 -1
- package/src/index.ts +8 -2
- package/src/instrumentations/anr/instrumentation.ts +8 -1
- package/src/instrumentations/appState/index.ts +10 -2
- package/src/instrumentations/crashReporting/BaseCrashReportingInstrumentation.ts +28 -8
- package/src/instrumentations/crashReporting/RecoveredCrashReportingInstrumentation.ts +277 -0
- package/src/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.ts +2 -2
- package/src/instrumentations/crashReporting/instrumentation.test.ts +433 -5
- package/src/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.ts +2 -2
- package/src/instrumentations/crashReporting/types.ts +7 -0
- package/src/instrumentations/errors/index.ts +12 -4
- package/src/instrumentations/errors/instrumentation.test.ts +35 -0
- package/src/instrumentations/frameMonitoring/instrumentation.test.ts +155 -0
- package/src/instrumentations/frameMonitoring/instrumentation.ts +19 -38
- package/src/instrumentations/frameMonitoring/types.ts +4 -6
- package/src/instrumentations/performance/index.ts +2 -6
- package/src/instrumentations/session/FaroSessionActivityBoundary.test.ts +60 -0
- package/src/instrumentations/session/FaroSessionActivityBoundary.tsx +41 -0
- package/src/instrumentations/session/beforeSendHook.test.ts +246 -0
- package/src/instrumentations/session/directSessionActivity.test.ts +158 -0
- package/src/instrumentations/session/directSessionActivity.ts +36 -0
- package/src/instrumentations/session/index.ts +269 -46
- package/src/instrumentations/session/persistentColdStart.test.ts +196 -0
- package/src/instrumentations/session/sessionActivity.test.ts +68 -0
- package/src/instrumentations/session/sessionActivity.ts +58 -0
- package/src/instrumentations/session/sessionAttributes.test.ts +37 -2
- package/src/instrumentations/session/sessionAttributes.ts +12 -6
- package/src/instrumentations/session/sessionCleanup.test.ts +410 -0
- package/src/instrumentations/session/sessionManager/MmkvPersistentSessionsManager.test.ts +552 -0
- package/src/instrumentations/session/sessionManager/MmkvPersistentSessionsManager.ts +249 -33
- package/src/instrumentations/session/sessionManager/VolatileSessionManager.ts +38 -18
- package/src/instrumentations/session/sessionManager/persistentSessionRecord.test.ts +103 -0
- package/src/instrumentations/session/sessionManager/persistentSessionRecord.ts +78 -0
- package/src/instrumentations/session/sessionManager/sampling.test.ts +1 -1
- package/src/instrumentations/session/sessionManager/sessionConstants.ts +1 -1
- package/src/instrumentations/session/sessionManager/sessionManagerUtils.test.ts +256 -18
- package/src/instrumentations/session/sessionManager/sessionManagerUtils.ts +180 -39
- package/src/instrumentations/session/sessionManager/types.ts +8 -0
- package/src/instrumentations/session/sessionManagerInstance.test.ts +65 -0
- package/src/instrumentations/session/sessionProcess.test.ts +136 -0
- package/src/instrumentations/session/sessionProcess.ts +114 -0
- package/src/instrumentations/session/startNewSession.test.ts +337 -0
- package/src/instrumentations/startup/index.ts +2 -6
- package/src/navigation/utils.ts +3 -1
- package/src/transports/fetch/index.ts +6 -1
- package/src/transports/fetch/transport.test.ts +86 -2
- package/src/transports/fetch/transport.ts +38 -16
- package/src/transports/fetch/types.ts +7 -0
- package/src/transports/offline/ConnectivityService.ts +1 -1
- package/src/transports/offline/OfflineCache.ts +2 -2
- package/src/transports/offline/transport.ts +3 -4
- package/src/userPersistence/UserPersistence.ts +1 -2
- package/dist/cjs/utils/throttle.js +0 -42
- package/dist/cjs/utils/throttle.js.map +0 -1
- package/dist/esm/utils/throttle.js +0 -34
- package/dist/esm/utils/throttle.js.map +0 -1
- package/dist/types/utils/throttle.d.ts +0 -9
- package/src/utils/throttle.test.ts +0 -141
- package/src/utils/throttle.ts +0 -34
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/config/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Config } from '@grafana/faro-core';\n\nimport type { ANRInstrumentationOptions } from '../instrumentations/anr';\nimport type { FrameMonitoringOptions } from '../instrumentations/frameMonitoring';\nimport type { PreloadedMobileMeta, SessionAttributes } from '../instrumentations/session/sessionAttributes';\n\nimport type { Sampling } from './sampling';\n\n/**\n * React Native session tracking config.\n * Extends Config['sessionTracking'] with sampling
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/config/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Config } from '@grafana/faro-core';\n\nimport type { ANRInstrumentationOptions } from '../instrumentations/anr';\nimport type { FrameMonitoringOptions } from '../instrumentations/frameMonitoring';\nimport type { PreloadedMobileMeta, SessionAttributes } from '../instrumentations/session/sessionAttributes';\n\nimport type { Sampling } from './sampling';\n\n/**\n * React Native session tracking config.\n * Extends Config['sessionTracking'] with sampling and RN-specific props.\n * Excludes samplingRate and sampler in favor of sampling.\n *\n * Persistence defaults to true and stores a minimal, versioned record with\n * [react-native-mmkv](https://github.com/mrousavy/react-native-mmkv) (synchronous).\n * Add `react-native-mmkv` to your app and rebuild native projects, or set\n * `persistent` to false to use in-memory sessions.\n */\nexport type ReactNativeSessionTrackingConfig = Omit<\n NonNullable<Config['sessionTracking']>,\n 'samplingRate' | 'sampler'\n> & {\n /**\n * Session sampling. Use {@link SamplingRate} for fixed rate or\n * {@link SamplingFunction} for dynamic sampling.\n */\n sampling?: Sampling;\n};\n\n/**\n * Flags for enabling optional built-in transports.\n * FetchTransport is always instantiated when url is provided.\n */\nexport interface EnableTransportsConfig {\n /** Enable OfflineTransport for caching when offline (default: false) */\n offline?: boolean;\n /** Enable ConsoleTransport to log telemetry to Metro console for debugging (default: false) */\n console?: boolean;\n}\n\n/** RN-specific config: overrides + new props. Omit faro-core props we replace with RN equivalents. */\ntype ReactNativeConfigOverrides = {\n /** Application metadata (required) */\n app: Config['app'];\n sessionTracking?: ReactNativeSessionTrackingConfig;\n url?: string;\n apiKey?: string;\n enableTransports?: EnableTransportsConfig;\n /**\n * Which HTTP instrumentations to enable. When tracing is disabled, these control\n * HttpInstrumentation (fetch) and XHRInstrumentation (xhr). Default: both true.\n */\n enableHttpInstrumentation?: {\n /** HttpInstrumentation - patches fetch API (default: true) */\n fetch?: boolean;\n /** XHRInstrumentation - patches XMLHttpRequest (default: true) */\n xhr?: boolean;\n };\n enableTracing?: boolean;\n /** Passed to TracingInstrumentation. See TracingInstrumentationOptions in @grafana/faro-react-native-tracing. */\n tracingOptions?: Record<string, unknown>;\n cpuUsageVitals?: boolean;\n memoryUsageVitals?: boolean;\n refreshRateVitals?: boolean;\n fetchVitalsInterval?: number;\n frameMonitoringOptions?: FrameMonitoringOptions;\n enableErrorReporting?: boolean;\n enableCrashReporting?: boolean;\n anrTracking?: boolean;\n anrOptions?: ANRInstrumentationOptions;\n enableConsoleCapture?: boolean;\n consoleCaptureOptions?: Config['consoleInstrumentation'];\n enableUserActions?: boolean;\n userActionsOptions?: Config['userActionsInstrumentation'];\n /**\n * Hermes / minified release stack lines omit a file path. This must match the Metro plugin\n * source map top-level `file` (default `bundle.js`, or your `sourceMapFile` option there).\n */\n releaseBundleFilename?: string;\n};\n\n/**\n * React Native config: Config (omit replaced props) & overrides.\n * Omit: sessionTracking, consoleInstrumentation, userActionsInstrumentation.\n * instrumentations and transports inherited from Config for extras (built-ins come from flags).\n */\nexport type ReactNativeConfig = Partial<\n Omit<Config, 'sessionTracking' | 'consoleInstrumentation' | 'userActionsInstrumentation'>\n> &\n ReactNativeConfigOverrides;\n\n/**\n * Internal full config returned by `makeRNConfig`.\n * Extends faro-core `Config` with RN-specific fields that instrumentations need at init time.\n */\nexport type ReactNativeFullConfig = Config & {\n preloadedMobileMeta?: PreloadedMobileMeta['meta'];\n preloadedSessionDeviceAttributes?: SessionAttributes;\n};\n"]}
|
|
@@ -18,8 +18,7 @@ const DEFAULT_STORAGE_KEY = 'faro_enable_data_collection';
|
|
|
18
18
|
* Controls whether telemetry data is collected and sent.
|
|
19
19
|
* The setting is persisted to AsyncStorage so it survives app restarts.
|
|
20
20
|
*
|
|
21
|
-
*
|
|
22
|
-
* - Uses AsyncStorage for persistence (matching Flutter's SharedPreferences)
|
|
21
|
+
* Uses AsyncStorage for persisting data collection policy state.
|
|
23
22
|
* - Provides enable/disable methods
|
|
24
23
|
* - Initializes from persisted value or default
|
|
25
24
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataCollectionPolicy.js","sourceRoot":"","sources":["../../../src/dataCollection/DataCollectionPolicy.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,YAAY,MAAM,2CAA2C,CAAC;AAIrE;;GAEG;AACH,MAAM,mBAAmB,GAAG,6BAA6B,CAAC;AAE1D
|
|
1
|
+
{"version":3,"file":"DataCollectionPolicy.js","sourceRoot":"","sources":["../../../src/dataCollection/DataCollectionPolicy.ts"],"names":[],"mappings":"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","sourcesContent":["import AsyncStorage from '@react-native-async-storage/async-storage';\n\nimport type { DataCollectionPolicy, DataCollectionPolicyOptions } from './types';\n\n/**\n * Default storage key for the data collection policy.\n */\nconst DEFAULT_STORAGE_KEY = 'faro_enable_data_collection';\n\n/**\n * DataCollectionPolicy implementation using AsyncStorage.\n *\n * Controls whether telemetry data is collected and sent.\n * The setting is persisted to AsyncStorage so it survives app restarts.\n *\n * Uses AsyncStorage for persisting data collection policy state.\n * - Provides enable/disable methods\n * - Initializes from persisted value or default\n *\n * @example\n * ```typescript\n * import { createDataCollectionPolicy } from '@grafana/faro-react-native';\n *\n * // Create and initialize the policy\n * const policy = await createDataCollectionPolicy();\n *\n * // Check if enabled\n * if (policy.isEnabled) {\n * // Data collection is allowed\n * }\n *\n * // User opts out\n * await policy.disable();\n *\n * // User opts back in\n * await policy.enable();\n * ```\n */\nexport class AsyncStorageDataCollectionPolicy implements DataCollectionPolicy {\n private _isEnabled: boolean;\n private readonly storageKey: string;\n private readonly subscribers: Set<(isEnabled: boolean) => void> = new Set();\n\n private constructor(options: DataCollectionPolicyOptions = {}) {\n this.storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;\n this._isEnabled = options.defaultEnabled ?? true;\n }\n\n /**\n * Create and initialize a DataCollectionPolicy.\n *\n * This async factory method loads the persisted value from AsyncStorage.\n */\n static async create(options: DataCollectionPolicyOptions = {}): Promise<AsyncStorageDataCollectionPolicy> {\n const policy = new AsyncStorageDataCollectionPolicy(options);\n await policy.initialize();\n return policy;\n }\n\n get isEnabled(): boolean {\n return this._isEnabled;\n }\n\n async enable(): Promise<void> {\n this._isEnabled = true;\n await this.persistSetting();\n this.notifySubscribers();\n }\n\n async disable(): Promise<void> {\n this._isEnabled = false;\n await this.persistSetting();\n this.notifySubscribers();\n }\n\n subscribe(callback: (isEnabled: boolean) => void): () => void {\n this.subscribers.add(callback);\n // Immediately notify subscriber of current state\n callback(this._isEnabled);\n\n return () => {\n this.subscribers.delete(callback);\n };\n }\n\n private async initialize(): Promise<void> {\n try {\n const storedValue = await AsyncStorage.getItem(this.storageKey);\n if (storedValue !== null) {\n this._isEnabled = storedValue === 'true';\n }\n } catch {\n // If loading fails, use default value\n }\n }\n\n private async persistSetting(): Promise<void> {\n try {\n await AsyncStorage.setItem(this.storageKey, String(this._isEnabled));\n } catch {\n // If persisting fails, log but don't throw\n }\n }\n\n private notifySubscribers(): void {\n this.subscribers.forEach((subscriber) => {\n try {\n subscriber(this._isEnabled);\n } catch {\n // Ignore subscriber errors\n }\n });\n }\n}\n\n/**\n * Factory function to create a DataCollectionPolicy.\n *\n * @example\n * ```typescript\n * const policy = await createDataCollectionPolicy();\n * ```\n */\nexport async function createDataCollectionPolicy(\n options: DataCollectionPolicyOptions = {}\n): Promise<DataCollectionPolicy> {\n return AsyncStorageDataCollectionPolicy.create(options);\n}\n\n/**\n * Global data collection policy instance.\n * Must be initialized before use.\n */\nlet globalPolicy: DataCollectionPolicy | null = null;\n\n/**\n * Initialize the global data collection policy.\n *\n * This should be called early in app initialization, before initializeFaro().\n *\n * @example\n * ```typescript\n * import { initializeDataCollectionPolicy, getDataCollectionPolicy } from '@grafana/faro-react-native';\n *\n * // Early in app startup\n * await initializeDataCollectionPolicy();\n *\n * // Later, check if collection is enabled\n * const policy = getDataCollectionPolicy();\n * if (policy?.isEnabled) {\n * // Initialize Faro\n * }\n * ```\n */\nexport async function initializeDataCollectionPolicy(\n options: DataCollectionPolicyOptions = {}\n): Promise<DataCollectionPolicy> {\n globalPolicy = await createDataCollectionPolicy(options);\n return globalPolicy;\n}\n\n/**\n * Get the global data collection policy.\n *\n * Returns null if not initialized.\n */\nexport function getDataCollectionPolicy(): DataCollectionPolicy | null {\n return globalPolicy;\n}\n\n/**\n * Set a custom data collection policy.\n *\n * Useful for testing or custom implementations.\n */\nexport function setDataCollectionPolicy(policy: DataCollectionPolicy | null): void {\n globalPolicy = policy;\n}\n"]}
|
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
* NPM package identity for this build. Generated by scripts/sync-faro-rn-package-meta.mjs - do not edit.
|
|
3
3
|
*/
|
|
4
4
|
export const FARO_REACT_NATIVE_NPM_NAME = '@grafana/faro-react-native';
|
|
5
|
-
export const FARO_REACT_NATIVE_NPM_VERSION = '1.
|
|
5
|
+
export const FARO_REACT_NATIVE_NPM_VERSION = '1.4.0';
|
|
6
6
|
//# sourceMappingURL=faroRNPackageMeta.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"faroRNPackageMeta.js","sourceRoot":"","sources":["../../../src/generated/faroRNPackageMeta.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,4BAAqC,CAAC;AAChF,MAAM,CAAC,MAAM,6BAA6B,GAAG,OAAgB,CAAC","sourcesContent":["/**\n * NPM package identity for this build. Generated by scripts/sync-faro-rn-package-meta.mjs - do not edit.\n */\nexport const FARO_REACT_NATIVE_NPM_NAME = '@grafana/faro-react-native' as const;\nexport const FARO_REACT_NATIVE_NPM_VERSION = '1.
|
|
1
|
+
{"version":3,"file":"faroRNPackageMeta.js","sourceRoot":"","sources":["../../../src/generated/faroRNPackageMeta.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,4BAAqC,CAAC;AAChF,MAAM,CAAC,MAAM,6BAA6B,GAAG,OAAgB,CAAC","sourcesContent":["/**\n * NPM package identity for this build. Generated by scripts/sync-faro-rn-package-meta.mjs - do not edit.\n */\nexport const FARO_REACT_NATIVE_NPM_NAME = '@grafana/faro-react-native' as const;\nexport const FARO_REACT_NATIVE_NPM_VERSION = '1.4.0' as const;\n"]}
|
package/dist/esm/index.js
CHANGED
|
@@ -4,14 +4,16 @@ import { applyPerformanceObserverPolyfill } from './util/performanceObserverPoly
|
|
|
4
4
|
applyPerformanceObserverPolyfill();
|
|
5
5
|
export { initializeFaro } from './initialize';
|
|
6
6
|
export { faro } from '@grafana/faro-core';
|
|
7
|
-
// Export sampling
|
|
7
|
+
// Export sampling
|
|
8
8
|
export { SamplingFunction, SamplingRate } from './config/sampling';
|
|
9
9
|
// Export instrumentation helpers
|
|
10
10
|
export { getRNInstrumentations } from './config/getRNInstrumentations';
|
|
11
11
|
// Export instrumentations
|
|
12
12
|
export { ErrorMechanism, ErrorsInstrumentation } from './instrumentations/errors';
|
|
13
13
|
export { ConsoleInstrumentation } from './instrumentations/console';
|
|
14
|
-
export { SessionInstrumentation } from './instrumentations/session';
|
|
14
|
+
export { startNewSession, SessionInstrumentation } from './instrumentations/session';
|
|
15
|
+
export { FaroSessionActivityBoundary, } from './instrumentations/session/FaroSessionActivityBoundary';
|
|
16
|
+
export { notifySessionActivity } from './instrumentations/session/directSessionActivity';
|
|
15
17
|
export { getSessionAttributes, loadMobileMetaForInit, loadSessionDeviceAttributesForInit, minimalSessionDeviceAttributes, } from './instrumentations/session/sessionAttributes';
|
|
16
18
|
export { ViewInstrumentation } from './instrumentations/view';
|
|
17
19
|
export { AppStateInstrumentation } from './instrumentations/appState';
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,mFAAmF;AACnF,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACtF,gCAAgC,EAAE,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAK1C,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Main entry point for @grafana/faro-react-native\n// Apply PerformanceObserver polyfill first to prevent iOS bad_variant_access crash\nimport { applyPerformanceObserverPolyfill } from './util/performanceObserverPolyfill';\napplyPerformanceObserverPolyfill();\nexport { initializeFaro } from './initialize';\nexport { faro } from '@grafana/faro-core';\n\n// Export types\nexport type { EnableTransportsConfig, ReactNativeConfig, ReactNativeSessionTrackingConfig } from './config/types';\n\n// Export sampling\nexport { SamplingFunction, SamplingRate, type Sampling, type SamplingContext } from './config/sampling';\n\n// Export instrumentation helpers\nexport { getRNInstrumentations } from './config/getRNInstrumentations';\n\n// Export instrumentations\nexport { ErrorMechanism, ErrorsInstrumentation } from './instrumentations/errors';\nexport type { ErrorMechanismType, ErrorsInstrumentationOptions } from './instrumentations/errors';\nexport { ConsoleInstrumentation } from './instrumentations/console';\nexport { startNewSession, SessionInstrumentation } from './instrumentations/session';\nexport {\n FaroSessionActivityBoundary,\n type FaroSessionActivityBoundaryProps,\n} from './instrumentations/session/FaroSessionActivityBoundary';\nexport { notifySessionActivity } from './instrumentations/session/directSessionActivity';\nexport {\n getSessionAttributes,\n loadMobileMetaForInit,\n loadSessionDeviceAttributesForInit,\n minimalSessionDeviceAttributes,\n} from './instrumentations/session/sessionAttributes';\nexport type { PreloadedMobileMeta, SessionAttributes } from './instrumentations/session/sessionAttributes';\nexport { ViewInstrumentation } from './instrumentations/view';\nexport { AppStateInstrumentation } from './instrumentations/appState';\nexport { UserActionInstrumentation } from './instrumentations/userActions';\nexport { HttpInstrumentation } from './instrumentations/http';\nexport { XHRInstrumentation } from './instrumentations/xhr';\nexport { PerformanceInstrumentation } from './instrumentations/performance';\nexport type { PerformanceInstrumentationOptions } from './instrumentations/performance/types';\nexport { StartupInstrumentation } from './instrumentations/startup';\nexport type { StartupInstrumentationOptions } from './instrumentations/startup/types';\nexport { FrameMonitoringInstrumentation } from './instrumentations/frameMonitoring';\nexport type { FrameMonitoringOptions } from './instrumentations/frameMonitoring';\nexport { ANRInstrumentation } from './instrumentations/anr';\nexport type { ANRInstrumentationOptions } from './instrumentations/anr';\nexport { CrashReportingInstrumentation } from './instrumentations/crashReporting';\nexport type { CrashReportingOptions } from './instrumentations/crashReporting';\n\n// Export console utilities\nexport { reactNativeLogArgsSerializer } from './instrumentations/console/utils';\n\n// Export user action helpers\nexport {\n withFaroUserAction,\n trackUserAction,\n type WithFaroUserActionProps,\n} from './instrumentations/userActions/withFaroUserAction';\nexport { notifyHttpRequestEnd, notifyHttpRequestStart } from './instrumentations/userActions/httpRequestMonitor';\nexport type { HttpRequestMessagePayload } from './instrumentations/userActions/httpRequestMonitor';\n\n// Export error boundary\nexport { FaroErrorBoundary } from './errorBoundary/FaroErrorBoundary';\nexport { withFaroErrorBoundary } from './errorBoundary/withFaroErrorBoundary';\nexport type {\n FaroErrorBoundaryProps,\n FaroErrorBoundaryState,\n FaroErrorBoundaryFallbackRender,\n} from './errorBoundary/types';\n\n// Export metas\nexport { getPageMeta } from './metas/page';\nexport { getScreenMeta } from './metas/screen';\nexport { getSdkMeta } from './metas/sdk';\n\n// Export transports\nexport { FetchTransport } from './transports/fetch';\nexport type { FetchTransportSendOutcome, FetchTransportSendResult } from './transports/fetch';\nexport { ConsoleTransport } from './transports/console';\nexport type { ConsoleTransportOptions } from './transports/console';\nexport { OfflineTransport } from './transports/offline';\nexport type { OfflineTransportOptions } from './transports/offline';\n\n// Export data collection policy\nexport {\n createDataCollectionPolicy,\n getDataCollectionPolicy,\n initializeDataCollectionPolicy,\n setDataCollectionPolicy,\n} from './dataCollection';\nexport type { DataCollectionPolicy, DataCollectionPolicyOptions } from './dataCollection';\n\n// Export user persistence\nexport {\n createUserPersistence,\n getUserPersistence,\n initializeUserPersistence,\n setUserPersistence,\n} from './userPersistence';\nexport type { UserPersistence, UserPersistenceOptions } from './userPersistence';\n\n// Export navigation utilities\nexport { ReactNativeNavigationIntegration } from './navigation/v6';\nexport {\n useFaroNavigation,\n createNavigationStateChangeHandler,\n getCurrentRoute,\n getRouteName,\n onNavigationStateChange,\n} from './navigation';\nexport type { ReactNavigationDependencies, ReactNavigationConfig } from './navigation/types';\n\n// Re-export core types and enums that consumers will need\nexport type {\n Config,\n Faro,\n Instrumentation,\n Meta,\n Transport,\n PushErrorOptions,\n PushEventOptions,\n PushLogOptions,\n PushMeasurementOptions,\n} from '@grafana/faro-core';\n\n// Export LogLevel and InternalLoggerLevel from our local copy (avoid bundling faro-core's web code)\nexport { LogLevel, InternalLoggerLevel, allLogLevels, defaultLogLevel } from './internalLogger';\n"]}
|
|
@@ -64,7 +64,12 @@ export class ANRInstrumentation extends BaseInstrumentation {
|
|
|
64
64
|
void this.drainAllAnrSources(nativeModule);
|
|
65
65
|
this.startNativeTracking(nativeModule);
|
|
66
66
|
const emitter = new NativeEventEmitter(nativeModule);
|
|
67
|
-
this.anrEventSubscription = emitter.addListener('onANRDetected', (
|
|
67
|
+
this.anrEventSubscription = emitter.addListener('onANRDetected', (...args) => {
|
|
68
|
+
const [anrJson] = args;
|
|
69
|
+
if (typeof anrJson !== 'string') {
|
|
70
|
+
this.logWarn('Ignoring onANRDetected event without a string payload');
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
68
73
|
void this.handleLiveAnrEvent(nativeModule, anrJson);
|
|
69
74
|
});
|
|
70
75
|
void this.checkANRStatus(nativeModule);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentation.js","sourceRoot":"","sources":["../../../../src/instrumentations/anr/instrumentation.ts"],"names":[],"mappings":"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","sourcesContent":["import { NativeEventEmitter, NativeModules, Platform } from 'react-native';\n\nimport { BaseInstrumentation, VERSION } from '@grafana/faro-core';\n\nimport { normalizeJavaStackTraceForRetrace, parseAndroidCrashTrace } from '../crashReporting/android';\nimport { ErrorMechanism } from '../errors/const';\n\nimport { isInvalidAnrCaptureStack } from './anrStack';\nimport type { ANREvent, ANRInstrumentationOptions } from './types';\n\n/**\n * Default timeout for ANR detection (5 seconds, matching Android's threshold)\n */\nconst DEFAULT_TIMEOUT = 5000;\n\n/**\n * Default polling interval for ANR status. Kept short so debug ANRs surface without\n * waiting a full minute; native also emits onANRDetected for immediate delivery.\n */\nconst DEFAULT_POLLING_INTERVAL = 10000;\n\n/** Aligns with native FaroAnrCache.MAX_TIMESTAMP_DELTA_MS */\nconst TIMESTAMP_DEDUP_WINDOW_MS = 10_000;\n\n/** ApplicationExitInfo ANR traces (Android 11 / API 30+). */\nconst APP_EXIT_INFO_MIN_SDK = 30;\n\n/**\n * ANR (Application Not Responding) Detection Instrumentation.\n *\n * On Android 11+, historical ANRs are read from ApplicationExitInfo (Sentry AnrV2\n * style) on the next launch. ANRTracker remains a pre-API-30 fallback and a\n * persistence backup when the OS trace stream is empty.\n *\n * ANRs stay out of CrashReportingInstrumentation so they are not replayed as\n * generic previous-session `crash` rows with empty messages.\n */\nexport class ANRInstrumentation extends BaseInstrumentation {\n readonly name = '@grafana/faro-react-native:instrumentation-anr';\n readonly version = VERSION;\n\n private readonly options: Required<ANRInstrumentationOptions>;\n private pollingIntervalId: ReturnType<typeof setInterval> | null = null;\n private anrEventSubscription: ReturnType<NativeEventEmitter['addListener']> | null = null;\n private readonly reportedAnrTimestamps = new Set<number>();\n private readonly preferAppExitInfoAnr: boolean;\n\n constructor(options: ANRInstrumentationOptions = {}) {\n super();\n this.options = {\n timeout: options.timeout ?? DEFAULT_TIMEOUT,\n pollingInterval: options.pollingInterval ?? DEFAULT_POLLING_INTERVAL,\n };\n this.preferAppExitInfoAnr = Platform.OS === 'android' && Number(Platform.Version) >= APP_EXIT_INFO_MIN_SDK;\n }\n\n initialize(): void {\n if (Platform.OS !== 'android') {\n this.logDebug('ANR detection is only available on Android');\n return;\n }\n\n const nativeModule = this.getNativeModule();\n if (!nativeModule) {\n this.logWarn('Native module not available for ANR detection');\n return;\n }\n\n this.logDebug('Initializing ANR detection instrumentation');\n\n void this.drainAllAnrSources(nativeModule);\n\n this.startNativeTracking(nativeModule);\n\n const emitter = new NativeEventEmitter(nativeModule);\n this.anrEventSubscription = emitter.addListener('onANRDetected', (anrJson: string) => {\n void this.handleLiveAnrEvent(nativeModule, anrJson);\n });\n\n void this.checkANRStatus(nativeModule);\n this.pollingIntervalId = setInterval(() => {\n void this.checkANRStatus(nativeModule);\n }, this.options.pollingInterval);\n }\n\n private getNativeModule(): typeof NativeModules.FaroReactNativeModule | null {\n const { FaroReactNativeModule } = NativeModules;\n\n if (!FaroReactNativeModule) {\n return null;\n }\n\n return FaroReactNativeModule;\n }\n\n private startNativeTracking(nativeModule: typeof NativeModules.FaroReactNativeModule): void {\n try {\n if (typeof nativeModule.startANRTracking === 'function') {\n nativeModule.startANRTracking({\n timeout: this.options.timeout,\n });\n this.logDebug('Started native ANR tracking');\n }\n } catch (error) {\n this.logError('Failed to start native ANR tracking', error);\n }\n }\n\n private async drainAllAnrSources(nativeModule: typeof NativeModules.FaroReactNativeModule): Promise<void> {\n await this.drainHistoricalAnrs(nativeModule);\n await this.drainPendingANRs(nativeModule);\n }\n\n private async drainHistoricalAnrs(nativeModule: typeof NativeModules.FaroReactNativeModule): Promise<void> {\n if (typeof nativeModule.getHistoricalAnrReports !== 'function') {\n return;\n }\n\n try {\n const anrList = (await nativeModule.getHistoricalAnrReports()) as string[] | null;\n if (!anrList?.length) {\n return;\n }\n\n const ackTimestamps: number[] = [];\n let reportedCount = 0;\n\n for (const anrJson of anrList) {\n try {\n const anr = JSON.parse(anrJson) as ANREvent;\n if (this.reportANRIfNew(anr)) {\n reportedCount += 1;\n }\n ackTimestamps.push(anr.timestamp);\n await this.acknowledgeNearbyPendingAnrs(nativeModule, anr.timestamp);\n } catch (error) {\n this.logError('Failed to parse historical ANR report', error);\n }\n }\n\n if (reportedCount > 0) {\n this.api.pushMeasurement(\n {\n type: 'anr',\n values: { anr_count: reportedCount },\n },\n { skipDedupe: true }\n );\n this.logDebug(`Reported ${reportedCount} historical ANR event(s) from ApplicationExitInfo`);\n }\n } catch (error) {\n this.logError('Failed to drain historical ANRs', error);\n }\n }\n\n private async drainPendingANRs(nativeModule: typeof NativeModules.FaroReactNativeModule): Promise<void> {\n const anrList = await this.fetchPendingANRs(nativeModule);\n if (!anrList?.length) {\n return;\n }\n\n await this.reportAndAcknowledgePendingANRs(nativeModule, anrList);\n this.logDebug(`Processed ${anrList.length} persisted ANR event(s) from tracker cache`);\n }\n\n private async handleLiveAnrEvent(\n nativeModule: typeof NativeModules.FaroReactNativeModule,\n anrJson: string\n ): Promise<void> {\n try {\n const anr = JSON.parse(anrJson) as ANREvent;\n\n if (this.preferAppExitInfoAnr) {\n // Process death + ApplicationExitInfo on next launch delivers the main-thread dump.\n this.logDebug('Deferring live ANR to ApplicationExitInfo on next launch');\n return;\n }\n\n if (!this.shouldReportTrackerAnr(anr)) {\n await this.acknowledgeANRs(nativeModule, [anr.timestamp]);\n return;\n }\n\n if (this.reportANRIfNew(anr)) {\n this.api.pushMeasurement(\n {\n type: 'anr',\n values: { anr_count: 1 },\n },\n { skipDedupe: true }\n );\n }\n await this.acknowledgeANRs(nativeModule, [anr.timestamp]);\n } catch (error) {\n this.logError('Failed to parse native ANR event', error);\n }\n }\n\n private async fetchPendingANRs(nativeModule: typeof NativeModules.FaroReactNativeModule): Promise<string[] | null> {\n try {\n if (typeof nativeModule.getPendingANRs === 'function') {\n return (await nativeModule.getPendingANRs()) as string[] | null;\n }\n\n if (typeof nativeModule.getANRStatus === 'function') {\n return (await nativeModule.getANRStatus()) as string[] | null;\n }\n } catch (error) {\n this.logError('Failed to fetch pending ANRs', error);\n }\n\n return null;\n }\n\n private async acknowledgeANRs(\n nativeModule: typeof NativeModules.FaroReactNativeModule,\n timestamps: number[]\n ): Promise<void> {\n if (!timestamps.length || typeof nativeModule.acknowledgeANRs !== 'function') {\n return;\n }\n\n try {\n await nativeModule.acknowledgeANRs(timestamps);\n } catch (error) {\n this.logError('Failed to acknowledge ANRs', error);\n }\n }\n\n private async acknowledgeNearbyPendingAnrs(\n nativeModule: typeof NativeModules.FaroReactNativeModule,\n exitTimestamp: number\n ): Promise<void> {\n const pending = await this.fetchPendingANRs(nativeModule);\n if (!pending?.length) {\n return;\n }\n\n const ackTimestamps: number[] = [];\n for (const anrJson of pending) {\n try {\n const anr = JSON.parse(anrJson) as ANREvent;\n if (this.isNearbyTimestamp(anr.timestamp, exitTimestamp)) {\n ackTimestamps.push(anr.timestamp);\n }\n } catch {\n // ignore malformed cache entries\n }\n }\n\n if (ackTimestamps.length > 0) {\n await this.acknowledgeANRs(nativeModule, ackTimestamps);\n }\n }\n\n private async reportAndAcknowledgePendingANRs(\n nativeModule: typeof NativeModules.FaroReactNativeModule,\n anrList: string[]\n ): Promise<void> {\n const ackTimestamps: number[] = [];\n let reportedCount = 0;\n\n for (const anrJson of anrList) {\n try {\n const anr = JSON.parse(anrJson) as ANREvent;\n\n if (this.shouldReportTrackerAnr(anr) && this.reportANRIfNew(anr)) {\n reportedCount += 1;\n }\n\n ackTimestamps.push(anr.timestamp);\n } catch {\n const error = new Error('ANR (Application Not Responding)');\n error.stack = undefined;\n this.api.pushError(error, {\n context: {\n mechanism: ErrorMechanism.ANR,\n raw: anrJson,\n },\n fatal: true,\n type: 'ANR',\n });\n }\n }\n\n if (reportedCount > 0) {\n this.api.pushMeasurement(\n {\n type: 'anr',\n values: { anr_count: reportedCount },\n },\n { skipDedupe: true }\n );\n }\n\n if (ackTimestamps.length > 0) {\n await this.acknowledgeANRs(nativeModule, ackTimestamps);\n }\n }\n\n private shouldReportTrackerAnr(anr: ANREvent): boolean {\n if (this.isNearbyReportedTimestamp(anr.timestamp)) {\n return false;\n }\n\n if (isInvalidAnrCaptureStack(anr.stacktrace)) {\n return false;\n }\n\n // On API 30+, ApplicationExitInfo is preferred on launch; tracker pending entries\n // are reported only when historical did not already cover the same incident.\n return true;\n }\n\n private reportANRIfNew(anr: ANREvent): boolean {\n if (this.isNearbyReportedTimestamp(anr.timestamp)) {\n return false;\n }\n\n if (isInvalidAnrCaptureStack(anr.stacktrace)) {\n return false;\n }\n\n this.rememberReportedTimestamp(anr.timestamp);\n this.reportANR(anr);\n return true;\n }\n\n private rememberReportedTimestamp(timestamp: number): void {\n this.reportedAnrTimestamps.add(timestamp);\n }\n\n private isNearbyReportedTimestamp(timestamp: number): boolean {\n for (const reported of Array.from(this.reportedAnrTimestamps)) {\n if (this.isNearbyTimestamp(timestamp, reported)) {\n return true;\n }\n }\n return false;\n }\n\n private isNearbyTimestamp(a: number, b: number): boolean {\n if (a <= 0 || b <= 0) {\n return false;\n }\n return Math.abs(a - b) <= TIMESTAMP_DEDUP_WINDOW_MS;\n }\n\n private reportANR(anr: ANREvent): void {\n const rawStacktrace = anr.stacktrace?.trim() ?? '';\n const traceForRetrace = rawStacktrace ? normalizeJavaStackTraceForRetrace(rawStacktrace) : '';\n const parsed = traceForRetrace ? parseAndroidCrashTrace(traceForRetrace) : null;\n\n const message = anr.description?.trim() || 'ANR (Application Not Responding)';\n const error = new Error(message);\n error.stack = undefined;\n\n const context: Record<string, string> = {\n duration: String(anr.duration),\n mechanism: ErrorMechanism.ANR,\n timestamp: String(anr.timestamp),\n };\n if (anr.source) {\n context['source'] = anr.source;\n }\n if (traceForRetrace) {\n context['stacktrace'] = traceForRetrace;\n }\n\n const stackFrames = parsed?.frames ?? [];\n if (!stackFrames.length && rawStacktrace) {\n this.logWarn('ANR main-thread stack present but no Java/Kotlin frames parsed');\n }\n\n this.api.pushError(error, {\n type: 'ANR',\n context,\n fatal: true,\n ...(stackFrames.length ? { stackFrames } : {}),\n });\n }\n\n private async checkANRStatus(nativeModule: typeof NativeModules.FaroReactNativeModule): Promise<void> {\n try {\n const anrList = await this.fetchPendingANRs(nativeModule);\n\n if (anrList && anrList.length > 0) {\n await this.reportAndAcknowledgePendingANRs(nativeModule, anrList);\n this.logDebug(`Polled ${anrList.length} ANR event(s) from pending cache`);\n }\n } catch (error) {\n this.logError('Failed to check ANR status', error);\n }\n }\n\n unpatch(): void {\n if (this.pollingIntervalId !== null) {\n clearInterval(this.pollingIntervalId);\n this.pollingIntervalId = null;\n }\n\n this.anrEventSubscription?.remove();\n this.anrEventSubscription = null;\n this.reportedAnrTimestamps.clear();\n\n if (Platform.OS === 'android') {\n const nativeModule = this.getNativeModule();\n if (nativeModule && typeof nativeModule.stopANRTracking === 'function') {\n try {\n nativeModule.stopANRTracking();\n } catch (error) {\n this.logError('Failed to stop native ANR tracking', error);\n }\n }\n }\n\n this.logDebug('ANR instrumentation stopped');\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"instrumentation.js","sourceRoot":"","sources":["../../../../src/instrumentations/anr/instrumentation.ts"],"names":[],"mappings":"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","sourcesContent":["import { NativeEventEmitter, NativeModules, Platform } from 'react-native';\n\nimport { BaseInstrumentation, VERSION } from '@grafana/faro-core';\n\nimport { normalizeJavaStackTraceForRetrace, parseAndroidCrashTrace } from '../crashReporting/android';\nimport { ErrorMechanism } from '../errors/const';\n\nimport { isInvalidAnrCaptureStack } from './anrStack';\nimport type { ANREvent, ANRInstrumentationOptions } from './types';\n\n/**\n * Default timeout for ANR detection (5 seconds, matching Android's threshold)\n */\nconst DEFAULT_TIMEOUT = 5000;\n\n/**\n * Default polling interval for ANR status. Kept short so debug ANRs surface without\n * waiting a full minute; native also emits onANRDetected for immediate delivery.\n */\nconst DEFAULT_POLLING_INTERVAL = 10000;\n\n/** Aligns with native FaroAnrCache.MAX_TIMESTAMP_DELTA_MS */\nconst TIMESTAMP_DEDUP_WINDOW_MS = 10_000;\n\n/** ApplicationExitInfo ANR traces (Android 11 / API 30+). */\nconst APP_EXIT_INFO_MIN_SDK = 30;\n\n/**\n * ANR (Application Not Responding) Detection Instrumentation.\n *\n * On Android 11+, historical ANRs are read from ApplicationExitInfo (Sentry AnrV2\n * style) on the next launch. ANRTracker remains a pre-API-30 fallback and a\n * persistence backup when the OS trace stream is empty.\n *\n * ANRs stay out of CrashReportingInstrumentation so they are not replayed as\n * generic previous-session `crash` rows with empty messages.\n */\nexport class ANRInstrumentation extends BaseInstrumentation {\n readonly name = '@grafana/faro-react-native:instrumentation-anr';\n readonly version = VERSION;\n\n private readonly options: Required<ANRInstrumentationOptions>;\n private pollingIntervalId: ReturnType<typeof setInterval> | null = null;\n private anrEventSubscription: ReturnType<NativeEventEmitter['addListener']> | null = null;\n private readonly reportedAnrTimestamps = new Set<number>();\n private readonly preferAppExitInfoAnr: boolean;\n\n constructor(options: ANRInstrumentationOptions = {}) {\n super();\n this.options = {\n timeout: options.timeout ?? DEFAULT_TIMEOUT,\n pollingInterval: options.pollingInterval ?? DEFAULT_POLLING_INTERVAL,\n };\n this.preferAppExitInfoAnr = Platform.OS === 'android' && Number(Platform.Version) >= APP_EXIT_INFO_MIN_SDK;\n }\n\n initialize(): void {\n if (Platform.OS !== 'android') {\n this.logDebug('ANR detection is only available on Android');\n return;\n }\n\n const nativeModule = this.getNativeModule();\n if (!nativeModule) {\n this.logWarn('Native module not available for ANR detection');\n return;\n }\n\n this.logDebug('Initializing ANR detection instrumentation');\n\n void this.drainAllAnrSources(nativeModule);\n\n this.startNativeTracking(nativeModule);\n\n const emitter = new NativeEventEmitter(nativeModule);\n this.anrEventSubscription = emitter.addListener('onANRDetected', (...args: readonly Object[]) => {\n const [anrJson] = args;\n\n if (typeof anrJson !== 'string') {\n this.logWarn('Ignoring onANRDetected event without a string payload');\n return;\n }\n\n void this.handleLiveAnrEvent(nativeModule, anrJson);\n });\n\n void this.checkANRStatus(nativeModule);\n this.pollingIntervalId = setInterval(() => {\n void this.checkANRStatus(nativeModule);\n }, this.options.pollingInterval);\n }\n\n private getNativeModule(): typeof NativeModules.FaroReactNativeModule | null {\n const { FaroReactNativeModule } = NativeModules;\n\n if (!FaroReactNativeModule) {\n return null;\n }\n\n return FaroReactNativeModule;\n }\n\n private startNativeTracking(nativeModule: typeof NativeModules.FaroReactNativeModule): void {\n try {\n if (typeof nativeModule.startANRTracking === 'function') {\n nativeModule.startANRTracking({\n timeout: this.options.timeout,\n });\n this.logDebug('Started native ANR tracking');\n }\n } catch (error) {\n this.logError('Failed to start native ANR tracking', error);\n }\n }\n\n private async drainAllAnrSources(nativeModule: typeof NativeModules.FaroReactNativeModule): Promise<void> {\n await this.drainHistoricalAnrs(nativeModule);\n await this.drainPendingANRs(nativeModule);\n }\n\n private async drainHistoricalAnrs(nativeModule: typeof NativeModules.FaroReactNativeModule): Promise<void> {\n if (typeof nativeModule.getHistoricalAnrReports !== 'function') {\n return;\n }\n\n try {\n const anrList = (await nativeModule.getHistoricalAnrReports()) as string[] | null;\n if (!anrList?.length) {\n return;\n }\n\n const ackTimestamps: number[] = [];\n let reportedCount = 0;\n\n for (const anrJson of anrList) {\n try {\n const anr = JSON.parse(anrJson) as ANREvent;\n if (this.reportANRIfNew(anr)) {\n reportedCount += 1;\n }\n ackTimestamps.push(anr.timestamp);\n await this.acknowledgeNearbyPendingAnrs(nativeModule, anr.timestamp);\n } catch (error) {\n this.logError('Failed to parse historical ANR report', error);\n }\n }\n\n if (reportedCount > 0) {\n this.api.pushMeasurement(\n {\n type: 'anr',\n values: { anr_count: reportedCount },\n },\n { skipDedupe: true }\n );\n this.logDebug(`Reported ${reportedCount} historical ANR event(s) from ApplicationExitInfo`);\n }\n } catch (error) {\n this.logError('Failed to drain historical ANRs', error);\n }\n }\n\n private async drainPendingANRs(nativeModule: typeof NativeModules.FaroReactNativeModule): Promise<void> {\n const anrList = await this.fetchPendingANRs(nativeModule);\n if (!anrList?.length) {\n return;\n }\n\n await this.reportAndAcknowledgePendingANRs(nativeModule, anrList);\n this.logDebug(`Processed ${anrList.length} persisted ANR event(s) from tracker cache`);\n }\n\n private async handleLiveAnrEvent(\n nativeModule: typeof NativeModules.FaroReactNativeModule,\n anrJson: string\n ): Promise<void> {\n try {\n const anr = JSON.parse(anrJson) as ANREvent;\n\n if (this.preferAppExitInfoAnr) {\n // Process death + ApplicationExitInfo on next launch delivers the main-thread dump.\n this.logDebug('Deferring live ANR to ApplicationExitInfo on next launch');\n return;\n }\n\n if (!this.shouldReportTrackerAnr(anr)) {\n await this.acknowledgeANRs(nativeModule, [anr.timestamp]);\n return;\n }\n\n if (this.reportANRIfNew(anr)) {\n this.api.pushMeasurement(\n {\n type: 'anr',\n values: { anr_count: 1 },\n },\n { skipDedupe: true }\n );\n }\n await this.acknowledgeANRs(nativeModule, [anr.timestamp]);\n } catch (error) {\n this.logError('Failed to parse native ANR event', error);\n }\n }\n\n private async fetchPendingANRs(nativeModule: typeof NativeModules.FaroReactNativeModule): Promise<string[] | null> {\n try {\n if (typeof nativeModule.getPendingANRs === 'function') {\n return (await nativeModule.getPendingANRs()) as string[] | null;\n }\n\n if (typeof nativeModule.getANRStatus === 'function') {\n return (await nativeModule.getANRStatus()) as string[] | null;\n }\n } catch (error) {\n this.logError('Failed to fetch pending ANRs', error);\n }\n\n return null;\n }\n\n private async acknowledgeANRs(\n nativeModule: typeof NativeModules.FaroReactNativeModule,\n timestamps: number[]\n ): Promise<void> {\n if (!timestamps.length || typeof nativeModule.acknowledgeANRs !== 'function') {\n return;\n }\n\n try {\n await nativeModule.acknowledgeANRs(timestamps);\n } catch (error) {\n this.logError('Failed to acknowledge ANRs', error);\n }\n }\n\n private async acknowledgeNearbyPendingAnrs(\n nativeModule: typeof NativeModules.FaroReactNativeModule,\n exitTimestamp: number\n ): Promise<void> {\n const pending = await this.fetchPendingANRs(nativeModule);\n if (!pending?.length) {\n return;\n }\n\n const ackTimestamps: number[] = [];\n for (const anrJson of pending) {\n try {\n const anr = JSON.parse(anrJson) as ANREvent;\n if (this.isNearbyTimestamp(anr.timestamp, exitTimestamp)) {\n ackTimestamps.push(anr.timestamp);\n }\n } catch {\n // ignore malformed cache entries\n }\n }\n\n if (ackTimestamps.length > 0) {\n await this.acknowledgeANRs(nativeModule, ackTimestamps);\n }\n }\n\n private async reportAndAcknowledgePendingANRs(\n nativeModule: typeof NativeModules.FaroReactNativeModule,\n anrList: string[]\n ): Promise<void> {\n const ackTimestamps: number[] = [];\n let reportedCount = 0;\n\n for (const anrJson of anrList) {\n try {\n const anr = JSON.parse(anrJson) as ANREvent;\n\n if (this.shouldReportTrackerAnr(anr) && this.reportANRIfNew(anr)) {\n reportedCount += 1;\n }\n\n ackTimestamps.push(anr.timestamp);\n } catch {\n const error = new Error('ANR (Application Not Responding)');\n error.stack = undefined;\n this.api.pushError(error, {\n context: {\n mechanism: ErrorMechanism.ANR,\n raw: anrJson,\n },\n fatal: true,\n type: 'ANR',\n });\n }\n }\n\n if (reportedCount > 0) {\n this.api.pushMeasurement(\n {\n type: 'anr',\n values: { anr_count: reportedCount },\n },\n { skipDedupe: true }\n );\n }\n\n if (ackTimestamps.length > 0) {\n await this.acknowledgeANRs(nativeModule, ackTimestamps);\n }\n }\n\n private shouldReportTrackerAnr(anr: ANREvent): boolean {\n if (this.isNearbyReportedTimestamp(anr.timestamp)) {\n return false;\n }\n\n if (isInvalidAnrCaptureStack(anr.stacktrace)) {\n return false;\n }\n\n // On API 30+, ApplicationExitInfo is preferred on launch; tracker pending entries\n // are reported only when historical did not already cover the same incident.\n return true;\n }\n\n private reportANRIfNew(anr: ANREvent): boolean {\n if (this.isNearbyReportedTimestamp(anr.timestamp)) {\n return false;\n }\n\n if (isInvalidAnrCaptureStack(anr.stacktrace)) {\n return false;\n }\n\n this.rememberReportedTimestamp(anr.timestamp);\n this.reportANR(anr);\n return true;\n }\n\n private rememberReportedTimestamp(timestamp: number): void {\n this.reportedAnrTimestamps.add(timestamp);\n }\n\n private isNearbyReportedTimestamp(timestamp: number): boolean {\n for (const reported of Array.from(this.reportedAnrTimestamps)) {\n if (this.isNearbyTimestamp(timestamp, reported)) {\n return true;\n }\n }\n return false;\n }\n\n private isNearbyTimestamp(a: number, b: number): boolean {\n if (a <= 0 || b <= 0) {\n return false;\n }\n return Math.abs(a - b) <= TIMESTAMP_DEDUP_WINDOW_MS;\n }\n\n private reportANR(anr: ANREvent): void {\n const rawStacktrace = anr.stacktrace?.trim() ?? '';\n const traceForRetrace = rawStacktrace ? normalizeJavaStackTraceForRetrace(rawStacktrace) : '';\n const parsed = traceForRetrace ? parseAndroidCrashTrace(traceForRetrace) : null;\n\n const message = anr.description?.trim() || 'ANR (Application Not Responding)';\n const error = new Error(message);\n error.stack = undefined;\n\n const context: Record<string, string> = {\n duration: String(anr.duration),\n mechanism: ErrorMechanism.ANR,\n timestamp: String(anr.timestamp),\n };\n if (anr.source) {\n context['source'] = anr.source;\n }\n if (traceForRetrace) {\n context['stacktrace'] = traceForRetrace;\n }\n\n const stackFrames = parsed?.frames ?? [];\n if (!stackFrames.length && rawStacktrace) {\n this.logWarn('ANR main-thread stack present but no Java/Kotlin frames parsed');\n }\n\n this.api.pushError(error, {\n type: 'ANR',\n context,\n fatal: true,\n ...(stackFrames.length ? { stackFrames } : {}),\n });\n }\n\n private async checkANRStatus(nativeModule: typeof NativeModules.FaroReactNativeModule): Promise<void> {\n try {\n const anrList = await this.fetchPendingANRs(nativeModule);\n\n if (anrList && anrList.length > 0) {\n await this.reportAndAcknowledgePendingANRs(nativeModule, anrList);\n this.logDebug(`Polled ${anrList.length} ANR event(s) from pending cache`);\n }\n } catch (error) {\n this.logError('Failed to check ANR status', error);\n }\n }\n\n unpatch(): void {\n if (this.pollingIntervalId !== null) {\n clearInterval(this.pollingIntervalId);\n this.pollingIntervalId = null;\n }\n\n this.anrEventSubscription?.remove();\n this.anrEventSubscription = null;\n this.reportedAnrTimestamps.clear();\n\n if (Platform.OS === 'android') {\n const nativeModule = this.getNativeModule();\n if (nativeModule && typeof nativeModule.stopANRTracking === 'function') {\n try {\n nativeModule.stopANRTracking();\n } catch (error) {\n this.logError('Failed to stop native ANR tracking', error);\n }\n }\n }\n\n this.logDebug('ANR instrumentation stopped');\n }\n}\n"]}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { AppState } from 'react-native';
|
|
2
2
|
import { BaseInstrumentation, dateNow, VERSION } from '@grafana/faro-core';
|
|
3
|
-
// Event name aligned with Faro Flutter SDK (app_lifecycle_changed)
|
|
4
3
|
export const EVENT_APP_STATE_CHANGED = 'app_lifecycle_changed';
|
|
4
|
+
const APP_STATE_STATUSES = ['inactive', 'background', 'active', 'extension', 'unknown'];
|
|
5
|
+
// RN types AppState.currentState as `null | undefined | string`: it stays null
|
|
6
|
+
// until the initial value is set, so narrow it instead of trusting the shape.
|
|
7
|
+
function isAppStateStatus(value) {
|
|
8
|
+
return typeof value === 'string' && APP_STATE_STATUSES.includes(value);
|
|
9
|
+
}
|
|
5
10
|
/**
|
|
6
11
|
* AppState instrumentation for React Native
|
|
7
12
|
* Tracks app foreground/background/inactive state changes
|
|
@@ -54,7 +59,8 @@ export class AppStateInstrumentation extends BaseInstrumentation {
|
|
|
54
59
|
}
|
|
55
60
|
initialize() {
|
|
56
61
|
// Get initial app state
|
|
57
|
-
|
|
62
|
+
const initialState = AppState.currentState;
|
|
63
|
+
this.currentState = isAppStateStatus(initialState) ? initialState : undefined;
|
|
58
64
|
this.stateStartTime = dateNow();
|
|
59
65
|
this.logInfo('AppState instrumentation initialized', {
|
|
60
66
|
initialState: this.currentState,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/instrumentations/appState/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAuB,MAAM,cAAc,CAAC;AAE7D,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE3E,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/instrumentations/appState/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { AppState, type AppStateStatus } from 'react-native';\n\nimport { BaseInstrumentation, dateNow, VERSION } from '@grafana/faro-core';\n\nexport const EVENT_APP_STATE_CHANGED = 'app_lifecycle_changed';\n\nconst APP_STATE_STATUSES = ['inactive', 'background', 'active', 'extension', 'unknown'] as const;\n\n// RN types AppState.currentState as `null | undefined | string`: it stays null\n// until the initial value is set, so narrow it instead of trusting the shape.\nfunction isAppStateStatus(value: unknown): value is AppStateStatus {\n return typeof value === 'string' && (APP_STATE_STATUSES as readonly string[]).includes(value);\n}\n\n/**\n * AppState instrumentation for React Native\n * Tracks app foreground/background/inactive state changes\n *\n * Emits `app_lifecycle_changed` with React Native `AppState` values in `fromState` / `toState`\n * (active, background, inactive, unknown, extension).\n */\nexport class AppStateInstrumentation extends BaseInstrumentation {\n readonly name = '@grafana/faro-react-native:instrumentation-appstate';\n readonly version = VERSION;\n\n private currentState: AppStateStatus | undefined;\n private stateStartTime: number | undefined;\n private appStateSubscription: ReturnType<typeof AppState.addEventListener> | undefined;\n\n initialize(): void {\n // Get initial app state\n const initialState = AppState.currentState;\n this.currentState = isAppStateStatus(initialState) ? initialState : undefined;\n this.stateStartTime = dateNow();\n\n this.logInfo('AppState instrumentation initialized', {\n initialState: this.currentState,\n });\n\n // Subscribe to app state changes\n this.appStateSubscription = AppState.addEventListener('change', this.handleAppStateChange);\n }\n\n /**\n * Handles app state changes and emits app_lifecycle_changed events\n * with native AppState status strings. Includes duration and timestamp for time-in-state analysis.\n */\n private handleAppStateChange = (nextAppState: AppStateStatus): void => {\n const previousState = this.currentState;\n const now = dateNow();\n const duration = this.stateStartTime ? now - this.stateStartTime : 0;\n\n // Update state tracking\n this.currentState = nextAppState;\n this.stateStartTime = now;\n\n // Log the state change (internal debug keeps RN state names)\n this.logDebug('App state changed', {\n from: previousState,\n to: nextAppState,\n duration,\n });\n\n // Emit app lifecycle change event (native RN AppState values + duration/timestamp)\n const fromState = previousState !== undefined ? previousState : '';\n const toState = nextAppState;\n this.api.pushEvent(\n EVENT_APP_STATE_CHANGED,\n {\n fromState,\n toState,\n duration: duration.toString(),\n timestamp: now.toString(),\n },\n undefined,\n { skipDedupe: true }\n );\n\n // Additional logging for specific transitions\n if (nextAppState === 'background') {\n this.logInfo('App moved to background', { fromState: previousState, duration });\n } else if (nextAppState === 'active' && previousState === 'background') {\n this.logInfo('App returned to foreground', { duration });\n } else if (nextAppState === 'inactive') {\n this.logDebug('App became inactive', { fromState: previousState });\n }\n };\n\n /**\n * Get the current app state\n */\n getCurrentState(): AppStateStatus | undefined {\n return this.currentState;\n }\n\n /**\n * Get the duration the app has been in the current state (in milliseconds)\n */\n getCurrentStateDuration(): number {\n if (!this.stateStartTime) {\n return 0;\n }\n return dateNow() - this.stateStartTime;\n }\n\n /**\n * Check if app is currently in the foreground (active state)\n */\n isActive(): boolean {\n return this.currentState === 'active';\n }\n\n /**\n * Check if app is currently in the background\n */\n isBackground(): boolean {\n return this.currentState === 'background';\n }\n\n /**\n * Cleanup: Remove app state listener\n */\n unpatch(): void {\n if (this.appStateSubscription) {\n this.appStateSubscription.remove();\n this.appStateSubscription = undefined;\n this.logInfo('AppState instrumentation unpatched');\n }\n }\n}\n"]}
|
|
@@ -38,12 +38,16 @@ export class BaseCrashReportingInstrumentation extends BaseInstrumentation {
|
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
40
|
this.logDebug('Initializing crash reporting instrumentation');
|
|
41
|
+
yield this.prepareCrashReporting(nativeModule);
|
|
41
42
|
// Wait for session attributes before sending crash reports
|
|
42
43
|
yield this.waitForSessionAttributes();
|
|
43
44
|
// Get and process crash reports from previous session
|
|
44
45
|
yield this.processCrashReports(nativeModule);
|
|
45
46
|
});
|
|
46
47
|
}
|
|
48
|
+
prepareCrashReporting(_nativeModule) {
|
|
49
|
+
// Optional platform-specific setup.
|
|
50
|
+
}
|
|
47
51
|
waitForSessionAttributes() {
|
|
48
52
|
return __awaiter(this, arguments, void 0, function* (maxWaitMs = 10000) {
|
|
49
53
|
var _a, _b, _c, _d, _e, _f;
|
|
@@ -148,13 +152,10 @@ export class BaseCrashReportingInstrumentation extends BaseInstrumentation {
|
|
|
148
152
|
}
|
|
149
153
|
});
|
|
150
154
|
}
|
|
151
|
-
|
|
155
|
+
buildCrashReportDetails(crash) {
|
|
152
156
|
// Platform-specific parsing
|
|
153
157
|
const parsedTrace = crash.trace ? this.parseCrashTrace(crash.trace) : null;
|
|
154
158
|
const errorMessage = this.resolveCrashErrorMessage(crash, parsedTrace).trim() || 'Application crash';
|
|
155
|
-
// Use a message-only Error so pushError does not capture the JS reporter stack
|
|
156
|
-
const error = new Error(errorMessage);
|
|
157
|
-
error.stack = undefined;
|
|
158
159
|
// Build context from crash data
|
|
159
160
|
const context = {
|
|
160
161
|
mechanism: 'crash',
|
|
@@ -198,6 +199,16 @@ export class BaseCrashReportingInstrumentation extends BaseInstrumentation {
|
|
|
198
199
|
.find((line) => /#\d+\s+pc\s+/i.test(line));
|
|
199
200
|
this.logInfo(`[Faro crash native] Sending tombstone trace (${crash.trace.split('\n').length} lines) preview=${framePreview !== null && framePreview !== void 0 ? framePreview : 'n/a'}`);
|
|
200
201
|
}
|
|
202
|
+
return {
|
|
203
|
+
context,
|
|
204
|
+
errorMessage,
|
|
205
|
+
stackFrames,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
sendCrashReport(crash) {
|
|
209
|
+
const { context, errorMessage, stackFrames } = this.buildCrashReportDetails(crash);
|
|
210
|
+
const error = new Error(errorMessage);
|
|
211
|
+
error.stack = undefined;
|
|
201
212
|
this.api.pushError(error, {
|
|
202
213
|
stackFrames,
|
|
203
214
|
context,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseCrashReportingInstrumentation.js","sourceRoot":"","sources":["../../../../src/instrumentations/crashReporting/BaseCrashReportingInstrumentation.ts"],"names":[],"mappings":"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","sourcesContent":["import { NativeModules } from 'react-native';\n\nimport { BaseInstrumentation } from '@grafana/faro-core';\n\nimport { looksLikeNativeTombstoneTrace } from './android/nativeTombstoneTrace';\nimport type { CrashReport, CrashReportingOptions } from './types';\n\n/**\n * Abstract base class for platform-specific crash reporting implementations.\n *\n * Defines the common contract that both Android and iOS implementations must follow.\n * Handles the shared logic for retrieving crash reports from native modules and\n * processing them, while delegating platform-specific parsing and validation to subclasses.\n */\nexport abstract class BaseCrashReportingInstrumentation extends BaseInstrumentation {\n abstract override readonly name: string;\n abstract override readonly version: string;\n\n protected readonly options: { enabled: boolean; releaseBundleFilename?: string };\n\n constructor(options: CrashReportingOptions = {}) {\n super();\n this.options = {\n enabled: options.enabled ?? true,\n releaseBundleFilename: options.releaseBundleFilename,\n };\n }\n\n async initialize(): Promise<void> {\n if (!this.options.enabled) {\n this.logDebug('Crash reporting is disabled');\n return;\n }\n\n const nativeModule = this.getNativeModule();\n if (!nativeModule) {\n this.logWarn('Native module not available for crash reporting');\n return;\n }\n\n this.logDebug('Initializing crash reporting instrumentation');\n\n // Wait for session attributes before sending crash reports\n await this.waitForSessionAttributes();\n\n // Get and process crash reports from previous session\n await this.processCrashReports(nativeModule);\n }\n\n /**\n * Platform-specific: Parse a crash trace string into structured stack frames.\n */\n protected abstract parseCrashTrace(trace: string): any | null;\n\n /**\n * Platform-specific: Resolve human-readable error message from crash data.\n */\n protected abstract resolveCrashErrorMessage(crash: CrashReport, parsedTrace: any | null): string;\n\n /**\n * Platform-specific: Determine if a crash report should be skipped.\n */\n protected abstract shouldSkipCrashReport(crash: CrashReport): boolean;\n\n /**\n * Platform-specific: Extract stack frames from parsed trace.\n */\n protected abstract getStackFrames(parsedTrace: any | null): any[];\n\n /**\n * Platform-specific: Build platform-specific context from parsed trace.\n */\n protected abstract buildPlatformContext(parsedTrace: any | null, context: Record<string, string>): void;\n\n /**\n * Platform-specific: Get warning message when trace parsing fails.\n */\n protected abstract getParseFailureWarning(): string;\n\n /**\n * Platform-specific: Get warning message when trace is unavailable.\n */\n protected abstract getTraceUnavailableWarning(): string;\n\n private async waitForSessionAttributes(maxWaitMs = 10000): Promise<void> {\n const startTime = Date.now();\n const pollInterval = 200;\n let checkCount = 0;\n\n while (Date.now() - startTime < maxWaitMs) {\n checkCount++;\n try {\n const sessionAttrs = this.metas?.value?.session?.attributes;\n\n if (sessionAttrs) {\n const attrCount = Object.keys(sessionAttrs).length;\n const attrKeys = JSON.stringify(Object.keys(sessionAttrs));\n\n // Look for multiple device-specific attributes that indicate full async collection is done.\n // getSessionAttributes() collects these asynchronously:\n // - device_id (SDK installation id, kept as a flat attr during migration)\n // - device_os_detail (async getDeviceOsDetail)\n // - device_model_name (DeviceInfo.getDeviceNameSync)\n // All three should be present when collection is complete.\n const hasDeviceId = 'device_id' in sessionAttrs && sessionAttrs['device_id'] !== 'unknown';\n const hasDeviceOsDetail =\n 'device_os_detail' in sessionAttrs && sessionAttrs['device_os_detail'] !== 'unknown';\n const hasDeviceModelName = 'device_model_name' in sessionAttrs;\n\n if (hasDeviceId && hasDeviceOsDetail && hasDeviceModelName) {\n const elapsed = Date.now() - startTime;\n this.logDebug(`Session attributes ready after ${elapsed}ms (${checkCount} checks, ${attrCount} attrs)`);\n return;\n } else {\n this.logDebug(\n `Check #${checkCount}: Found ${attrCount} session attributes: ${attrKeys} but still missing required attrs - device_id:${hasDeviceId}, device_os_detail:${hasDeviceOsDetail}, device_model_name:${hasDeviceModelName}`\n );\n }\n } else {\n this.logDebug(`Check #${checkCount}: No session attributes available yet`);\n }\n } catch (error) {\n this.logDebug(`Check #${checkCount}: Error accessing metas: ${error}`);\n }\n\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\n }\n\n const finalAttrs = this.metas?.value?.session?.attributes;\n const finalAttrCount = finalAttrs ? Object.keys(finalAttrs).length : 0;\n const finalAttrKeys = finalAttrs ? JSON.stringify(Object.keys(finalAttrs)) : 'none';\n this.logWarn(\n `Session attributes not ready after ${maxWaitMs}ms timeout (${checkCount} checks, ${finalAttrCount} attrs: ${finalAttrKeys}). Sending crash report anyway.`\n );\n }\n\n private getNativeModule(): typeof NativeModules.FaroReactNativeModule | null {\n const { FaroReactNativeModule } = NativeModules;\n\n if (!FaroReactNativeModule) {\n return null;\n }\n\n return FaroReactNativeModule;\n }\n\n private async processCrashReports(nativeModule: typeof NativeModules.FaroReactNativeModule): Promise<void> {\n try {\n if (typeof nativeModule.getCrashReport !== 'function') {\n this.logDebug('getCrashReport method not available');\n return;\n }\n\n this.logDebug('Attempting to retrieve crash reports from native module');\n const crashReports = (await nativeModule.getCrashReport()) as string[] | null;\n\n if (!crashReports || crashReports.length === 0) {\n this.logDebug('No crash reports from previous session');\n return;\n }\n\n this.logDebug(`Processing ${crashReports.length} crash report(s) from previous session`);\n\n const reportedTimestamps = new Set<number>();\n\n for (const crashJson of crashReports) {\n try {\n this.logDebug(`Parsing crash report JSON: ${crashJson.substring(0, 200)}...`);\n const crash = JSON.parse(crashJson) as CrashReport;\n\n if (crash.timestamp && reportedTimestamps.has(crash.timestamp)) {\n this.logDebug(`Skipping duplicate crash report at ${crash.timestamp}`);\n continue;\n }\n\n if (this.shouldSkipCrashReport(crash)) {\n this.logDebug(`Skipping crash report at ${crash.timestamp} (platform-specific skip logic)`);\n continue;\n }\n\n if (crash.timestamp) {\n reportedTimestamps.add(crash.timestamp);\n }\n\n this.sendCrashReport(crash);\n } catch (parseError) {\n this.logError('Failed to parse crash report JSON', parseError);\n this.api.pushError(new Error('Application crash (parse error)'), {\n context: {\n mechanism: 'crash',\n parseError: String(parseError),\n raw: crashJson.substring(0, 500),\n },\n fatal: true,\n type: 'crash',\n });\n }\n }\n } catch (error) {\n this.logError('Failed to process crash reports', error);\n }\n }\n\n private sendCrashReport(crash: CrashReport): void {\n // Platform-specific parsing\n const parsedTrace = crash.trace ? this.parseCrashTrace(crash.trace) : null;\n const errorMessage = this.resolveCrashErrorMessage(crash, parsedTrace).trim() || 'Application crash';\n\n // Use a message-only Error so pushError does not capture the JS reporter stack\n const error = new Error(errorMessage);\n error.stack = undefined;\n\n // Build context from crash data\n const context: Record<string, string> = {\n mechanism: 'crash',\n };\n\n if (crash.trace) {\n context['trace'] = crash.trace;\n }\n if (crash.signal) {\n context['signal'] = crash.signal;\n }\n if (crash.timestamp) {\n context['timestamp'] = String(crash.timestamp);\n }\n if (crash.description) {\n context['description'] = crash.description;\n }\n if (crash.processName) {\n context['processName'] = crash.processName;\n }\n if (crash.pid) {\n context['pid'] = String(crash.pid);\n }\n if (crash.importance !== undefined) {\n context['importance'] = String(crash.importance);\n }\n\n // Platform-specific context\n this.buildPlatformContext(parsedTrace, context);\n\n // Platform-specific stack frames\n const stackFrames = this.getStackFrames(parsedTrace);\n\n // Warnings for missing/unparseable traces\n if (!stackFrames.length && crash.trace) {\n this.logWarn(this.getParseFailureWarning());\n } else if (!crash.trace) {\n this.logWarn(this.getTraceUnavailableWarning());\n } else if (looksLikeNativeTombstoneTrace(crash.trace)) {\n const framePreview = crash.trace\n .split('\\n')\n .map((line) => line.trim())\n .find((line) => /#\\d+\\s+pc\\s+/i.test(line));\n this.logInfo(\n `[Faro crash native] Sending tombstone trace (${crash.trace.split('\\n').length} lines) preview=${framePreview ?? 'n/a'}`\n );\n }\n\n this.api.pushError(error, {\n stackFrames,\n context,\n type: 'crash',\n fatal: true,\n });\n\n this.logDebug(`Sent crash report: ${errorMessage}`);\n }\n\n // Logging helpers\n override logDebug(message: string, ...args: any[]): void {\n this.internalLogger?.debug?.(message, ...args);\n }\n\n override logInfo(message: string, ...args: any[]): void {\n this.internalLogger?.info?.(message, ...args);\n }\n\n override logWarn(message: string, ...args: any[]): void {\n this.internalLogger?.warn?.(message, ...args);\n }\n\n override logError(message: string, ...args: any[]): void {\n this.internalLogger?.error?.(message, ...args);\n }\n\n unpatch(): void {\n // No patching to undo\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"BaseCrashReportingInstrumentation.js","sourceRoot":"","sources":["../../../../src/instrumentations/crashReporting/BaseCrashReportingInstrumentation.ts"],"names":[],"mappings":"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","sourcesContent":["import { NativeModules } from 'react-native';\n\nimport { BaseInstrumentation } from '@grafana/faro-core';\nimport type { ExceptionStackFrame } from '@grafana/faro-core';\n\nimport { looksLikeNativeTombstoneTrace } from './android/nativeTombstoneTrace';\nimport type { CrashReport, CrashReportingOptions } from './types';\n\ninterface CrashReportDetails {\n context: Record<string, string>;\n errorMessage: string;\n stackFrames: ExceptionStackFrame[];\n}\n\n/**\n * Abstract base class for platform-specific crash reporting implementations.\n *\n * Defines the common contract that both Android and iOS implementations must follow.\n * Handles the shared logic for retrieving crash reports from native modules and\n * processing them, while delegating platform-specific parsing and validation to subclasses.\n */\nexport abstract class BaseCrashReportingInstrumentation extends BaseInstrumentation {\n abstract override readonly name: string;\n abstract override readonly version: string;\n\n protected readonly options: { enabled: boolean; releaseBundleFilename?: string };\n\n constructor(options: CrashReportingOptions = {}) {\n super();\n this.options = {\n enabled: options.enabled ?? true,\n releaseBundleFilename: options.releaseBundleFilename,\n };\n }\n\n async initialize(): Promise<void> {\n if (!this.options.enabled) {\n this.logDebug('Crash reporting is disabled');\n return;\n }\n\n const nativeModule = this.getNativeModule();\n if (!nativeModule) {\n this.logWarn('Native module not available for crash reporting');\n return;\n }\n\n this.logDebug('Initializing crash reporting instrumentation');\n await this.prepareCrashReporting(nativeModule);\n\n // Wait for session attributes before sending crash reports\n await this.waitForSessionAttributes();\n\n // Get and process crash reports from previous session\n await this.processCrashReports(nativeModule);\n }\n\n /**\n * Platform-specific: Parse a crash trace string into structured stack frames.\n */\n protected abstract parseCrashTrace(trace: string): any | null;\n\n /**\n * Platform-specific: Resolve human-readable error message from crash data.\n */\n protected abstract resolveCrashErrorMessage(crash: CrashReport, parsedTrace: any | null): string;\n\n /**\n * Platform-specific: Determine if a crash report should be skipped.\n */\n protected abstract shouldSkipCrashReport(crash: CrashReport): boolean;\n\n /**\n * Platform-specific: Extract stack frames from parsed trace.\n */\n protected abstract getStackFrames(parsedTrace: any | null): any[];\n\n /**\n * Platform-specific: Build platform-specific context from parsed trace.\n */\n protected abstract buildPlatformContext(parsedTrace: any | null, context: Record<string, string>): void;\n\n /**\n * Platform-specific: Get warning message when trace parsing fails.\n */\n protected abstract getParseFailureWarning(): string;\n\n /**\n * Platform-specific: Get warning message when trace is unavailable.\n */\n protected abstract getTraceUnavailableWarning(): string;\n\n protected prepareCrashReporting(_nativeModule: typeof NativeModules.FaroReactNativeModule): void | Promise<void> {\n // Optional platform-specific setup.\n }\n\n protected async waitForSessionAttributes(maxWaitMs = 10000): Promise<void> {\n const startTime = Date.now();\n const pollInterval = 200;\n let checkCount = 0;\n\n while (Date.now() - startTime < maxWaitMs) {\n checkCount++;\n try {\n const sessionAttrs = this.metas?.value?.session?.attributes;\n\n if (sessionAttrs) {\n const attrCount = Object.keys(sessionAttrs).length;\n const attrKeys = JSON.stringify(Object.keys(sessionAttrs));\n\n // Look for multiple device-specific attributes that indicate full async collection is done.\n // getSessionAttributes() collects these asynchronously:\n // - device_id (SDK installation id, kept as a flat attr during migration)\n // - device_os_detail (async getDeviceOsDetail)\n // - device_model_name (DeviceInfo.getDeviceNameSync)\n // All three should be present when collection is complete.\n const hasDeviceId = 'device_id' in sessionAttrs && sessionAttrs['device_id'] !== 'unknown';\n const hasDeviceOsDetail =\n 'device_os_detail' in sessionAttrs && sessionAttrs['device_os_detail'] !== 'unknown';\n const hasDeviceModelName = 'device_model_name' in sessionAttrs;\n\n if (hasDeviceId && hasDeviceOsDetail && hasDeviceModelName) {\n const elapsed = Date.now() - startTime;\n this.logDebug(`Session attributes ready after ${elapsed}ms (${checkCount} checks, ${attrCount} attrs)`);\n return;\n } else {\n this.logDebug(\n `Check #${checkCount}: Found ${attrCount} session attributes: ${attrKeys} but still missing required attrs - device_id:${hasDeviceId}, device_os_detail:${hasDeviceOsDetail}, device_model_name:${hasDeviceModelName}`\n );\n }\n } else {\n this.logDebug(`Check #${checkCount}: No session attributes available yet`);\n }\n } catch (error) {\n this.logDebug(`Check #${checkCount}: Error accessing metas: ${error}`);\n }\n\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\n }\n\n const finalAttrs = this.metas?.value?.session?.attributes;\n const finalAttrCount = finalAttrs ? Object.keys(finalAttrs).length : 0;\n const finalAttrKeys = finalAttrs ? JSON.stringify(Object.keys(finalAttrs)) : 'none';\n this.logWarn(\n `Session attributes not ready after ${maxWaitMs}ms timeout (${checkCount} checks, ${finalAttrCount} attrs: ${finalAttrKeys}). Sending crash report anyway.`\n );\n }\n\n protected getNativeModule(): typeof NativeModules.FaroReactNativeModule | null {\n const { FaroReactNativeModule } = NativeModules;\n\n if (!FaroReactNativeModule) {\n return null;\n }\n\n return FaroReactNativeModule;\n }\n\n protected async processCrashReports(nativeModule: typeof NativeModules.FaroReactNativeModule): Promise<void> {\n try {\n if (typeof nativeModule.getCrashReport !== 'function') {\n this.logDebug('getCrashReport method not available');\n return;\n }\n\n this.logDebug('Attempting to retrieve crash reports from native module');\n const crashReports = (await nativeModule.getCrashReport()) as string[] | null;\n\n if (!crashReports || crashReports.length === 0) {\n this.logDebug('No crash reports from previous session');\n return;\n }\n\n this.logDebug(`Processing ${crashReports.length} crash report(s) from previous session`);\n\n const reportedTimestamps = new Set<number>();\n\n for (const crashJson of crashReports) {\n try {\n this.logDebug(`Parsing crash report JSON: ${crashJson.substring(0, 200)}...`);\n const crash = JSON.parse(crashJson) as CrashReport;\n\n if (crash.timestamp && reportedTimestamps.has(crash.timestamp)) {\n this.logDebug(`Skipping duplicate crash report at ${crash.timestamp}`);\n continue;\n }\n\n if (this.shouldSkipCrashReport(crash)) {\n this.logDebug(`Skipping crash report at ${crash.timestamp} (platform-specific skip logic)`);\n continue;\n }\n\n if (crash.timestamp) {\n reportedTimestamps.add(crash.timestamp);\n }\n\n this.sendCrashReport(crash);\n } catch (parseError) {\n this.logError('Failed to parse crash report JSON', parseError);\n this.api.pushError(new Error('Application crash (parse error)'), {\n context: {\n mechanism: 'crash',\n parseError: String(parseError),\n raw: crashJson.substring(0, 500),\n },\n fatal: true,\n type: 'crash',\n });\n }\n }\n } catch (error) {\n this.logError('Failed to process crash reports', error);\n }\n }\n\n protected buildCrashReportDetails(crash: CrashReport): CrashReportDetails {\n // Platform-specific parsing\n const parsedTrace = crash.trace ? this.parseCrashTrace(crash.trace) : null;\n const errorMessage = this.resolveCrashErrorMessage(crash, parsedTrace).trim() || 'Application crash';\n\n // Build context from crash data\n const context: Record<string, string> = {\n mechanism: 'crash',\n };\n\n if (crash.trace) {\n context['trace'] = crash.trace;\n }\n if (crash.signal) {\n context['signal'] = crash.signal;\n }\n if (crash.timestamp) {\n context['timestamp'] = String(crash.timestamp);\n }\n if (crash.description) {\n context['description'] = crash.description;\n }\n if (crash.processName) {\n context['processName'] = crash.processName;\n }\n if (crash.pid) {\n context['pid'] = String(crash.pid);\n }\n if (crash.importance !== undefined) {\n context['importance'] = String(crash.importance);\n }\n\n // Platform-specific context\n this.buildPlatformContext(parsedTrace, context);\n\n // Platform-specific stack frames\n const stackFrames = this.getStackFrames(parsedTrace);\n\n // Warnings for missing/unparseable traces\n if (!stackFrames.length && crash.trace) {\n this.logWarn(this.getParseFailureWarning());\n } else if (!crash.trace) {\n this.logWarn(this.getTraceUnavailableWarning());\n } else if (looksLikeNativeTombstoneTrace(crash.trace)) {\n const framePreview = crash.trace\n .split('\\n')\n .map((line) => line.trim())\n .find((line) => /#\\d+\\s+pc\\s+/i.test(line));\n this.logInfo(\n `[Faro crash native] Sending tombstone trace (${crash.trace.split('\\n').length} lines) preview=${framePreview ?? 'n/a'}`\n );\n }\n\n return {\n context,\n errorMessage,\n stackFrames,\n };\n }\n\n protected sendCrashReport(crash: CrashReport): void {\n const { context, errorMessage, stackFrames } = this.buildCrashReportDetails(crash);\n const error = new Error(errorMessage);\n error.stack = undefined;\n\n this.api.pushError(error, {\n stackFrames,\n context,\n type: 'crash',\n fatal: true,\n });\n\n this.logDebug(`Sent crash report: ${errorMessage}`);\n }\n\n // Logging helpers\n override logDebug(message: string, ...args: any[]): void {\n this.internalLogger?.debug?.(message, ...args);\n }\n\n override logInfo(message: string, ...args: any[]): void {\n this.internalLogger?.info?.(message, ...args);\n }\n\n override logWarn(message: string, ...args: any[]): void {\n this.internalLogger?.warn?.(message, ...args);\n }\n\n override logError(message: string, ...args: any[]): void {\n this.internalLogger?.error?.(message, ...args);\n }\n\n unpatch(): void {\n // No patching to undo\n }\n}\n"]}
|