@grafana/faro-react-native 1.2.1 → 1.3.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.
Files changed (217) hide show
  1. package/android/build.gradle +118 -36
  2. package/android/consumer-proguard-rules.pro +2 -0
  3. package/android/src/main/java/com/grafana/faro/reactnative/ANRTracker.kt +61 -9
  4. package/android/src/main/java/com/grafana/faro/reactnative/AnrThreadDumpParser.kt +70 -0
  5. package/android/src/main/java/com/grafana/faro/reactnative/ApplicationExitTraceReader.kt +142 -0
  6. package/android/src/main/java/com/grafana/faro/reactnative/FaroAnrCache.kt +163 -0
  7. package/android/src/main/java/com/grafana/faro/reactnative/FaroAnrReporter.kt +163 -0
  8. package/android/src/main/java/com/grafana/faro/reactnative/FaroCrashReporter.kt +243 -50
  9. package/android/src/main/java/com/grafana/faro/reactnative/FaroCrashTraceCache.kt +75 -0
  10. package/android/src/main/java/com/grafana/faro/reactnative/FaroNativeCrashTrace.kt +39 -0
  11. package/android/src/main/java/com/grafana/faro/reactnative/FaroReactNativeModule.kt +99 -8
  12. package/android/src/main/java/com/grafana/faro/reactnative/FaroReactNativePackage.kt +1 -0
  13. package/android/src/main/java/com/grafana/faro/reactnative/FaroUncaughtExceptionHandler.kt +62 -0
  14. package/android/src/main/java/com/grafana/faro/reactnative/TombstoneBacktraceFormatter.kt +117 -0
  15. package/android/src/main/java/com/grafana/faro/reactnative/TombstoneModels.kt +35 -0
  16. package/android/src/main/java/com/grafana/faro/reactnative/TombstoneWireParser.kt +235 -0
  17. package/android/src/main/proto/tombstone.proto +62 -0
  18. package/android/src/test/java/com/grafana/faro/reactnative/AnrStackFiltersTest.kt +28 -0
  19. package/android/src/test/java/com/grafana/faro/reactnative/AnrThreadDumpParserTest.kt +38 -0
  20. package/android/src/test/java/com/grafana/faro/reactnative/FaroAnrCacheTest.kt +81 -0
  21. package/android/src/test/java/com/grafana/faro/reactnative/TombstoneWireParserTest.kt +51 -0
  22. package/dist/cjs/config/getRNInstrumentations.js +3 -1
  23. package/dist/cjs/config/getRNInstrumentations.js.map +1 -1
  24. package/dist/cjs/config/makeRNConfig.js +48 -9
  25. package/dist/cjs/config/makeRNConfig.js.map +1 -1
  26. package/dist/cjs/config/types.js.map +1 -1
  27. package/dist/cjs/generated/faroRNPackageMeta.js +1 -1
  28. package/dist/cjs/generated/faroRNPackageMeta.js.map +1 -1
  29. package/dist/cjs/index.js +3 -2
  30. package/dist/cjs/index.js.map +1 -1
  31. package/dist/cjs/initialize.js +14 -8
  32. package/dist/cjs/initialize.js.map +1 -1
  33. package/dist/cjs/instrumentations/anr/anrStack.js +19 -0
  34. package/dist/cjs/instrumentations/anr/anrStack.js.map +1 -0
  35. package/dist/cjs/instrumentations/anr/instrumentation.js +374 -72
  36. package/dist/cjs/instrumentations/anr/instrumentation.js.map +1 -1
  37. package/dist/cjs/instrumentations/anr/types.js.map +1 -1
  38. package/dist/cjs/instrumentations/console/index.js +5 -1
  39. package/dist/cjs/instrumentations/console/index.js.map +1 -1
  40. package/dist/cjs/instrumentations/crashReporting/{instrumentation.js → BaseCrashReportingInstrumentation.js} +110 -103
  41. package/dist/cjs/instrumentations/crashReporting/BaseCrashReportingInstrumentation.js.map +1 -0
  42. package/dist/cjs/instrumentations/crashReporting/NoOpCrashReportingInstrumentation.js +41 -0
  43. package/dist/cjs/instrumentations/crashReporting/NoOpCrashReportingInstrumentation.js.map +1 -0
  44. package/dist/cjs/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.js +87 -0
  45. package/dist/cjs/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.js.map +1 -0
  46. package/dist/cjs/instrumentations/crashReporting/android/crashErrorMessage.js +123 -0
  47. package/dist/cjs/instrumentations/crashReporting/android/crashErrorMessage.js.map +1 -0
  48. package/dist/cjs/instrumentations/crashReporting/android/index.js +12 -0
  49. package/dist/cjs/instrumentations/crashReporting/android/index.js.map +1 -0
  50. package/dist/cjs/instrumentations/crashReporting/android/nativeTombstoneTrace.js +11 -0
  51. package/dist/cjs/instrumentations/crashReporting/android/nativeTombstoneTrace.js.map +1 -0
  52. package/dist/cjs/instrumentations/crashReporting/android/parseAndroidCrashTrace.js +181 -0
  53. package/dist/cjs/instrumentations/crashReporting/android/parseAndroidCrashTrace.js.map +1 -0
  54. package/dist/cjs/instrumentations/crashReporting/index.js +35 -2
  55. package/dist/cjs/instrumentations/crashReporting/index.js.map +1 -1
  56. package/dist/cjs/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.js +78 -0
  57. package/dist/cjs/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.js.map +1 -0
  58. package/dist/cjs/instrumentations/crashReporting/ios/crashErrorMessage.js +103 -0
  59. package/dist/cjs/instrumentations/crashReporting/ios/crashErrorMessage.js.map +1 -0
  60. package/dist/cjs/instrumentations/crashReporting/ios/index.js +11 -0
  61. package/dist/cjs/instrumentations/crashReporting/ios/index.js.map +1 -0
  62. package/dist/cjs/instrumentations/crashReporting/ios/parseIosCrashTrace.js +48 -0
  63. package/dist/cjs/instrumentations/crashReporting/ios/parseIosCrashTrace.js.map +1 -0
  64. package/dist/cjs/instrumentations/crashReporting/types.js.map +1 -1
  65. package/dist/cjs/instrumentations/errors/index.js +2 -1
  66. package/dist/cjs/instrumentations/errors/index.js.map +1 -1
  67. package/dist/cjs/instrumentations/session/installationId.js +91 -0
  68. package/dist/cjs/instrumentations/session/installationId.js.map +1 -0
  69. package/dist/cjs/instrumentations/session/sessionAttributes.js +152 -89
  70. package/dist/cjs/instrumentations/session/sessionAttributes.js.map +1 -1
  71. package/dist/cjs/metas/appBuildIdentity.js +95 -0
  72. package/dist/cjs/metas/appBuildIdentity.js.map +1 -0
  73. package/dist/cjs/testUtils/mockDeviceInfo.js +5 -0
  74. package/dist/cjs/testUtils/mockDeviceInfo.js.map +1 -1
  75. package/dist/cjs/testUtils/setupTests.js +7 -0
  76. package/dist/cjs/testUtils/setupTests.js.map +1 -1
  77. package/dist/esm/config/getRNInstrumentations.js +3 -1
  78. package/dist/esm/config/getRNInstrumentations.js.map +1 -1
  79. package/dist/esm/config/makeRNConfig.js +49 -10
  80. package/dist/esm/config/makeRNConfig.js.map +1 -1
  81. package/dist/esm/config/types.js.map +1 -1
  82. package/dist/esm/generated/faroRNPackageMeta.js +1 -1
  83. package/dist/esm/generated/faroRNPackageMeta.js.map +1 -1
  84. package/dist/esm/index.js +1 -1
  85. package/dist/esm/index.js.map +1 -1
  86. package/dist/esm/initialize.js +11 -5
  87. package/dist/esm/initialize.js.map +1 -1
  88. package/dist/esm/instrumentations/anr/anrStack.js +16 -0
  89. package/dist/esm/instrumentations/anr/anrStack.js.map +1 -0
  90. package/dist/esm/instrumentations/anr/instrumentation.js +260 -67
  91. package/dist/esm/instrumentations/anr/instrumentation.js.map +1 -1
  92. package/dist/esm/instrumentations/anr/types.js.map +1 -1
  93. package/dist/esm/instrumentations/console/index.js +5 -1
  94. package/dist/esm/instrumentations/console/index.js.map +1 -1
  95. package/dist/esm/instrumentations/crashReporting/{instrumentation.js → BaseCrashReportingInstrumentation.js} +76 -94
  96. package/dist/esm/instrumentations/crashReporting/BaseCrashReportingInstrumentation.js.map +1 -0
  97. package/dist/esm/instrumentations/crashReporting/NoOpCrashReportingInstrumentation.js +18 -0
  98. package/dist/esm/instrumentations/crashReporting/NoOpCrashReportingInstrumentation.js.map +1 -0
  99. package/dist/esm/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.js +56 -0
  100. package/dist/esm/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.js.map +1 -0
  101. package/dist/esm/instrumentations/crashReporting/android/crashErrorMessage.js +116 -0
  102. package/dist/esm/instrumentations/crashReporting/android/crashErrorMessage.js.map +1 -0
  103. package/dist/esm/instrumentations/crashReporting/android/index.js +4 -0
  104. package/dist/esm/instrumentations/crashReporting/android/index.js.map +1 -0
  105. package/dist/esm/instrumentations/crashReporting/android/nativeTombstoneTrace.js +8 -0
  106. package/dist/esm/instrumentations/crashReporting/android/nativeTombstoneTrace.js.map +1 -0
  107. package/dist/esm/instrumentations/crashReporting/android/parseAndroidCrashTrace.js +174 -0
  108. package/dist/esm/instrumentations/crashReporting/android/parseAndroidCrashTrace.js.map +1 -0
  109. package/dist/esm/instrumentations/crashReporting/index.js +35 -1
  110. package/dist/esm/instrumentations/crashReporting/index.js.map +1 -1
  111. package/dist/esm/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.js +56 -0
  112. package/dist/esm/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.js.map +1 -0
  113. package/dist/esm/instrumentations/crashReporting/ios/crashErrorMessage.js +98 -0
  114. package/dist/esm/instrumentations/crashReporting/ios/crashErrorMessage.js.map +1 -0
  115. package/dist/esm/instrumentations/crashReporting/ios/index.js +4 -0
  116. package/dist/esm/instrumentations/crashReporting/ios/index.js.map +1 -0
  117. package/dist/esm/instrumentations/crashReporting/ios/parseIosCrashTrace.js +44 -0
  118. package/dist/esm/instrumentations/crashReporting/ios/parseIosCrashTrace.js.map +1 -0
  119. package/dist/esm/instrumentations/crashReporting/types.js.map +1 -1
  120. package/dist/esm/instrumentations/errors/index.js +2 -1
  121. package/dist/esm/instrumentations/errors/index.js.map +1 -1
  122. package/dist/esm/instrumentations/session/installationId.js +48 -0
  123. package/dist/esm/instrumentations/session/installationId.js.map +1 -0
  124. package/dist/esm/instrumentations/session/sessionAttributes.js +83 -38
  125. package/dist/esm/instrumentations/session/sessionAttributes.js.map +1 -1
  126. package/dist/esm/metas/appBuildIdentity.js +56 -0
  127. package/dist/esm/metas/appBuildIdentity.js.map +1 -0
  128. package/dist/esm/testUtils/mockDeviceInfo.js +5 -0
  129. package/dist/esm/testUtils/mockDeviceInfo.js.map +1 -1
  130. package/dist/esm/testUtils/setupTests.js +7 -0
  131. package/dist/esm/testUtils/setupTests.js.map +1 -1
  132. package/dist/types/config/makeRNConfig.d.ts +4 -3
  133. package/dist/types/config/types.d.ts +2 -1
  134. package/dist/types/generated/faroRNPackageMeta.d.ts +1 -1
  135. package/dist/types/index.d.ts +2 -2
  136. package/dist/types/initialize.d.ts +4 -2
  137. package/dist/types/instrumentations/anr/anrStack.d.ts +7 -0
  138. package/dist/types/instrumentations/anr/instrumentation.d.ts +23 -28
  139. package/dist/types/instrumentations/anr/types.d.ts +5 -1
  140. package/dist/types/instrumentations/appState/index.d.ts +1 -1
  141. package/dist/types/instrumentations/console/index.d.ts +1 -1
  142. package/dist/types/instrumentations/crashReporting/BaseCrashReportingInstrumentation.d.ts +56 -0
  143. package/dist/types/instrumentations/crashReporting/NoOpCrashReportingInstrumentation.d.ts +12 -0
  144. package/dist/types/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.d.ts +26 -0
  145. package/dist/types/instrumentations/crashReporting/android/crashErrorMessage.d.ts +23 -0
  146. package/dist/types/instrumentations/crashReporting/android/index.d.ts +4 -0
  147. package/dist/types/instrumentations/crashReporting/android/nativeTombstoneTrace.d.ts +2 -0
  148. package/dist/types/instrumentations/crashReporting/android/parseAndroidCrashTrace.d.ts +45 -0
  149. package/dist/types/instrumentations/crashReporting/index.d.ts +25 -2
  150. package/dist/types/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.d.ts +28 -0
  151. package/dist/types/instrumentations/crashReporting/ios/crashErrorMessage.d.ts +14 -0
  152. package/dist/types/instrumentations/crashReporting/ios/index.d.ts +4 -0
  153. package/dist/types/instrumentations/crashReporting/ios/parseIosCrashTrace.d.ts +38 -0
  154. package/dist/types/instrumentations/crashReporting/types.d.ts +18 -51
  155. package/dist/types/instrumentations/frameMonitoring/instrumentation.d.ts +1 -1
  156. package/dist/types/instrumentations/http/index.d.ts +1 -1
  157. package/dist/types/instrumentations/performance/index.d.ts +1 -1
  158. package/dist/types/instrumentations/session/index.d.ts +1 -1
  159. package/dist/types/instrumentations/session/installationId.d.ts +1 -0
  160. package/dist/types/instrumentations/session/sessionAttributes.d.ts +13 -4
  161. package/dist/types/instrumentations/startup/index.d.ts +1 -1
  162. package/dist/types/instrumentations/userActions/index.d.ts +1 -1
  163. package/dist/types/instrumentations/view/index.d.ts +1 -1
  164. package/dist/types/instrumentations/xhr/index.d.ts +1 -1
  165. package/dist/types/metas/appBuildIdentity.d.ts +16 -0
  166. package/dist/types/testUtils/mockFaroReactNativeTracing.d.ts +1 -1
  167. package/dist/types/transports/console/transport.d.ts +1 -1
  168. package/dist/types/transports/fetch/transport.d.ts +1 -1
  169. package/dist/types/transports/offline/transport.d.ts +1 -1
  170. package/package.json +3 -3
  171. package/src/config/getRNInstrumentations.ts +5 -1
  172. package/src/config/makeRNConfig.test.ts +59 -3
  173. package/src/config/makeRNConfig.ts +48 -9
  174. package/src/config/types.ts +2 -1
  175. package/src/generated/faroRNPackageMeta.ts +1 -1
  176. package/src/index.ts +2 -1
  177. package/src/initialize.test.ts +71 -15
  178. package/src/initialize.ts +11 -5
  179. package/src/instrumentations/anr/anrStack.test.ts +27 -0
  180. package/src/instrumentations/anr/anrStack.ts +19 -0
  181. package/src/instrumentations/anr/instrumentation.test.ts +45 -0
  182. package/src/instrumentations/anr/instrumentation.ts +301 -67
  183. package/src/instrumentations/anr/types.ts +7 -1
  184. package/src/instrumentations/console/index.ts +5 -1
  185. package/src/instrumentations/console/instrumentation.test.ts +5 -0
  186. package/src/instrumentations/crashReporting/{instrumentation.ts → BaseCrashReportingInstrumentation.ts} +119 -93
  187. package/src/instrumentations/crashReporting/NoOpCrashReportingInstrumentation.ts +23 -0
  188. package/src/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.ts +62 -0
  189. package/src/instrumentations/crashReporting/android/crashErrorMessage.test.ts +182 -0
  190. package/src/instrumentations/crashReporting/android/crashErrorMessage.ts +135 -0
  191. package/src/instrumentations/crashReporting/android/index.ts +4 -0
  192. package/src/instrumentations/crashReporting/android/nativeTombstoneTrace.test.ts +19 -0
  193. package/src/instrumentations/crashReporting/android/nativeTombstoneTrace.ts +8 -0
  194. package/src/instrumentations/crashReporting/android/parseAndroidCrashTrace.test.ts +232 -0
  195. package/src/instrumentations/crashReporting/android/parseAndroidCrashTrace.ts +235 -0
  196. package/src/instrumentations/crashReporting/index.ts +43 -2
  197. package/src/instrumentations/crashReporting/instrumentation.test.ts +42 -0
  198. package/src/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.ts +62 -0
  199. package/src/instrumentations/crashReporting/ios/crashErrorMessage.test.ts +170 -0
  200. package/src/instrumentations/crashReporting/ios/crashErrorMessage.ts +111 -0
  201. package/src/instrumentations/crashReporting/ios/index.ts +4 -0
  202. package/src/instrumentations/crashReporting/ios/parseIosCrashTrace.test.ts +86 -0
  203. package/src/instrumentations/crashReporting/ios/parseIosCrashTrace.ts +83 -0
  204. package/src/instrumentations/crashReporting/types.ts +19 -58
  205. package/src/instrumentations/errors/index.ts +2 -1
  206. package/src/instrumentations/errors/instrumentation.test.ts +8 -2
  207. package/src/instrumentations/errors/stackTraceParser.test.ts +1 -1
  208. package/src/instrumentations/session/installationId.ts +43 -0
  209. package/src/instrumentations/session/sessionAttributes.test.ts +260 -30
  210. package/src/instrumentations/session/sessionAttributes.ts +112 -22
  211. package/src/metas/appBuildIdentity.test.ts +48 -0
  212. package/src/metas/appBuildIdentity.ts +50 -0
  213. package/src/testUtils/mockDeviceInfo.ts +5 -0
  214. package/src/testUtils/setupTests.ts +7 -0
  215. package/dist/cjs/instrumentations/crashReporting/instrumentation.js.map +0 -1
  216. package/dist/esm/instrumentations/crashReporting/instrumentation.js.map +0 -1
  217. package/dist/types/instrumentations/crashReporting/instrumentation.d.ts +0 -58
@@ -14,6 +14,17 @@ var __extends = (this && this.__extends) || (function () {
14
14
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
15
  };
16
16
  })();
17
+ var __assign = (this && this.__assign) || function () {
18
+ __assign = Object.assign || function(t) {
19
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
20
+ s = arguments[i];
21
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
22
+ t[p] = s[p];
23
+ }
24
+ return t;
25
+ };
26
+ return __assign.apply(this, arguments);
27
+ };
17
28
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
18
29
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
19
30
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -54,43 +65,31 @@ Object.defineProperty(exports, "__esModule", { value: true });
54
65
  exports.ANRInstrumentation = void 0;
55
66
  var react_native_1 = require("react-native");
56
67
  var faro_core_1 = require("@grafana/faro-core");
68
+ var android_1 = require("../crashReporting/android");
57
69
  var const_1 = require("../errors/const");
70
+ var anrStack_1 = require("./anrStack");
58
71
  /**
59
72
  * Default timeout for ANR detection (5 seconds, matching Android's threshold)
60
73
  */
61
74
  var DEFAULT_TIMEOUT = 5000;
62
75
  /**
63
- * Default polling interval for ANR status (60 seconds, matching Flutter SDK)
76
+ * Default polling interval for ANR status. Kept short so debug ANRs surface without
77
+ * waiting a full minute; native also emits onANRDetected for immediate delivery.
64
78
  */
65
- var DEFAULT_POLLING_INTERVAL = 60000;
79
+ var DEFAULT_POLLING_INTERVAL = 10000;
80
+ /** Aligns with native FaroAnrCache.MAX_TIMESTAMP_DELTA_MS */
81
+ var TIMESTAMP_DEDUP_WINDOW_MS = 10000;
82
+ /** ApplicationExitInfo ANR traces (Android 11 / API 30+). */
83
+ var APP_EXIT_INFO_MIN_SDK = 30;
66
84
  /**
67
85
  * ANR (Application Not Responding) Detection Instrumentation.
68
86
  *
69
- * Detects when the main/UI thread is blocked for extended periods on Android.
70
- * Uses a background thread that posts tasks to the main thread and monitors
71
- * if they complete within the timeout.
72
- *
73
- * **Note**: ANR detection is only available on Android. iOS does not have
74
- * the same ANR concept as Android's system watchdog.
75
- *
76
- * Sends telemetry via Faro API:
77
- * - Measurement: `anr` with `anr_count` value (for dashboards)
78
- * - Error: Each ANR with `type: 'ANR'`, stack trace, duration, timestamp (Sentry-aligned)
87
+ * On Android 11+, historical ANRs are read from ApplicationExitInfo (Sentry AnrV2
88
+ * style) on the next launch. ANRTracker remains a pre-API-30 fallback and a
89
+ * persistence backup when the OS trace stream is empty.
79
90
  *
80
- * @example
81
- * ```typescript
82
- * import { initializeFaro, ANRInstrumentation } from '@grafana/faro-react-native';
83
- *
84
- * initializeFaro({
85
- * url: 'https://collector.example.com',
86
- * instrumentations: [
87
- * new ANRInstrumentation({
88
- * timeout: 5000, // 5 second threshold
89
- * pollingInterval: 60000, // Poll every 60 seconds
90
- * }),
91
- * ],
92
- * });
93
- * ```
91
+ * ANRs stay out of CrashReportingInstrumentation so they are not replayed as
92
+ * generic previous-session `crash` rows with empty messages.
94
93
  */
95
94
  var ANRInstrumentation = /** @class */ (function (_super) {
96
95
  __extends(ANRInstrumentation, _super);
@@ -101,15 +100,17 @@ var ANRInstrumentation = /** @class */ (function (_super) {
101
100
  _this.name = '@grafana/faro-react-native:instrumentation-anr';
102
101
  _this.version = faro_core_1.VERSION;
103
102
  _this.pollingIntervalId = null;
103
+ _this.anrEventSubscription = null;
104
+ _this.reportedAnrTimestamps = new Set();
104
105
  _this.options = {
105
106
  timeout: (_a = options.timeout) !== null && _a !== void 0 ? _a : DEFAULT_TIMEOUT,
106
107
  pollingInterval: (_b = options.pollingInterval) !== null && _b !== void 0 ? _b : DEFAULT_POLLING_INTERVAL,
107
108
  };
109
+ _this.preferAppExitInfoAnr = react_native_1.Platform.OS === 'android' && Number(react_native_1.Platform.Version) >= APP_EXIT_INFO_MIN_SDK;
108
110
  return _this;
109
111
  }
110
112
  ANRInstrumentation.prototype.initialize = function () {
111
113
  var _this = this;
112
- // ANR detection is only available on Android
113
114
  if (react_native_1.Platform.OS !== 'android') {
114
115
  this.logDebug('ANR detection is only available on Android');
115
116
  return;
@@ -120,11 +121,15 @@ var ANRInstrumentation = /** @class */ (function (_super) {
120
121
  return;
121
122
  }
122
123
  this.logDebug('Initializing ANR detection instrumentation');
123
- // Start native ANR tracking
124
+ void this.drainAllAnrSources(nativeModule);
124
125
  this.startNativeTracking(nativeModule);
125
- // Set up polling for ANR status
126
+ var emitter = new react_native_1.NativeEventEmitter(nativeModule);
127
+ this.anrEventSubscription = emitter.addListener('onANRDetected', function (anrJson) {
128
+ void _this.handleLiveAnrEvent(nativeModule, anrJson);
129
+ });
130
+ void this.checkANRStatus(nativeModule);
126
131
  this.pollingIntervalId = setInterval(function () {
127
- _this.checkANRStatus(nativeModule);
132
+ void _this.checkANRStatus(nativeModule);
128
133
  }, this.options.pollingInterval);
129
134
  };
130
135
  ANRInstrumentation.prototype.getNativeModule = function () {
@@ -147,73 +152,370 @@ var ANRInstrumentation = /** @class */ (function (_super) {
147
152
  this.logError('Failed to start native ANR tracking', error);
148
153
  }
149
154
  };
150
- ANRInstrumentation.prototype.checkANRStatus = function (nativeModule) {
155
+ ANRInstrumentation.prototype.drainAllAnrSources = function (nativeModule) {
156
+ return __awaiter(this, void 0, void 0, function () {
157
+ return __generator(this, function (_a) {
158
+ switch (_a.label) {
159
+ case 0: return [4 /*yield*/, this.drainHistoricalAnrs(nativeModule)];
160
+ case 1:
161
+ _a.sent();
162
+ return [4 /*yield*/, this.drainPendingANRs(nativeModule)];
163
+ case 2:
164
+ _a.sent();
165
+ return [2 /*return*/];
166
+ }
167
+ });
168
+ });
169
+ };
170
+ ANRInstrumentation.prototype.drainHistoricalAnrs = function (nativeModule) {
151
171
  return __awaiter(this, void 0, void 0, function () {
152
- var anrList, _i, anrList_1, anrJson, anr, error_1;
172
+ var anrList, ackTimestamps, reportedCount, _i, anrList_1, anrJson, anr, error_1, error_2;
153
173
  return __generator(this, function (_a) {
154
174
  switch (_a.label) {
155
175
  case 0:
156
- _a.trys.push([0, 2, , 3]);
157
- if (typeof nativeModule.getANRStatus !== 'function') {
176
+ if (typeof nativeModule.getHistoricalAnrReports !== 'function') {
158
177
  return [2 /*return*/];
159
178
  }
160
- return [4 /*yield*/, nativeModule.getANRStatus()];
179
+ _a.label = 1;
161
180
  case 1:
181
+ _a.trys.push([1, 9, , 10]);
182
+ return [4 /*yield*/, nativeModule.getHistoricalAnrReports()];
183
+ case 2:
162
184
  anrList = (_a.sent());
163
- if (anrList && anrList.length > 0) {
164
- // Push measurement for ANR count (matching Flutter pattern)
185
+ if (!(anrList === null || anrList === void 0 ? void 0 : anrList.length)) {
186
+ return [2 /*return*/];
187
+ }
188
+ ackTimestamps = [];
189
+ reportedCount = 0;
190
+ _i = 0, anrList_1 = anrList;
191
+ _a.label = 3;
192
+ case 3:
193
+ if (!(_i < anrList_1.length)) return [3 /*break*/, 8];
194
+ anrJson = anrList_1[_i];
195
+ _a.label = 4;
196
+ case 4:
197
+ _a.trys.push([4, 6, , 7]);
198
+ anr = JSON.parse(anrJson);
199
+ if (this.reportANRIfNew(anr)) {
200
+ reportedCount += 1;
201
+ }
202
+ ackTimestamps.push(anr.timestamp);
203
+ return [4 /*yield*/, this.acknowledgeNearbyPendingAnrs(nativeModule, anr.timestamp)];
204
+ case 5:
205
+ _a.sent();
206
+ return [3 /*break*/, 7];
207
+ case 6:
208
+ error_1 = _a.sent();
209
+ this.logError('Failed to parse historical ANR report', error_1);
210
+ return [3 /*break*/, 7];
211
+ case 7:
212
+ _i++;
213
+ return [3 /*break*/, 3];
214
+ case 8:
215
+ if (reportedCount > 0) {
165
216
  this.api.pushMeasurement({
166
217
  type: 'anr',
167
- values: { anr_count: anrList.length },
218
+ values: { anr_count: reportedCount },
168
219
  }, { skipDedupe: true });
169
- // Push each ANR as an error with type='ANR' for filtering (Sentry-aligned)
170
- for (_i = 0, anrList_1 = anrList; _i < anrList_1.length; _i++) {
171
- anrJson = anrList_1[_i];
172
- try {
173
- anr = JSON.parse(anrJson);
174
- this.api.pushError(new Error('ANR (Application Not Responding)'), {
175
- context: {
176
- duration: String(anr.duration),
177
- mechanism: const_1.ErrorMechanism.ANR,
178
- stacktrace: anr.stacktrace,
179
- timestamp: String(anr.timestamp),
180
- },
181
- type: 'ANR',
182
- });
183
- }
184
- catch (_b) {
185
- // If parsing fails, still log the raw ANR
186
- this.api.pushError(new Error('ANR (Application Not Responding)'), {
187
- context: {
188
- mechanism: const_1.ErrorMechanism.ANR,
189
- raw: anrJson,
190
- },
191
- type: 'ANR',
192
- });
220
+ this.logDebug("Reported ".concat(reportedCount, " historical ANR event(s) from ApplicationExitInfo"));
221
+ }
222
+ return [3 /*break*/, 10];
223
+ case 9:
224
+ error_2 = _a.sent();
225
+ this.logError('Failed to drain historical ANRs', error_2);
226
+ return [3 /*break*/, 10];
227
+ case 10: return [2 /*return*/];
228
+ }
229
+ });
230
+ });
231
+ };
232
+ ANRInstrumentation.prototype.drainPendingANRs = function (nativeModule) {
233
+ return __awaiter(this, void 0, void 0, function () {
234
+ var anrList;
235
+ return __generator(this, function (_a) {
236
+ switch (_a.label) {
237
+ case 0: return [4 /*yield*/, this.fetchPendingANRs(nativeModule)];
238
+ case 1:
239
+ anrList = _a.sent();
240
+ if (!(anrList === null || anrList === void 0 ? void 0 : anrList.length)) {
241
+ return [2 /*return*/];
242
+ }
243
+ return [4 /*yield*/, this.reportAndAcknowledgePendingANRs(nativeModule, anrList)];
244
+ case 2:
245
+ _a.sent();
246
+ this.logDebug("Processed ".concat(anrList.length, " persisted ANR event(s) from tracker cache"));
247
+ return [2 /*return*/];
248
+ }
249
+ });
250
+ });
251
+ };
252
+ ANRInstrumentation.prototype.handleLiveAnrEvent = function (nativeModule, anrJson) {
253
+ return __awaiter(this, void 0, void 0, function () {
254
+ var anr, error_3;
255
+ return __generator(this, function (_a) {
256
+ switch (_a.label) {
257
+ case 0:
258
+ _a.trys.push([0, 4, , 5]);
259
+ anr = JSON.parse(anrJson);
260
+ if (this.preferAppExitInfoAnr) {
261
+ // Process death + ApplicationExitInfo on next launch delivers the main-thread dump.
262
+ this.logDebug('Deferring live ANR to ApplicationExitInfo on next launch');
263
+ return [2 /*return*/];
264
+ }
265
+ if (!!this.shouldReportTrackerAnr(anr)) return [3 /*break*/, 2];
266
+ return [4 /*yield*/, this.acknowledgeANRs(nativeModule, [anr.timestamp])];
267
+ case 1:
268
+ _a.sent();
269
+ return [2 /*return*/];
270
+ case 2:
271
+ if (this.reportANRIfNew(anr)) {
272
+ this.api.pushMeasurement({
273
+ type: 'anr',
274
+ values: { anr_count: 1 },
275
+ }, { skipDedupe: true });
276
+ }
277
+ return [4 /*yield*/, this.acknowledgeANRs(nativeModule, [anr.timestamp])];
278
+ case 3:
279
+ _a.sent();
280
+ return [3 /*break*/, 5];
281
+ case 4:
282
+ error_3 = _a.sent();
283
+ this.logError('Failed to parse native ANR event', error_3);
284
+ return [3 /*break*/, 5];
285
+ case 5: return [2 /*return*/];
286
+ }
287
+ });
288
+ });
289
+ };
290
+ ANRInstrumentation.prototype.fetchPendingANRs = function (nativeModule) {
291
+ return __awaiter(this, void 0, void 0, function () {
292
+ var error_4;
293
+ return __generator(this, function (_a) {
294
+ switch (_a.label) {
295
+ case 0:
296
+ _a.trys.push([0, 5, , 6]);
297
+ if (!(typeof nativeModule.getPendingANRs === 'function')) return [3 /*break*/, 2];
298
+ return [4 /*yield*/, nativeModule.getPendingANRs()];
299
+ case 1: return [2 /*return*/, (_a.sent())];
300
+ case 2:
301
+ if (!(typeof nativeModule.getANRStatus === 'function')) return [3 /*break*/, 4];
302
+ return [4 /*yield*/, nativeModule.getANRStatus()];
303
+ case 3: return [2 /*return*/, (_a.sent())];
304
+ case 4: return [3 /*break*/, 6];
305
+ case 5:
306
+ error_4 = _a.sent();
307
+ this.logError('Failed to fetch pending ANRs', error_4);
308
+ return [3 /*break*/, 6];
309
+ case 6: return [2 /*return*/, null];
310
+ }
311
+ });
312
+ });
313
+ };
314
+ ANRInstrumentation.prototype.acknowledgeANRs = function (nativeModule, timestamps) {
315
+ return __awaiter(this, void 0, void 0, function () {
316
+ var error_5;
317
+ return __generator(this, function (_a) {
318
+ switch (_a.label) {
319
+ case 0:
320
+ if (!timestamps.length || typeof nativeModule.acknowledgeANRs !== 'function') {
321
+ return [2 /*return*/];
322
+ }
323
+ _a.label = 1;
324
+ case 1:
325
+ _a.trys.push([1, 3, , 4]);
326
+ return [4 /*yield*/, nativeModule.acknowledgeANRs(timestamps)];
327
+ case 2:
328
+ _a.sent();
329
+ return [3 /*break*/, 4];
330
+ case 3:
331
+ error_5 = _a.sent();
332
+ this.logError('Failed to acknowledge ANRs', error_5);
333
+ return [3 /*break*/, 4];
334
+ case 4: return [2 /*return*/];
335
+ }
336
+ });
337
+ });
338
+ };
339
+ ANRInstrumentation.prototype.acknowledgeNearbyPendingAnrs = function (nativeModule, exitTimestamp) {
340
+ return __awaiter(this, void 0, void 0, function () {
341
+ var pending, ackTimestamps, _i, pending_1, anrJson, anr;
342
+ return __generator(this, function (_a) {
343
+ switch (_a.label) {
344
+ case 0: return [4 /*yield*/, this.fetchPendingANRs(nativeModule)];
345
+ case 1:
346
+ pending = _a.sent();
347
+ if (!(pending === null || pending === void 0 ? void 0 : pending.length)) {
348
+ return [2 /*return*/];
349
+ }
350
+ ackTimestamps = [];
351
+ for (_i = 0, pending_1 = pending; _i < pending_1.length; _i++) {
352
+ anrJson = pending_1[_i];
353
+ try {
354
+ anr = JSON.parse(anrJson);
355
+ if (this.isNearbyTimestamp(anr.timestamp, exitTimestamp)) {
356
+ ackTimestamps.push(anr.timestamp);
193
357
  }
194
358
  }
195
- this.logDebug("Recorded ".concat(anrList.length, " ANR event(s)"));
359
+ catch (_b) {
360
+ // ignore malformed cache entries
361
+ }
196
362
  }
197
- return [3 /*break*/, 3];
363
+ if (!(ackTimestamps.length > 0)) return [3 /*break*/, 3];
364
+ return [4 /*yield*/, this.acknowledgeANRs(nativeModule, ackTimestamps)];
198
365
  case 2:
199
- error_1 = _a.sent();
200
- this.logError('Failed to check ANR status', error_1);
201
- return [3 /*break*/, 3];
366
+ _a.sent();
367
+ _a.label = 3;
202
368
  case 3: return [2 /*return*/];
203
369
  }
204
370
  });
205
371
  });
206
372
  };
207
- /**
208
- * Clean up resources when instrumentation is disabled.
209
- */
373
+ ANRInstrumentation.prototype.reportAndAcknowledgePendingANRs = function (nativeModule, anrList) {
374
+ return __awaiter(this, void 0, void 0, function () {
375
+ var ackTimestamps, reportedCount, _i, anrList_2, anrJson, anr, error;
376
+ return __generator(this, function (_a) {
377
+ switch (_a.label) {
378
+ case 0:
379
+ ackTimestamps = [];
380
+ reportedCount = 0;
381
+ for (_i = 0, anrList_2 = anrList; _i < anrList_2.length; _i++) {
382
+ anrJson = anrList_2[_i];
383
+ try {
384
+ anr = JSON.parse(anrJson);
385
+ if (this.shouldReportTrackerAnr(anr) && this.reportANRIfNew(anr)) {
386
+ reportedCount += 1;
387
+ }
388
+ ackTimestamps.push(anr.timestamp);
389
+ }
390
+ catch (_b) {
391
+ error = new Error('ANR (Application Not Responding)');
392
+ error.stack = undefined;
393
+ this.api.pushError(error, {
394
+ context: {
395
+ mechanism: const_1.ErrorMechanism.ANR,
396
+ raw: anrJson,
397
+ },
398
+ fatal: true,
399
+ type: 'ANR',
400
+ });
401
+ }
402
+ }
403
+ if (reportedCount > 0) {
404
+ this.api.pushMeasurement({
405
+ type: 'anr',
406
+ values: { anr_count: reportedCount },
407
+ }, { skipDedupe: true });
408
+ }
409
+ if (!(ackTimestamps.length > 0)) return [3 /*break*/, 2];
410
+ return [4 /*yield*/, this.acknowledgeANRs(nativeModule, ackTimestamps)];
411
+ case 1:
412
+ _a.sent();
413
+ _a.label = 2;
414
+ case 2: return [2 /*return*/];
415
+ }
416
+ });
417
+ });
418
+ };
419
+ ANRInstrumentation.prototype.shouldReportTrackerAnr = function (anr) {
420
+ if (this.isNearbyReportedTimestamp(anr.timestamp)) {
421
+ return false;
422
+ }
423
+ if ((0, anrStack_1.isInvalidAnrCaptureStack)(anr.stacktrace)) {
424
+ return false;
425
+ }
426
+ // On API 30+, ApplicationExitInfo is preferred on launch; tracker pending entries
427
+ // are reported only when historical did not already cover the same incident.
428
+ return true;
429
+ };
430
+ ANRInstrumentation.prototype.reportANRIfNew = function (anr) {
431
+ if (this.isNearbyReportedTimestamp(anr.timestamp)) {
432
+ return false;
433
+ }
434
+ if ((0, anrStack_1.isInvalidAnrCaptureStack)(anr.stacktrace)) {
435
+ return false;
436
+ }
437
+ this.rememberReportedTimestamp(anr.timestamp);
438
+ this.reportANR(anr);
439
+ return true;
440
+ };
441
+ ANRInstrumentation.prototype.rememberReportedTimestamp = function (timestamp) {
442
+ this.reportedAnrTimestamps.add(timestamp);
443
+ };
444
+ ANRInstrumentation.prototype.isNearbyReportedTimestamp = function (timestamp) {
445
+ for (var _i = 0, _a = Array.from(this.reportedAnrTimestamps); _i < _a.length; _i++) {
446
+ var reported = _a[_i];
447
+ if (this.isNearbyTimestamp(timestamp, reported)) {
448
+ return true;
449
+ }
450
+ }
451
+ return false;
452
+ };
453
+ ANRInstrumentation.prototype.isNearbyTimestamp = function (a, b) {
454
+ if (a <= 0 || b <= 0) {
455
+ return false;
456
+ }
457
+ return Math.abs(a - b) <= TIMESTAMP_DEDUP_WINDOW_MS;
458
+ };
459
+ ANRInstrumentation.prototype.reportANR = function (anr) {
460
+ var _a, _b, _c, _d;
461
+ var rawStacktrace = (_b = (_a = anr.stacktrace) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : '';
462
+ var traceForRetrace = rawStacktrace ? (0, android_1.normalizeJavaStackTraceForRetrace)(rawStacktrace) : '';
463
+ var parsed = traceForRetrace ? (0, android_1.parseAndroidCrashTrace)(traceForRetrace) : null;
464
+ var message = ((_c = anr.description) === null || _c === void 0 ? void 0 : _c.trim()) || 'ANR (Application Not Responding)';
465
+ var error = new Error(message);
466
+ error.stack = undefined;
467
+ var context = {
468
+ duration: String(anr.duration),
469
+ mechanism: const_1.ErrorMechanism.ANR,
470
+ timestamp: String(anr.timestamp),
471
+ };
472
+ if (anr.source) {
473
+ context['source'] = anr.source;
474
+ }
475
+ if (traceForRetrace) {
476
+ context['stacktrace'] = traceForRetrace;
477
+ }
478
+ var stackFrames = (_d = parsed === null || parsed === void 0 ? void 0 : parsed.frames) !== null && _d !== void 0 ? _d : [];
479
+ if (!stackFrames.length && rawStacktrace) {
480
+ this.logWarn('ANR main-thread stack present but no Java/Kotlin frames parsed');
481
+ }
482
+ this.api.pushError(error, __assign({ type: 'ANR', context: context, fatal: true }, (stackFrames.length ? { stackFrames: stackFrames } : {})));
483
+ };
484
+ ANRInstrumentation.prototype.checkANRStatus = function (nativeModule) {
485
+ return __awaiter(this, void 0, void 0, function () {
486
+ var anrList, error_6;
487
+ return __generator(this, function (_a) {
488
+ switch (_a.label) {
489
+ case 0:
490
+ _a.trys.push([0, 4, , 5]);
491
+ return [4 /*yield*/, this.fetchPendingANRs(nativeModule)];
492
+ case 1:
493
+ anrList = _a.sent();
494
+ if (!(anrList && anrList.length > 0)) return [3 /*break*/, 3];
495
+ return [4 /*yield*/, this.reportAndAcknowledgePendingANRs(nativeModule, anrList)];
496
+ case 2:
497
+ _a.sent();
498
+ this.logDebug("Polled ".concat(anrList.length, " ANR event(s) from pending cache"));
499
+ _a.label = 3;
500
+ case 3: return [3 /*break*/, 5];
501
+ case 4:
502
+ error_6 = _a.sent();
503
+ this.logError('Failed to check ANR status', error_6);
504
+ return [3 /*break*/, 5];
505
+ case 5: return [2 /*return*/];
506
+ }
507
+ });
508
+ });
509
+ };
210
510
  ANRInstrumentation.prototype.unpatch = function () {
211
- // Stop polling
511
+ var _a;
212
512
  if (this.pollingIntervalId !== null) {
213
513
  clearInterval(this.pollingIntervalId);
214
514
  this.pollingIntervalId = null;
215
515
  }
216
- // Stop native tracking
516
+ (_a = this.anrEventSubscription) === null || _a === void 0 ? void 0 : _a.remove();
517
+ this.anrEventSubscription = null;
518
+ this.reportedAnrTimestamps.clear();
217
519
  if (react_native_1.Platform.OS === 'android') {
218
520
  var nativeModule = this.getNativeModule();
219
521
  if (nativeModule && typeof nativeModule.stopANRTracking === 'function') {
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentation.js","sourceRoot":"","sources":["../../../../src/instrumentations/anr/instrumentation.ts"],"names":[],"mappings":"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","sourcesContent":["import { NativeModules, Platform } from 'react-native';\n\nimport { BaseInstrumentation, VERSION } from '@grafana/faro-core';\n\nimport { ErrorMechanism } from '../errors/const';\n\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 (60 seconds, matching Flutter SDK)\n */\nconst DEFAULT_POLLING_INTERVAL = 60000;\n\n/**\n * ANR (Application Not Responding) Detection Instrumentation.\n *\n * Detects when the main/UI thread is blocked for extended periods on Android.\n * Uses a background thread that posts tasks to the main thread and monitors\n * if they complete within the timeout.\n *\n * **Note**: ANR detection is only available on Android. iOS does not have\n * the same ANR concept as Android's system watchdog.\n *\n * Sends telemetry via Faro API:\n * - Measurement: `anr` with `anr_count` value (for dashboards)\n * - Error: Each ANR with `type: 'ANR'`, stack trace, duration, timestamp (Sentry-aligned)\n *\n * @example\n * ```typescript\n * import { initializeFaro, ANRInstrumentation } from '@grafana/faro-react-native';\n *\n * initializeFaro({\n * url: 'https://collector.example.com',\n * instrumentations: [\n * new ANRInstrumentation({\n * timeout: 5000, // 5 second threshold\n * pollingInterval: 60000, // Poll every 60 seconds\n * }),\n * ],\n * });\n * ```\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\n constructor(options: ANRInstrumentationOptions = {}) {\n super();\n this.options = {\n timeout: options.timeout ?? DEFAULT_TIMEOUT,\n pollingInterval: options.pollingInterval ?? DEFAULT_POLLING_INTERVAL,\n };\n }\n\n initialize(): void {\n // ANR detection is only available on Android\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 // Start native ANR tracking\n this.startNativeTracking(nativeModule);\n\n // Set up polling for ANR status\n this.pollingIntervalId = setInterval(() => {\n 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 checkANRStatus(nativeModule: typeof NativeModules.FaroReactNativeModule): Promise<void> {\n try {\n if (typeof nativeModule.getANRStatus !== 'function') {\n return;\n }\n\n const anrList = (await nativeModule.getANRStatus()) as string[] | null;\n\n if (anrList && anrList.length > 0) {\n // Push measurement for ANR count (matching Flutter pattern)\n this.api.pushMeasurement(\n {\n type: 'anr',\n values: { anr_count: anrList.length },\n },\n { skipDedupe: true }\n );\n\n // Push each ANR as an error with type='ANR' for filtering (Sentry-aligned)\n for (const anrJson of anrList) {\n try {\n const anr = JSON.parse(anrJson) as ANREvent;\n\n this.api.pushError(new Error('ANR (Application Not Responding)'), {\n context: {\n duration: String(anr.duration),\n mechanism: ErrorMechanism.ANR,\n stacktrace: anr.stacktrace,\n timestamp: String(anr.timestamp),\n },\n type: 'ANR',\n });\n } catch {\n // If parsing fails, still log the raw ANR\n this.api.pushError(new Error('ANR (Application Not Responding)'), {\n context: {\n mechanism: ErrorMechanism.ANR,\n raw: anrJson,\n },\n type: 'ANR',\n });\n }\n }\n\n this.logDebug(`Recorded ${anrList.length} ANR event(s)`);\n }\n } catch (error) {\n this.logError('Failed to check ANR status', error);\n }\n }\n\n /**\n * Clean up resources when instrumentation is disabled.\n */\n unpatch(): void {\n // Stop polling\n if (this.pollingIntervalId !== null) {\n clearInterval(this.pollingIntervalId);\n this.pollingIntervalId = null;\n }\n\n // Stop native tracking\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', (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 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/instrumentations/anr/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Configuration options for ANR (Application Not Responding) detection.\n */\nexport interface ANRInstrumentationOptions {\n /**\n * Timeout in milliseconds for detecting ANR.\n * If the main thread doesn't respond within this time, an ANR is recorded.\n * Default: 5000 (5 seconds, matching Android's ANR threshold)\n */\n timeout?: number;\n\n /**\n * Interval in milliseconds for polling ANR status from native.\n * Default: 60000 (60 seconds, matching Flutter SDK's default)\n */\n pollingInterval?: number;\n}\n\n/**\n * ANR event data from native module.\n */\nexport interface ANREvent {\n /**\n * Event type (always \"ANR\")\n */\n type: string;\n\n /**\n * Timestamp when ANR was detected\n */\n timestamp: number;\n\n /**\n * Stack trace of the main thread when ANR was detected\n */\n stacktrace: string;\n\n /**\n * Duration of the ANR in milliseconds\n */\n duration: number;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/instrumentations/anr/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Configuration options for ANR (Application Not Responding) detection.\n */\nexport interface ANRInstrumentationOptions {\n /**\n * Timeout in milliseconds for detecting ANR.\n * If the main thread doesn't respond within this time, an ANR is recorded.\n * Default: 5000 (5 seconds, matching Android's ANR threshold)\n */\n timeout?: number;\n\n /**\n * Interval in milliseconds for polling ANR status from native.\n * Default: 10000 (10 seconds). Native also emits onANRDetected immediately.\n */\n pollingInterval?: number;\n}\n\n/**\n * ANR event data from native module.\n */\nexport interface ANREvent {\n /**\n * Event type (always \"ANR\")\n */\n type: string;\n\n /**\n * Timestamp when ANR was detected\n */\n timestamp: number;\n\n /**\n * Stack trace of the main thread when ANR was detected\n */\n stacktrace: string;\n\n /**\n * Duration of the ANR in milliseconds\n */\n duration: number;\n\n /** Human-readable ANR description from ApplicationExitInfo when available. */\n description?: string;\n\n /** `AppExitInfo` (preferred) or `ANRTracker` (fallback). */\n source?: string;\n}\n"]}
@@ -88,12 +88,16 @@ var ConsoleInstrumentation = /** @class */ (function (_super) {
88
88
  var context = { mechanism: const_1.ErrorMechanism.CONSOLE };
89
89
  if (value && !type && !stackFrames) {
90
90
  // Simple error without stack frames
91
- _this.api.pushError(new Error(ConsoleInstrumentation.consoleErrorPrefix + value), { context: context });
91
+ _this.api.pushError(new Error(ConsoleInstrumentation.consoleErrorPrefix + value), {
92
+ context: context,
93
+ fatal: false,
94
+ });
92
95
  }
93
96
  else {
94
97
  // Error with type and/or stack frames (type from error.name, matches Web SDK)
95
98
  _this.api.pushError(new Error(ConsoleInstrumentation.consoleErrorPrefix + (value !== null && value !== void 0 ? value : '')), {
96
99
  context: context,
100
+ fatal: false,
97
101
  type: type,
98
102
  stackFrames: stackFrames,
99
103
  });