@grafana/faro-react-native 1.2.0 → 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 (218) 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/ios/faro-upload-composed-source-map.sh +8 -2
  171. package/package.json +5 -5
  172. package/src/config/getRNInstrumentations.ts +5 -1
  173. package/src/config/makeRNConfig.test.ts +59 -3
  174. package/src/config/makeRNConfig.ts +48 -9
  175. package/src/config/types.ts +2 -1
  176. package/src/generated/faroRNPackageMeta.ts +1 -1
  177. package/src/index.ts +2 -1
  178. package/src/initialize.test.ts +71 -15
  179. package/src/initialize.ts +11 -5
  180. package/src/instrumentations/anr/anrStack.test.ts +27 -0
  181. package/src/instrumentations/anr/anrStack.ts +19 -0
  182. package/src/instrumentations/anr/instrumentation.test.ts +45 -0
  183. package/src/instrumentations/anr/instrumentation.ts +301 -67
  184. package/src/instrumentations/anr/types.ts +7 -1
  185. package/src/instrumentations/console/index.ts +5 -1
  186. package/src/instrumentations/console/instrumentation.test.ts +5 -0
  187. package/src/instrumentations/crashReporting/{instrumentation.ts → BaseCrashReportingInstrumentation.ts} +119 -93
  188. package/src/instrumentations/crashReporting/NoOpCrashReportingInstrumentation.ts +23 -0
  189. package/src/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.ts +62 -0
  190. package/src/instrumentations/crashReporting/android/crashErrorMessage.test.ts +182 -0
  191. package/src/instrumentations/crashReporting/android/crashErrorMessage.ts +135 -0
  192. package/src/instrumentations/crashReporting/android/index.ts +4 -0
  193. package/src/instrumentations/crashReporting/android/nativeTombstoneTrace.test.ts +19 -0
  194. package/src/instrumentations/crashReporting/android/nativeTombstoneTrace.ts +8 -0
  195. package/src/instrumentations/crashReporting/android/parseAndroidCrashTrace.test.ts +232 -0
  196. package/src/instrumentations/crashReporting/android/parseAndroidCrashTrace.ts +235 -0
  197. package/src/instrumentations/crashReporting/index.ts +43 -2
  198. package/src/instrumentations/crashReporting/instrumentation.test.ts +42 -0
  199. package/src/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.ts +62 -0
  200. package/src/instrumentations/crashReporting/ios/crashErrorMessage.test.ts +170 -0
  201. package/src/instrumentations/crashReporting/ios/crashErrorMessage.ts +111 -0
  202. package/src/instrumentations/crashReporting/ios/index.ts +4 -0
  203. package/src/instrumentations/crashReporting/ios/parseIosCrashTrace.test.ts +86 -0
  204. package/src/instrumentations/crashReporting/ios/parseIosCrashTrace.ts +83 -0
  205. package/src/instrumentations/crashReporting/types.ts +19 -58
  206. package/src/instrumentations/errors/index.ts +2 -1
  207. package/src/instrumentations/errors/instrumentation.test.ts +8 -2
  208. package/src/instrumentations/errors/stackTraceParser.test.ts +1 -1
  209. package/src/instrumentations/session/installationId.ts +43 -0
  210. package/src/instrumentations/session/sessionAttributes.test.ts +260 -30
  211. package/src/instrumentations/session/sessionAttributes.ts +112 -22
  212. package/src/metas/appBuildIdentity.test.ts +48 -0
  213. package/src/metas/appBuildIdentity.ts +50 -0
  214. package/src/testUtils/mockDeviceInfo.ts +5 -0
  215. package/src/testUtils/setupTests.ts +7 -0
  216. package/dist/cjs/instrumentations/crashReporting/instrumentation.js.map +0 -1
  217. package/dist/esm/instrumentations/crashReporting/instrumentation.js.map +0 -1
  218. package/dist/types/instrumentations/crashReporting/instrumentation.d.ts +0 -58
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveCrashErrorMessage = resolveCrashErrorMessage;
4
+ exports.isAnrTimeoutDescription = isAnrTimeoutDescription;
5
+ exports.shouldSkipCrashReport = shouldSkipCrashReport;
6
+ exports.shouldSkipLowSignalCrashReport = shouldSkipLowSignalCrashReport;
7
+ exports.buildFallbackCrashMessage = buildFallbackCrashMessage;
8
+ var parseAndroidCrashTrace_1 = require("./parseAndroidCrashTrace");
9
+ /**
10
+ * Human-readable exception value for ApplicationExitInfo crash reports.
11
+ * Priority: parsed trace message → exception class → description → generic fallback.
12
+ */
13
+ function resolveCrashErrorMessage(crash, parsedTrace) {
14
+ var _a, _b, _c;
15
+ var fromTrace = (_a = parsedTrace === null || parsedTrace === void 0 ? void 0 : parsedTrace.exceptionMessage) === null || _a === void 0 ? void 0 : _a.trim();
16
+ if (fromTrace) {
17
+ return fromTrace;
18
+ }
19
+ var fromType = (_b = parsedTrace === null || parsedTrace === void 0 ? void 0 : parsedTrace.exceptionType) === null || _b === void 0 ? void 0 : _b.trim();
20
+ if (fromType && (0, parseAndroidCrashTrace_1.isPlausibleJavaExceptionIdentifier)(fromType)) {
21
+ return fromType;
22
+ }
23
+ var fromDescriptionType = exceptionTypeFromDescription(crash.description);
24
+ if (fromDescriptionType) {
25
+ return fromDescriptionType;
26
+ }
27
+ var fromDescription = (_c = crash.description) === null || _c === void 0 ? void 0 : _c.trim();
28
+ if (fromDescription && !isGenericCrashDescription(fromDescription)) {
29
+ return fromDescription;
30
+ }
31
+ var fallback = buildFallbackCrashMessage(crash);
32
+ return fallback.trim() || crash.reason || 'Application crash';
33
+ }
34
+ var ANR_TIMEOUT_DESCRIPTION_PATTERN = /input dispatching timed out|not responding|application not responding/i;
35
+ /**
36
+ * Android ANR watchdog descriptions from ApplicationExitInfo (any app).
37
+ */
38
+ function isAnrTimeoutDescription(description) {
39
+ var trimmed = description === null || description === void 0 ? void 0 : description.trim();
40
+ if (!trimmed) {
41
+ return false;
42
+ }
43
+ return ANR_TIMEOUT_DESCRIPTION_PATTERN.test(trimmed);
44
+ }
45
+ /**
46
+ * Skip duplicate ApplicationExitInfo rows that have no stack and no useful title,
47
+ * and ANR incidents mis-tagged as previous-session crashes.
48
+ */
49
+ function shouldSkipCrashReport(crash) {
50
+ if (isAnrTimeoutDescription(crash.description)) {
51
+ return true;
52
+ }
53
+ return shouldSkipLowSignalCrashReport(crash);
54
+ }
55
+ /**
56
+ * Skip duplicate ApplicationExitInfo rows that have no stack and no useful title.
57
+ * These surface in the plugin as a second generic `crash` row for a single button press.
58
+ */
59
+ function shouldSkipLowSignalCrashReport(crash) {
60
+ var _a, _b;
61
+ if ((_a = crash.trace) === null || _a === void 0 ? void 0 : _a.trim()) {
62
+ return false;
63
+ }
64
+ var description = (_b = crash.description) === null || _b === void 0 ? void 0 : _b.trim();
65
+ if (description && !isGenericCrashDescription(description)) {
66
+ return false;
67
+ }
68
+ return true;
69
+ }
70
+ /** Extract `java.lang.NullPointerException` from ApplicationExitInfo description text. */
71
+ function exceptionTypeFromDescription(description) {
72
+ var _a;
73
+ var trimmed = description === null || description === void 0 ? void 0 : description.trim();
74
+ if (!trimmed || isGenericCrashDescription(trimmed)) {
75
+ return undefined;
76
+ }
77
+ var match = trimmed.match(/^([\w.$]+)(?::(.*))?$/);
78
+ var candidate = (_a = match === null || match === void 0 ? void 0 : match[1]) === null || _a === void 0 ? void 0 : _a.trim();
79
+ if (!candidate || !(0, parseAndroidCrashTrace_1.isPlausibleJavaExceptionIdentifier)(candidate)) {
80
+ return undefined;
81
+ }
82
+ return candidate;
83
+ }
84
+ function isGenericCrashDescription(description) {
85
+ var normalized = description.trim().toLowerCase();
86
+ return (normalized === 'crash' ||
87
+ normalized === 'native crash' ||
88
+ normalized === 'application crash' ||
89
+ normalized === 'application crash (java/kotlin)' ||
90
+ normalized === 'application crash (native)');
91
+ }
92
+ /** Generic fallback when the trace carries no parseable message or type. */
93
+ function buildFallbackCrashMessage(crash) {
94
+ var _a;
95
+ var reason = crash.reason || 'UNKNOWN';
96
+ var status = (_a = crash.status) !== null && _a !== void 0 ? _a : 0;
97
+ var description;
98
+ switch (crash.reason) {
99
+ case 'ANR':
100
+ description = 'Application Not Responding';
101
+ break;
102
+ case 'CRASH':
103
+ description = 'Application crash (Java/Kotlin)';
104
+ break;
105
+ case 'CRASH_NATIVE':
106
+ description = 'Application crash (Native)';
107
+ break;
108
+ case 'LOW_MEMORY':
109
+ description = 'Application terminated due to low memory';
110
+ break;
111
+ case 'EXCESSIVE_RESOURCE_USAGE':
112
+ description = 'Application terminated due to excessive resource usage';
113
+ break;
114
+ case 'INITIALIZATION_FAILURE':
115
+ description = 'Application failed to initialize';
116
+ break;
117
+ default:
118
+ description = crash.description || 'Application crash';
119
+ break;
120
+ }
121
+ return "".concat(reason, ": ").concat(description, ", status: ").concat(status);
122
+ }
123
+ //# sourceMappingURL=crashErrorMessage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crashErrorMessage.js","sourceRoot":"","sources":["../../../../../src/instrumentations/crashReporting/android/crashErrorMessage.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CrashReport } from '../types';\n\nimport { isPlausibleJavaExceptionIdentifier } from './parseAndroidCrashTrace';\nimport type { ParsedAndroidCrashTrace } from './parseAndroidCrashTrace';\n\n/**\n * Human-readable exception value for ApplicationExitInfo crash reports.\n * Priority: parsed trace message → exception class → description → generic fallback.\n */\nexport function resolveCrashErrorMessage(crash: CrashReport, parsedTrace: ParsedAndroidCrashTrace | null): string {\n const fromTrace = parsedTrace?.exceptionMessage?.trim();\n if (fromTrace) {\n return fromTrace;\n }\n\n const fromType = parsedTrace?.exceptionType?.trim();\n if (fromType && isPlausibleJavaExceptionIdentifier(fromType)) {\n return fromType;\n }\n\n const fromDescriptionType = exceptionTypeFromDescription(crash.description);\n if (fromDescriptionType) {\n return fromDescriptionType;\n }\n\n const fromDescription = crash.description?.trim();\n if (fromDescription && !isGenericCrashDescription(fromDescription)) {\n return fromDescription;\n }\n\n const fallback = buildFallbackCrashMessage(crash);\n return fallback.trim() || crash.reason || 'Application crash';\n}\n\nconst ANR_TIMEOUT_DESCRIPTION_PATTERN = /input dispatching timed out|not responding|application not responding/i;\n\n/**\n * Android ANR watchdog descriptions from ApplicationExitInfo (any app).\n */\nexport function isAnrTimeoutDescription(description: string | undefined): boolean {\n const trimmed = description?.trim();\n if (!trimmed) {\n return false;\n }\n return ANR_TIMEOUT_DESCRIPTION_PATTERN.test(trimmed);\n}\n\n/**\n * Skip duplicate ApplicationExitInfo rows that have no stack and no useful title,\n * and ANR incidents mis-tagged as previous-session crashes.\n */\nexport function shouldSkipCrashReport(crash: CrashReport): boolean {\n if (isAnrTimeoutDescription(crash.description)) {\n return true;\n }\n\n return shouldSkipLowSignalCrashReport(crash);\n}\n\n/**\n * Skip duplicate ApplicationExitInfo rows that have no stack and no useful title.\n * These surface in the plugin as a second generic `crash` row for a single button press.\n */\nexport function shouldSkipLowSignalCrashReport(crash: CrashReport): boolean {\n if (crash.trace?.trim()) {\n return false;\n }\n\n const description = crash.description?.trim();\n if (description && !isGenericCrashDescription(description)) {\n return false;\n }\n\n return true;\n}\n\n/** Extract `java.lang.NullPointerException` from ApplicationExitInfo description text. */\nfunction exceptionTypeFromDescription(description: string | undefined): string | undefined {\n const trimmed = description?.trim();\n if (!trimmed || isGenericCrashDescription(trimmed)) {\n return undefined;\n }\n\n const match = trimmed.match(/^([\\w.$]+)(?::(.*))?$/);\n const candidate = match?.[1]?.trim();\n if (!candidate || !isPlausibleJavaExceptionIdentifier(candidate)) {\n return undefined;\n }\n\n return candidate;\n}\n\nfunction isGenericCrashDescription(description: string): boolean {\n const normalized = description.trim().toLowerCase();\n return (\n normalized === 'crash' ||\n normalized === 'native crash' ||\n normalized === 'application crash' ||\n normalized === 'application crash (java/kotlin)' ||\n normalized === 'application crash (native)'\n );\n}\n\n/** Generic fallback when the trace carries no parseable message or type. */\nexport function buildFallbackCrashMessage(crash: CrashReport): string {\n const reason = crash.reason || 'UNKNOWN';\n const status = crash.status ?? 0;\n\n let description: string;\n switch (crash.reason) {\n case 'ANR':\n description = 'Application Not Responding';\n break;\n case 'CRASH':\n description = 'Application crash (Java/Kotlin)';\n break;\n case 'CRASH_NATIVE':\n description = 'Application crash (Native)';\n break;\n case 'LOW_MEMORY':\n description = 'Application terminated due to low memory';\n break;\n case 'EXCESSIVE_RESOURCE_USAGE':\n description = 'Application terminated due to excessive resource usage';\n break;\n case 'INITIALIZATION_FAILURE':\n description = 'Application failed to initialize';\n break;\n default:\n description = crash.description || 'Application crash';\n break;\n }\n\n return `${reason}: ${description}, status: ${status}`;\n}\n"]}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.shouldSkipCrashReport = exports.resolveCrashErrorMessage = exports.normalizeJavaStackTraceForRetrace = exports.parseAndroidCrashTrace = exports.AndroidCrashReportingInstrumentation = void 0;
4
+ var AndroidCrashReportingInstrumentation_1 = require("./AndroidCrashReportingInstrumentation");
5
+ Object.defineProperty(exports, "AndroidCrashReportingInstrumentation", { enumerable: true, get: function () { return AndroidCrashReportingInstrumentation_1.AndroidCrashReportingInstrumentation; } });
6
+ var parseAndroidCrashTrace_1 = require("./parseAndroidCrashTrace");
7
+ Object.defineProperty(exports, "parseAndroidCrashTrace", { enumerable: true, get: function () { return parseAndroidCrashTrace_1.parseAndroidCrashTrace; } });
8
+ Object.defineProperty(exports, "normalizeJavaStackTraceForRetrace", { enumerable: true, get: function () { return parseAndroidCrashTrace_1.normalizeJavaStackTraceForRetrace; } });
9
+ var crashErrorMessage_1 = require("./crashErrorMessage");
10
+ Object.defineProperty(exports, "resolveCrashErrorMessage", { enumerable: true, get: function () { return crashErrorMessage_1.resolveCrashErrorMessage; } });
11
+ Object.defineProperty(exports, "shouldSkipCrashReport", { enumerable: true, get: function () { return crashErrorMessage_1.shouldSkipCrashReport; } });
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/instrumentations/crashReporting/android/index.ts"],"names":[],"mappings":";;;AAAA,+FAA8F;AAArF,4JAAA,oCAAoC,OAAA;AAC7C,mEAAqG;AAA5F,gIAAA,sBAAsB,OAAA;AAAE,2IAAA,iCAAiC,OAAA;AAElE,yDAAsF;AAA7E,6HAAA,wBAAwB,OAAA;AAAE,0HAAA,qBAAqB,OAAA","sourcesContent":["export { AndroidCrashReportingInstrumentation } from './AndroidCrashReportingInstrumentation';\nexport { parseAndroidCrashTrace, normalizeJavaStackTraceForRetrace } from './parseAndroidCrashTrace';\nexport type { ParsedAndroidCrashTrace, AndroidCrashStackFrame } from './parseAndroidCrashTrace';\nexport { resolveCrashErrorMessage, shouldSkipCrashReport } from './crashErrorMessage';\n"]}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.looksLikeNativeTombstoneTrace = looksLikeNativeTombstoneTrace;
4
+ /** Detect Android tombstone backtrace lines used for NDK native retrace. */
5
+ function looksLikeNativeTombstoneTrace(trace) {
6
+ if (!(trace === null || trace === void 0 ? void 0 : trace.trim())) {
7
+ return false;
8
+ }
9
+ return trace.split('\n').some(function (line) { return /^\s*#\d+\s+pc\s+(?:0x)?[0-9a-fA-F]+\s+\S+/i.test(line); });
10
+ }
11
+ //# sourceMappingURL=nativeTombstoneTrace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nativeTombstoneTrace.js","sourceRoot":"","sources":["../../../../../src/instrumentations/crashReporting/android/nativeTombstoneTrace.ts"],"names":[],"mappings":";;AACA,sEAMC;AAPD,4EAA4E;AAC5E,SAAgB,6BAA6B,CAAC,KAAyB;IACrE,IAAI,CAAC,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,IAAI,EAAE,CAAA,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAC,IAAI,IAAK,OAAA,4CAA4C,CAAC,IAAI,CAAC,IAAI,CAAC,EAAvD,CAAuD,CAAC,CAAC;AACnG,CAAC","sourcesContent":["/** Detect Android tombstone backtrace lines used for NDK native retrace. */\nexport function looksLikeNativeTombstoneTrace(trace: string | undefined): boolean {\n if (!trace?.trim()) {\n return false;\n }\n\n return trace.split('\\n').some((line) => /^\\s*#\\d+\\s+pc\\s+(?:0x)?[0-9a-fA-F]+\\s+\\S+/i.test(line));\n}\n"]}
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isTombstoneSectionLabel = isTombstoneSectionLabel;
4
+ exports.isPlausibleJavaExceptionIdentifier = isPlausibleJavaExceptionIdentifier;
5
+ exports.normalizeJavaStackTraceForRetrace = normalizeJavaStackTraceForRetrace;
6
+ exports.normalizeCrashTraceExceptionMessage = normalizeCrashTraceExceptionMessage;
7
+ exports.parseAndroidCrashTrace = parseAndroidCrashTrace;
8
+ var stackTraceParser_1 = require("../../errors/stackTraceParser");
9
+ // Mirrors pkg/exporter/androidretrace/mapping.go frameLine / exceptionHeader.
10
+ var FRAME_LINE = /^\s*at\s+([\w$.]+)\.([\w$<>]+)\(([^):]*)(?::(\d+))?\)\s*$/;
11
+ // Thread.getStackTrace() / legacy ANRTracker lines without the "at " prefix.
12
+ var THREAD_STACK_FRAME_LINE = /^\s*([\w$.]+)\.([\w$<>]+)\(([^):]*)(?::(\d+))?\)\s*$/;
13
+ var EXCEPTION_HEADER = /^\s*(?:Caused by:\s*)?([\w$.]+)(?::(.*))?$/;
14
+ // Mirrors pkg/exporter/androidretrace/native_frame.go nativeFrameLine.
15
+ var NATIVE_TOMBSTONE_FRAME_LINE = /^\s*#(\d+)\s+pc\s+(?:0x)?([0-9a-fA-F]+)\s+(\S+)(?:\s+\(([^)]+)\))?/i;
16
+ var TOMBSTONE_SECTION_LABELS = new Set(['backtrace', 'stack', 'build id', 'memory map', 'memory near', 'abi']);
17
+ /** Tombstone section headers and metadata must not become exception_type / nativeExceptionType. */
18
+ function isTombstoneSectionLabel(value) {
19
+ return TOMBSTONE_SECTION_LABELS.has(value.trim().toLowerCase());
20
+ }
21
+ function isTombstoneMetadataLine(line) {
22
+ var trimmed = line.trim();
23
+ if (!trimmed) {
24
+ return true;
25
+ }
26
+ if (trimmed.startsWith('***')) {
27
+ return true;
28
+ }
29
+ if (/^ABI:/i.test(trimmed)) {
30
+ return true;
31
+ }
32
+ if (/^signal\s+/i.test(trimmed)) {
33
+ return true;
34
+ }
35
+ if (/^pid:/i.test(trimmed)) {
36
+ return true;
37
+ }
38
+ if (isTombstoneSectionLabel(trimmed.replace(/:$/, ''))) {
39
+ return true;
40
+ }
41
+ return false;
42
+ }
43
+ function nativeLibBasename(token) {
44
+ var bang = token.lastIndexOf('!');
45
+ if (bang >= 0) {
46
+ token = token.slice(bang + 1);
47
+ }
48
+ var slash = token.lastIndexOf('/');
49
+ return slash >= 0 ? token.slice(slash + 1) : token;
50
+ }
51
+ function parseNativeTombstoneFrameLine(line) {
52
+ var _a, _b;
53
+ var match = line.match(NATIVE_TOMBSTONE_FRAME_LINE);
54
+ if (!match) {
55
+ return null;
56
+ }
57
+ var library = (_a = match[3]) !== null && _a !== void 0 ? _a : '';
58
+ var suffix = (_b = match[4]) === null || _b === void 0 ? void 0 : _b.trim();
59
+ var fn = '<unknown>';
60
+ if (suffix) {
61
+ var fnMatch = suffix.match(/^([A-Za-z_][A-Za-z0-9_]*)(?:\+(\d+))?$/);
62
+ if ((fnMatch === null || fnMatch === void 0 ? void 0 : fnMatch[1]) && fnMatch[1] !== 'BuildId' && fnMatch[1] !== 'offset') {
63
+ fn = fnMatch[1];
64
+ }
65
+ }
66
+ return {
67
+ module: nativeLibBasename(library),
68
+ function: fn,
69
+ filename: nativeLibBasename(library),
70
+ };
71
+ }
72
+ /** Reject version tokens (e.g. "18.2213") and other non-class header lines. */
73
+ function isPlausibleJavaExceptionIdentifier(value) {
74
+ var trimmed = value.trim();
75
+ if (!trimmed || !/[a-zA-Z]/.test(trimmed)) {
76
+ return false;
77
+ }
78
+ if (/^\d+(\.\d+)+$/.test(trimmed)) {
79
+ return false;
80
+ }
81
+ return true;
82
+ }
83
+ /**
84
+ * Normalize raw Java thread stacks (e.g. ANRTracker) to Log.getStackTraceString shape
85
+ * so collector R8 retrace (mapping.RetraceText) can rewrite frame lines.
86
+ */
87
+ function normalizeJavaStackTraceForRetrace(trace) {
88
+ return trace
89
+ .split('\n')
90
+ .map(function (line) {
91
+ var trimmed = line.trim();
92
+ if (!trimmed) {
93
+ return line;
94
+ }
95
+ if (/^\s*at\s+/.test(line)) {
96
+ return line;
97
+ }
98
+ if (THREAD_STACK_FRAME_LINE.test(trimmed)) {
99
+ return " at ".concat(trimmed);
100
+ }
101
+ return line;
102
+ })
103
+ .join('\n');
104
+ }
105
+ /**
106
+ * Normalize exception text from ApplicationExitInfo / Log.getStackTraceString headers.
107
+ *
108
+ * React Native fatal JS errors embed the JS message in a fixed header shape
109
+ * (`Error: <message>, stack:`) regardless of the wrapping Java exception class.
110
+ * Match on that shape instead of the exception type name.
111
+ */
112
+ var RN_FATAL_JS_ERROR_HEADER = /^Error:\s*(.+?),\s*stack:\s*$/i;
113
+ function normalizeCrashTraceExceptionMessage(rawMessage) {
114
+ var _a;
115
+ if (!(rawMessage === null || rawMessage === void 0 ? void 0 : rawMessage.trim())) {
116
+ return undefined;
117
+ }
118
+ var message = rawMessage.trim();
119
+ var rnFatalMatch = message.match(RN_FATAL_JS_ERROR_HEADER);
120
+ return ((_a = rnFatalMatch === null || rnFatalMatch === void 0 ? void 0 : rnFatalMatch[1]) !== null && _a !== void 0 ? _a : message).trim() || undefined;
121
+ }
122
+ function parseJsFrameLine(line, options) {
123
+ var _a;
124
+ var parsed = (0, stackTraceParser_1.parseStackTraceLine)(line);
125
+ if (!parsed) {
126
+ return null;
127
+ }
128
+ return (_a = (0, stackTraceParser_1.toFaroStackFrames)([parsed], options)[0]) !== null && _a !== void 0 ? _a : null;
129
+ }
130
+ /**
131
+ * Parse a raw Android crash trace into structured stack frames for pushError().
132
+ */
133
+ function parseAndroidCrashTrace(trace, options) {
134
+ var trimmed = trace.trim();
135
+ if (!trimmed) {
136
+ return null;
137
+ }
138
+ var lines = trimmed.split('\n');
139
+ var jsFrames = [];
140
+ var frames = [];
141
+ var nativeFrames = [];
142
+ var exceptionType;
143
+ var exceptionMessage;
144
+ lines.forEach(function (line) {
145
+ var _a;
146
+ var nativeFrame = parseNativeTombstoneFrameLine(line);
147
+ if (nativeFrame) {
148
+ nativeFrames.push(nativeFrame);
149
+ return;
150
+ }
151
+ var frameMatch = (_a = line.match(FRAME_LINE)) !== null && _a !== void 0 ? _a : line.trim().match(THREAD_STACK_FRAME_LINE);
152
+ if (frameMatch) {
153
+ var module_1 = frameMatch[1], method = frameMatch[2], filename = frameMatch[3], lineNo = frameMatch[4];
154
+ frames.push({
155
+ module: module_1 !== null && module_1 !== void 0 ? module_1 : '',
156
+ function: method !== null && method !== void 0 ? method : '<unknown>',
157
+ filename: (filename === null || filename === void 0 ? void 0 : filename.trim()) || 'SourceFile',
158
+ lineno: lineNo ? parseInt(lineNo, 10) : undefined,
159
+ });
160
+ return;
161
+ }
162
+ var jsFrame = parseJsFrameLine(line, options);
163
+ if (jsFrame) {
164
+ jsFrames.push(jsFrame);
165
+ return;
166
+ }
167
+ var headerMatch = line.match(EXCEPTION_HEADER);
168
+ if (!isTombstoneMetadataLine(line) &&
169
+ (headerMatch === null || headerMatch === void 0 ? void 0 : headerMatch[1]) &&
170
+ isPlausibleJavaExceptionIdentifier(headerMatch[1]) &&
171
+ !isTombstoneSectionLabel(headerMatch[1])) {
172
+ exceptionType = headerMatch[1];
173
+ exceptionMessage = normalizeCrashTraceExceptionMessage(headerMatch[2]);
174
+ }
175
+ });
176
+ if (frames.length === 0 && jsFrames.length === 0 && nativeFrames.length === 0 && !exceptionType) {
177
+ return null;
178
+ }
179
+ return { exceptionType: exceptionType, exceptionMessage: exceptionMessage, jsFrames: jsFrames, frames: frames, nativeFrames: nativeFrames };
180
+ }
181
+ //# sourceMappingURL=parseAndroidCrashTrace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseAndroidCrashTrace.js","sourceRoot":"","sources":["../../../../../src/instrumentations/crashReporting/android/parseAndroidCrashTrace.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExceptionStackFrame } from '@grafana/faro-core';\n\nimport { parseStackTraceLine, toFaroStackFrames } from '../../errors/stackTraceParser';\n\n/**\n * Android ApplicationExitInfo traces use Java/Kotlin stack-trace formatting.\n * Faro ingest expects structured frames with `module` (obfuscated class) so the\n * collector can R8-retrace them — not the JS call stack from sendCrashReport().\n *\n * Fatal RN JS errors also embed a short Hermes/Metro stack before native frames\n * (e.g. `anonymous@1:1390953`). Those lines are parsed as JS frames (no `module`)\n * so the collector can source-map them to files like DebugScreen.tsx.\n */\nexport interface AndroidCrashStackFrame extends ExceptionStackFrame {\n module: string;\n}\n\nexport interface ParseAndroidCrashTraceOptions {\n releaseBundleFilename?: string;\n}\n\nexport interface NativeTombstoneStackFrame extends ExceptionStackFrame {\n /** Unstripped .so basename (e.g. libappmodules.so) for NDK retrace on the collector. */\n module: string;\n}\n\nexport interface ParsedAndroidCrashTrace {\n exceptionType?: string;\n /** Human-readable message from the trace header (e.g. the JS error text). */\n exceptionMessage?: string;\n /** JS/Hermes frames from the embedded RN stack (source-map targets). */\n jsFrames: ExceptionStackFrame[];\n /** Native Java/Kotlin frames (Android R8 retrace targets). */\n frames: AndroidCrashStackFrame[];\n /** NDK tombstone #NN pc lines (server-side .so retrace targets). */\n nativeFrames: NativeTombstoneStackFrame[];\n}\n\n// Mirrors pkg/exporter/androidretrace/mapping.go frameLine / exceptionHeader.\nconst FRAME_LINE = /^\\s*at\\s+([\\w$.]+)\\.([\\w$<>]+)\\(([^):]*)(?::(\\d+))?\\)\\s*$/;\n// Thread.getStackTrace() / legacy ANRTracker lines without the \"at \" prefix.\nconst THREAD_STACK_FRAME_LINE = /^\\s*([\\w$.]+)\\.([\\w$<>]+)\\(([^):]*)(?::(\\d+))?\\)\\s*$/;\nconst EXCEPTION_HEADER = /^\\s*(?:Caused by:\\s*)?([\\w$.]+)(?::(.*))?$/;\n// Mirrors pkg/exporter/androidretrace/native_frame.go nativeFrameLine.\nconst NATIVE_TOMBSTONE_FRAME_LINE = /^\\s*#(\\d+)\\s+pc\\s+(?:0x)?([0-9a-fA-F]+)\\s+(\\S+)(?:\\s+\\(([^)]+)\\))?/i;\n\nconst TOMBSTONE_SECTION_LABELS = new Set(['backtrace', 'stack', 'build id', 'memory map', 'memory near', 'abi']);\n\n/** Tombstone section headers and metadata must not become exception_type / nativeExceptionType. */\nexport function isTombstoneSectionLabel(value: string): boolean {\n return TOMBSTONE_SECTION_LABELS.has(value.trim().toLowerCase());\n}\n\nfunction isTombstoneMetadataLine(line: string): boolean {\n const trimmed = line.trim();\n if (!trimmed) {\n return true;\n }\n if (trimmed.startsWith('***')) {\n return true;\n }\n if (/^ABI:/i.test(trimmed)) {\n return true;\n }\n if (/^signal\\s+/i.test(trimmed)) {\n return true;\n }\n if (/^pid:/i.test(trimmed)) {\n return true;\n }\n if (isTombstoneSectionLabel(trimmed.replace(/:$/, ''))) {\n return true;\n }\n return false;\n}\n\nfunction nativeLibBasename(token: string): string {\n const bang = token.lastIndexOf('!');\n if (bang >= 0) {\n token = token.slice(bang + 1);\n }\n const slash = token.lastIndexOf('/');\n return slash >= 0 ? token.slice(slash + 1) : token;\n}\n\nfunction parseNativeTombstoneFrameLine(line: string): NativeTombstoneStackFrame | null {\n const match = line.match(NATIVE_TOMBSTONE_FRAME_LINE);\n if (!match) {\n return null;\n }\n\n const library = match[3] ?? '';\n const suffix = match[4]?.trim();\n let fn = '<unknown>';\n if (suffix) {\n const fnMatch = suffix.match(/^([A-Za-z_][A-Za-z0-9_]*)(?:\\+(\\d+))?$/);\n if (fnMatch?.[1] && fnMatch[1] !== 'BuildId' && fnMatch[1] !== 'offset') {\n fn = fnMatch[1];\n }\n }\n\n return {\n module: nativeLibBasename(library),\n function: fn,\n filename: nativeLibBasename(library),\n };\n}\n\n/** Reject version tokens (e.g. \"18.2213\") and other non-class header lines. */\nexport function isPlausibleJavaExceptionIdentifier(value: string): boolean {\n const trimmed = value.trim();\n if (!trimmed || !/[a-zA-Z]/.test(trimmed)) {\n return false;\n }\n if (/^\\d+(\\.\\d+)+$/.test(trimmed)) {\n return false;\n }\n return true;\n}\n\n/**\n * Normalize raw Java thread stacks (e.g. ANRTracker) to Log.getStackTraceString shape\n * so collector R8 retrace (mapping.RetraceText) can rewrite frame lines.\n */\nexport function normalizeJavaStackTraceForRetrace(trace: string): string {\n return trace\n .split('\\n')\n .map((line) => {\n const trimmed = line.trim();\n if (!trimmed) {\n return line;\n }\n if (/^\\s*at\\s+/.test(line)) {\n return line;\n }\n if (THREAD_STACK_FRAME_LINE.test(trimmed)) {\n return ` at ${trimmed}`;\n }\n return line;\n })\n .join('\\n');\n}\n\n/**\n * Normalize exception text from ApplicationExitInfo / Log.getStackTraceString headers.\n *\n * React Native fatal JS errors embed the JS message in a fixed header shape\n * (`Error: <message>, stack:`) regardless of the wrapping Java exception class.\n * Match on that shape instead of the exception type name.\n */\nconst RN_FATAL_JS_ERROR_HEADER = /^Error:\\s*(.+?),\\s*stack:\\s*$/i;\n\nexport function normalizeCrashTraceExceptionMessage(rawMessage: string | undefined): string | undefined {\n if (!rawMessage?.trim()) {\n return undefined;\n }\n\n const message = rawMessage.trim();\n const rnFatalMatch = message.match(RN_FATAL_JS_ERROR_HEADER);\n\n return (rnFatalMatch?.[1] ?? message).trim() || undefined;\n}\n\nfunction parseJsFrameLine(line: string, options?: ParseAndroidCrashTraceOptions): ExceptionStackFrame | null {\n const parsed = parseStackTraceLine(line);\n if (!parsed) {\n return null;\n }\n\n return toFaroStackFrames([parsed], options)[0] ?? null;\n}\n\n/**\n * Parse a raw Android crash trace into structured stack frames for pushError().\n */\nexport function parseAndroidCrashTrace(\n trace: string,\n options?: ParseAndroidCrashTraceOptions\n): ParsedAndroidCrashTrace | null {\n const trimmed = trace.trim();\n if (!trimmed) {\n return null;\n }\n\n const lines = trimmed.split('\\n');\n const jsFrames: ExceptionStackFrame[] = [];\n const frames: AndroidCrashStackFrame[] = [];\n const nativeFrames: NativeTombstoneStackFrame[] = [];\n let exceptionType: string | undefined;\n let exceptionMessage: string | undefined;\n\n lines.forEach((line) => {\n const nativeFrame = parseNativeTombstoneFrameLine(line);\n if (nativeFrame) {\n nativeFrames.push(nativeFrame);\n return;\n }\n\n const frameMatch = line.match(FRAME_LINE) ?? line.trim().match(THREAD_STACK_FRAME_LINE);\n\n if (frameMatch) {\n const [, module, method, filename, lineNo] = frameMatch;\n frames.push({\n module: module ?? '',\n function: method ?? '<unknown>',\n filename: filename?.trim() || 'SourceFile',\n lineno: lineNo ? parseInt(lineNo, 10) : undefined,\n });\n return;\n }\n\n const jsFrame = parseJsFrameLine(line, options);\n if (jsFrame) {\n jsFrames.push(jsFrame);\n return;\n }\n\n const headerMatch = line.match(EXCEPTION_HEADER);\n if (\n !isTombstoneMetadataLine(line) &&\n headerMatch?.[1] &&\n isPlausibleJavaExceptionIdentifier(headerMatch[1]) &&\n !isTombstoneSectionLabel(headerMatch[1])\n ) {\n exceptionType = headerMatch[1];\n exceptionMessage = normalizeCrashTraceExceptionMessage(headerMatch[2]);\n }\n });\n\n if (frames.length === 0 && jsFrames.length === 0 && nativeFrames.length === 0 && !exceptionType) {\n return null;\n }\n\n return { exceptionType, exceptionMessage, jsFrames, frames, nativeFrames };\n}\n"]}
@@ -1,6 +1,39 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CrashReportingInstrumentation = void 0;
4
- var instrumentation_1 = require("./instrumentation");
5
- Object.defineProperty(exports, "CrashReportingInstrumentation", { enumerable: true, get: function () { return instrumentation_1.CrashReportingInstrumentation; } });
4
+ var react_native_1 = require("react-native");
5
+ var android_1 = require("./android");
6
+ var ios_1 = require("./ios");
7
+ var NoOpCrashReportingInstrumentation_1 = require("./NoOpCrashReportingInstrumentation");
8
+ function resolveCrashReportingInstrumentation() {
9
+ if (react_native_1.Platform.OS === 'android') {
10
+ return android_1.AndroidCrashReportingInstrumentation;
11
+ }
12
+ if (react_native_1.Platform.OS === 'ios') {
13
+ // React Native reports both iPhone and iPadOS as "ios".
14
+ return ios_1.IosCrashReportingInstrumentation;
15
+ }
16
+ return NoOpCrashReportingInstrumentation_1.NoOpCrashReportingInstrumentation;
17
+ }
18
+ /**
19
+ * Platform-aware crash reporting instrumentation export.
20
+ *
21
+ * At module load time, determines the platform and exports the correct implementation:
22
+ * - Android: Uses ApplicationExitInfo API to retrieve crashes
23
+ * - iOS: Uses PLCrashReporter to retrieve crashes
24
+ * - Other: No-op stub (web, macOS, Windows, etc.)
25
+ *
26
+ * Usage:
27
+ * ```ts
28
+ * import { CrashReportingInstrumentation } from '@grafana/faro-react-native/instrumentation-crash';
29
+ *
30
+ * const faro = initializeFaro({
31
+ * // ...
32
+ * instrumentations: [
33
+ * new CrashReportingInstrumentation(),
34
+ * ],
35
+ * });
36
+ * ```
37
+ */
38
+ exports.CrashReportingInstrumentation = resolveCrashReportingInstrumentation();
6
39
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/instrumentations/crashReporting/index.ts"],"names":[],"mappings":";;;AAAA,qDAAkE;AAAzD,gIAAA,6BAA6B,OAAA","sourcesContent":["export { CrashReportingInstrumentation } from './instrumentation';\nexport type { CrashReport, CrashReportingOptions } from './types';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/instrumentations/crashReporting/index.ts"],"names":[],"mappings":";;;AAAA,6CAAwC;AAExC,qCAAiE;AACjE,6BAAyD;AACzD,yFAAwF;AAExF,SAAS,oCAAoC;IAC3C,IAAI,uBAAQ,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,8CAAoC,CAAC;IAC9C,CAAC;IAED,IAAI,uBAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QAC1B,wDAAwD;QACxD,OAAO,sCAAgC,CAAC;IAC1C,CAAC;IAED,OAAO,qEAAiC,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACU,QAAA,6BAA6B,GAAG,oCAAoC,EAAE,CAAC","sourcesContent":["import { Platform } from 'react-native';\n\nimport { AndroidCrashReportingInstrumentation } from './android';\nimport { IosCrashReportingInstrumentation } from './ios';\nimport { NoOpCrashReportingInstrumentation } from './NoOpCrashReportingInstrumentation';\n\nfunction resolveCrashReportingInstrumentation() {\n if (Platform.OS === 'android') {\n return AndroidCrashReportingInstrumentation;\n }\n\n if (Platform.OS === 'ios') {\n // React Native reports both iPhone and iPadOS as \"ios\".\n return IosCrashReportingInstrumentation;\n }\n\n return NoOpCrashReportingInstrumentation;\n}\n\n/**\n * Platform-aware crash reporting instrumentation export.\n *\n * At module load time, determines the platform and exports the correct implementation:\n * - Android: Uses ApplicationExitInfo API to retrieve crashes\n * - iOS: Uses PLCrashReporter to retrieve crashes\n * - Other: No-op stub (web, macOS, Windows, etc.)\n *\n * Usage:\n * ```ts\n * import { CrashReportingInstrumentation } from '@grafana/faro-react-native/instrumentation-crash';\n *\n * const faro = initializeFaro({\n * // ...\n * instrumentations: [\n * new CrashReportingInstrumentation(),\n * ],\n * });\n * ```\n */\nexport const CrashReportingInstrumentation = resolveCrashReportingInstrumentation();\n\n// Export public API types\nexport type { CrashReportingOptions } from './types';\n"]}
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ if (typeof b !== "function" && b !== null)
11
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
+ extendStatics(d, b);
13
+ function __() { this.constructor = d; }
14
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
+ };
16
+ })();
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.IosCrashReportingInstrumentation = void 0;
19
+ var faro_core_1 = require("@grafana/faro-core");
20
+ var BaseCrashReportingInstrumentation_1 = require("../BaseCrashReportingInstrumentation");
21
+ var crashErrorMessage_1 = require("./crashErrorMessage");
22
+ var parseIosCrashTrace_1 = require("./parseIosCrashTrace");
23
+ /**
24
+ * iOS Crash Reporting Instrumentation.
25
+ *
26
+ * Uses PLCrashReporter to capture native crashes from previous sessions:
27
+ * - SIGSEGV: Segmentation fault / invalid memory access
28
+ * - SIGABRT: Abnormal termination (e.g., assertion failure, uncaught exception)
29
+ * - SIGBUS: Bus error / alignment/hardware error
30
+ * - SIGILL: Illegal instruction
31
+ * - SIGFPE: Floating point exception
32
+ * - SIGTRAP: Breakpoint/debugger trap
33
+ * - Mach exceptions (EXC_BAD_ACCESS, EXC_CRASH, etc.)
34
+ *
35
+ * Stack frames are symbolicated on the native side before being surfaced.
36
+ */
37
+ var IosCrashReportingInstrumentation = /** @class */ (function (_super) {
38
+ __extends(IosCrashReportingInstrumentation, _super);
39
+ function IosCrashReportingInstrumentation() {
40
+ var _this = _super !== null && _super.apply(this, arguments) || this;
41
+ _this.name = '@grafana/faro-react-native:instrumentation-crash-ios';
42
+ _this.version = faro_core_1.VERSION;
43
+ return _this;
44
+ }
45
+ IosCrashReportingInstrumentation.prototype.parseCrashTrace = function (trace) {
46
+ return (0, parseIosCrashTrace_1.parseIosCrashTrace)(trace);
47
+ };
48
+ IosCrashReportingInstrumentation.prototype.resolveCrashErrorMessage = function (crash, parsedTrace) {
49
+ return (0, crashErrorMessage_1.resolveCrashErrorMessage)(crash, parsedTrace);
50
+ };
51
+ IosCrashReportingInstrumentation.prototype.shouldSkipCrashReport = function (crash) {
52
+ return (0, crashErrorMessage_1.shouldSkipCrashReport)(crash);
53
+ };
54
+ IosCrashReportingInstrumentation.prototype.getStackFrames = function (parsedTrace) {
55
+ var _a;
56
+ return (_a = parsedTrace === null || parsedTrace === void 0 ? void 0 : parsedTrace.frames) !== null && _a !== void 0 ? _a : [];
57
+ };
58
+ IosCrashReportingInstrumentation.prototype.buildPlatformContext = function (parsedTrace, context) {
59
+ if (parsedTrace === null || parsedTrace === void 0 ? void 0 : parsedTrace.exceptionName) {
60
+ context['nativeExceptionName'] = parsedTrace.exceptionName;
61
+ }
62
+ if (parsedTrace === null || parsedTrace === void 0 ? void 0 : parsedTrace.signalName) {
63
+ context['signalName'] = parsedTrace.signalName;
64
+ }
65
+ if (parsedTrace === null || parsedTrace === void 0 ? void 0 : parsedTrace.signalDescription) {
66
+ context['signalDescription'] = parsedTrace.signalDescription;
67
+ }
68
+ };
69
+ IosCrashReportingInstrumentation.prototype.getParseFailureWarning = function () {
70
+ return 'Native crash trace present but no frames parsed; check iOS PLCrashReporter format';
71
+ };
72
+ IosCrashReportingInstrumentation.prototype.getTraceUnavailableWarning = function () {
73
+ return 'Native crash trace unavailable (PLCrashReporter trace was null at crash time)';
74
+ };
75
+ return IosCrashReportingInstrumentation;
76
+ }(BaseCrashReportingInstrumentation_1.BaseCrashReportingInstrumentation));
77
+ exports.IosCrashReportingInstrumentation = IosCrashReportingInstrumentation;
78
+ //# sourceMappingURL=IosCrashReportingInstrumentation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IosCrashReportingInstrumentation.js","sourceRoot":"","sources":["../../../../../src/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,gDAA6C;AAE7C,0FAAyF;AAGzF,yDAAsF;AACtF,2DAAoF;AAEpF;;;;;;;;;;;;;GAaG;AACH;IAAsD,oDAAiC;IAAvF;;QACW,UAAI,GAAG,sDAAsD,CAAC;QAC9D,aAAO,GAAG,mBAAO,CAAC;;IAqC7B,CAAC;IAnCW,0DAAe,GAAzB,UAA0B,KAAa;QACrC,OAAO,IAAA,uCAAkB,EAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAES,mEAAwB,GAAlC,UAAmC,KAAkB,EAAE,WAAuC;QAC5F,OAAO,IAAA,4CAAwB,EAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IACtD,CAAC;IAES,gEAAqB,GAA/B,UAAgC,KAAkB;QAChD,OAAO,IAAA,yCAAqB,EAAC,KAAK,CAAC,CAAC;IACtC,CAAC;IAES,yDAAc,GAAxB,UAAyB,WAAuC;;QAC9D,OAAO,MAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,MAAM,mCAAI,EAAE,CAAC;IACnC,CAAC;IAES,+DAAoB,GAA9B,UAA+B,WAAuC,EAAE,OAA+B;QACrG,IAAI,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,aAAa,EAAE,CAAC;YAC/B,OAAO,CAAC,qBAAqB,CAAC,GAAG,WAAW,CAAC,aAAa,CAAC;QAC7D,CAAC;QACD,IAAI,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,UAAU,EAAE,CAAC;YAC5B,OAAO,CAAC,YAAY,CAAC,GAAG,WAAW,CAAC,UAAU,CAAC;QACjD,CAAC;QACD,IAAI,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,iBAAiB,EAAE,CAAC;YACnC,OAAO,CAAC,mBAAmB,CAAC,GAAG,WAAW,CAAC,iBAAiB,CAAC;QAC/D,CAAC;IACH,CAAC;IAES,iEAAsB,GAAhC;QACE,OAAO,mFAAmF,CAAC;IAC7F,CAAC;IAES,qEAA0B,GAApC;QACE,OAAO,+EAA+E,CAAC;IACzF,CAAC;IACH,uCAAC;AAAD,CAAC,AAvCD,CAAsD,qEAAiC,GAuCtF;AAvCY,4EAAgC","sourcesContent":["import { VERSION } from '@grafana/faro-core';\n\nimport { BaseCrashReportingInstrumentation } from '../BaseCrashReportingInstrumentation';\nimport type { CrashReport } from '../types';\n\nimport { resolveCrashErrorMessage, shouldSkipCrashReport } from './crashErrorMessage';\nimport { type ParsedIosCrashTrace, parseIosCrashTrace } from './parseIosCrashTrace';\n\n/**\n * iOS Crash Reporting Instrumentation.\n *\n * Uses PLCrashReporter to capture native crashes from previous sessions:\n * - SIGSEGV: Segmentation fault / invalid memory access\n * - SIGABRT: Abnormal termination (e.g., assertion failure, uncaught exception)\n * - SIGBUS: Bus error / alignment/hardware error\n * - SIGILL: Illegal instruction\n * - SIGFPE: Floating point exception\n * - SIGTRAP: Breakpoint/debugger trap\n * - Mach exceptions (EXC_BAD_ACCESS, EXC_CRASH, etc.)\n *\n * Stack frames are symbolicated on the native side before being surfaced.\n */\nexport class IosCrashReportingInstrumentation extends BaseCrashReportingInstrumentation {\n readonly name = '@grafana/faro-react-native:instrumentation-crash-ios';\n readonly version = VERSION;\n\n protected parseCrashTrace(trace: string): ParsedIosCrashTrace | null {\n return parseIosCrashTrace(trace);\n }\n\n protected resolveCrashErrorMessage(crash: CrashReport, parsedTrace: ParsedIosCrashTrace | null): string {\n return resolveCrashErrorMessage(crash, parsedTrace);\n }\n\n protected shouldSkipCrashReport(crash: CrashReport): boolean {\n return shouldSkipCrashReport(crash);\n }\n\n protected getStackFrames(parsedTrace: ParsedIosCrashTrace | null): any[] {\n return parsedTrace?.frames ?? [];\n }\n\n protected buildPlatformContext(parsedTrace: ParsedIosCrashTrace | null, context: Record<string, string>): void {\n if (parsedTrace?.exceptionName) {\n context['nativeExceptionName'] = parsedTrace.exceptionName;\n }\n if (parsedTrace?.signalName) {\n context['signalName'] = parsedTrace.signalName;\n }\n if (parsedTrace?.signalDescription) {\n context['signalDescription'] = parsedTrace.signalDescription;\n }\n }\n\n protected getParseFailureWarning(): string {\n return 'Native crash trace present but no frames parsed; check iOS PLCrashReporter format';\n }\n\n protected getTraceUnavailableWarning(): string {\n return 'Native crash trace unavailable (PLCrashReporter trace was null at crash time)';\n }\n}\n"]}
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveCrashErrorMessage = resolveCrashErrorMessage;
4
+ exports.shouldSkipCrashReport = shouldSkipCrashReport;
5
+ exports.buildFallbackCrashMessage = buildFallbackCrashMessage;
6
+ /**
7
+ * Human-readable exception value for iOS PLCrashReporter crash reports.
8
+ * Priority: exception reason → signal description → signal name → fallback.
9
+ */
10
+ function resolveCrashErrorMessage(crash, parsedTrace) {
11
+ var _a, _b, _c, _d, _e;
12
+ // iOS uncaught exceptions (NSException) have name and reason
13
+ if ((parsedTrace === null || parsedTrace === void 0 ? void 0 : parsedTrace.exceptionName) || (parsedTrace === null || parsedTrace === void 0 ? void 0 : parsedTrace.exceptionReason)) {
14
+ var name_1 = parsedTrace.exceptionName || 'Exception';
15
+ var reason_1 = (_a = parsedTrace.exceptionReason) === null || _a === void 0 ? void 0 : _a.trim();
16
+ if (reason_1) {
17
+ return "".concat(name_1, ": ").concat(reason_1);
18
+ }
19
+ return name_1;
20
+ }
21
+ // Use signal description if available from parsed trace
22
+ if ((_b = parsedTrace === null || parsedTrace === void 0 ? void 0 : parsedTrace.signalDescription) === null || _b === void 0 ? void 0 : _b.trim()) {
23
+ return parsedTrace.signalDescription.trim();
24
+ }
25
+ // Use signal name from parsed trace
26
+ if ((_c = parsedTrace === null || parsedTrace === void 0 ? void 0 : parsedTrace.signalName) === null || _c === void 0 ? void 0 : _c.trim()) {
27
+ var signalName = parsedTrace.signalName.trim();
28
+ var description_1 = SIGNAL_DESCRIPTIONS[signalName];
29
+ return description_1 || signalName;
30
+ }
31
+ // Check crash description - use if meaningful
32
+ var description = (_d = crash.description) === null || _d === void 0 ? void 0 : _d.trim();
33
+ if (description && !isGenericCrashDescription(description)) {
34
+ return description;
35
+ }
36
+ // Check if we have a known signal reason
37
+ var reason = (_e = crash.reason) === null || _e === void 0 ? void 0 : _e.trim();
38
+ if (reason && SIGNAL_DESCRIPTIONS[reason]) {
39
+ // If description is explicitly generic, use full format
40
+ if (description && isGenericCrashDescription(description)) {
41
+ return buildFallbackCrashMessage(crash);
42
+ }
43
+ // No description - use simple signal description
44
+ return SIGNAL_DESCRIPTIONS[reason];
45
+ }
46
+ // Final fallback: format with signal name, description, and status
47
+ return buildFallbackCrashMessage(crash);
48
+ }
49
+ /**
50
+ * Skip crash reports that have no useful information.
51
+ * iOS crashes should always have either a trace or a signal.
52
+ */
53
+ function shouldSkipCrashReport(crash) {
54
+ var _a, _b, _c;
55
+ if ((_a = crash.trace) === null || _a === void 0 ? void 0 : _a.trim()) {
56
+ return false;
57
+ }
58
+ if ((_b = crash.signal) === null || _b === void 0 ? void 0 : _b.trim()) {
59
+ return false;
60
+ }
61
+ var description = (_c = crash.description) === null || _c === void 0 ? void 0 : _c.trim();
62
+ if (description && !isGenericCrashDescription(description)) {
63
+ return false;
64
+ }
65
+ return true;
66
+ }
67
+ /** BSD signal names to human-readable descriptions */
68
+ var SIGNAL_DESCRIPTIONS = {
69
+ SIGHUP: 'Hangup',
70
+ SIGINT: 'Interrupt',
71
+ SIGQUIT: 'Quit',
72
+ SIGILL: 'Illegal instruction',
73
+ SIGTRAP: 'Trace/BPT trap',
74
+ SIGABRT: 'Abort trap',
75
+ SIGEMT: 'EMT trap',
76
+ SIGFPE: 'Floating point exception',
77
+ SIGKILL: 'Killed',
78
+ SIGBUS: 'Bus error',
79
+ SIGSEGV: 'Segmentation fault',
80
+ SIGSYS: 'Bad system call',
81
+ SIGPIPE: 'Broken pipe',
82
+ SIGALRM: 'Alarm clock',
83
+ SIGTERM: 'Terminated',
84
+ };
85
+ function isGenericCrashDescription(description) {
86
+ var normalized = description.trim().toLowerCase();
87
+ return normalized === 'crash' || normalized === 'application crash' || normalized === 'signal crash';
88
+ }
89
+ /** Generic fallback when the trace carries no parseable signal or description. */
90
+ function buildFallbackCrashMessage(crash) {
91
+ var _a;
92
+ var reason = crash.reason || 'UNKNOWN';
93
+ var status = (_a = crash.status) !== null && _a !== void 0 ? _a : 0;
94
+ var description;
95
+ if (SIGNAL_DESCRIPTIONS[reason]) {
96
+ description = SIGNAL_DESCRIPTIONS[reason];
97
+ }
98
+ else {
99
+ description = crash.description || 'Application crash';
100
+ }
101
+ return "".concat(reason, ": ").concat(description, ", status: ").concat(status);
102
+ }
103
+ //# sourceMappingURL=crashErrorMessage.js.map