@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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crashErrorMessage.js","sourceRoot":"","sources":["../../../../../src/instrumentations/crashReporting/ios/crashErrorMessage.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CrashReport } from '../types';\n\nimport type { ParsedIosCrashTrace } from './parseIosCrashTrace';\n\n/**\n * Human-readable exception value for iOS PLCrashReporter crash reports.\n * Priority: exception reason → signal description → signal name → fallback.\n */\nexport function resolveCrashErrorMessage(crash: CrashReport, parsedTrace: ParsedIosCrashTrace | null): string {\n // iOS uncaught exceptions (NSException) have name and reason\n if (parsedTrace?.exceptionName || parsedTrace?.exceptionReason) {\n const name = parsedTrace.exceptionName || 'Exception';\n const reason = parsedTrace.exceptionReason?.trim();\n if (reason) {\n return `${name}: ${reason}`;\n }\n return name;\n }\n\n // Use signal description if available from parsed trace\n if (parsedTrace?.signalDescription?.trim()) {\n return parsedTrace.signalDescription.trim();\n }\n\n // Use signal name from parsed trace\n if (parsedTrace?.signalName?.trim()) {\n const signalName = parsedTrace.signalName.trim();\n const description = SIGNAL_DESCRIPTIONS[signalName];\n return description || signalName;\n }\n\n // Check crash description - use if meaningful\n const description = crash.description?.trim();\n if (description && !isGenericCrashDescription(description)) {\n return description;\n }\n\n // Check if we have a known signal reason\n const reason = crash.reason?.trim();\n if (reason && SIGNAL_DESCRIPTIONS[reason]) {\n // If description is explicitly generic, use full format\n if (description && isGenericCrashDescription(description)) {\n return buildFallbackCrashMessage(crash);\n }\n // No description - use simple signal description\n return SIGNAL_DESCRIPTIONS[reason];\n }\n\n // Final fallback: format with signal name, description, and status\n return buildFallbackCrashMessage(crash);\n}\n\n/**\n * Skip crash reports that have no useful information.\n * iOS crashes should always have either a trace or a signal.\n */\nexport function shouldSkipCrashReport(crash: CrashReport): boolean {\n if (crash.trace?.trim()) {\n return false;\n }\n\n if (crash.signal?.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/** BSD signal names to human-readable descriptions */\nconst SIGNAL_DESCRIPTIONS: Record<string, string> = {\n SIGHUP: 'Hangup',\n SIGINT: 'Interrupt',\n SIGQUIT: 'Quit',\n SIGILL: 'Illegal instruction',\n SIGTRAP: 'Trace/BPT trap',\n SIGABRT: 'Abort trap',\n SIGEMT: 'EMT trap',\n SIGFPE: 'Floating point exception',\n SIGKILL: 'Killed',\n SIGBUS: 'Bus error',\n SIGSEGV: 'Segmentation fault',\n SIGSYS: 'Bad system call',\n SIGPIPE: 'Broken pipe',\n SIGALRM: 'Alarm clock',\n SIGTERM: 'Terminated',\n};\n\nfunction isGenericCrashDescription(description: string): boolean {\n const normalized = description.trim().toLowerCase();\n return normalized === 'crash' || normalized === 'application crash' || normalized === 'signal crash';\n}\n\n/** Generic fallback when the trace carries no parseable signal or description. */\nexport function buildFallbackCrashMessage(crash: CrashReport): string {\n const reason = crash.reason || 'UNKNOWN';\n const status = crash.status ?? 0;\n\n let description: string;\n if (SIGNAL_DESCRIPTIONS[reason]) {\n description = SIGNAL_DESCRIPTIONS[reason];\n } else {\n description = crash.description || 'Application crash';\n }\n\n return `${reason}: ${description}, status: ${status}`;\n}\n"]}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.shouldSkipCrashReport = exports.resolveCrashErrorMessage = exports.parseIosCrashTrace = exports.IosCrashReportingInstrumentation = void 0;
4
+ var IosCrashReportingInstrumentation_1 = require("./IosCrashReportingInstrumentation");
5
+ Object.defineProperty(exports, "IosCrashReportingInstrumentation", { enumerable: true, get: function () { return IosCrashReportingInstrumentation_1.IosCrashReportingInstrumentation; } });
6
+ var parseIosCrashTrace_1 = require("./parseIosCrashTrace");
7
+ Object.defineProperty(exports, "parseIosCrashTrace", { enumerable: true, get: function () { return parseIosCrashTrace_1.parseIosCrashTrace; } });
8
+ var crashErrorMessage_1 = require("./crashErrorMessage");
9
+ Object.defineProperty(exports, "resolveCrashErrorMessage", { enumerable: true, get: function () { return crashErrorMessage_1.resolveCrashErrorMessage; } });
10
+ Object.defineProperty(exports, "shouldSkipCrashReport", { enumerable: true, get: function () { return crashErrorMessage_1.shouldSkipCrashReport; } });
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/instrumentations/crashReporting/ios/index.ts"],"names":[],"mappings":";;;AAAA,uFAAsF;AAA7E,oJAAA,gCAAgC,OAAA;AACzC,2DAA0D;AAAjD,wHAAA,kBAAkB,OAAA;AAE3B,yDAAsF;AAA7E,6HAAA,wBAAwB,OAAA;AAAE,0HAAA,qBAAqB,OAAA","sourcesContent":["export { IosCrashReportingInstrumentation } from './IosCrashReportingInstrumentation';\nexport { parseIosCrashTrace } from './parseIosCrashTrace';\nexport type { ParsedIosCrashTrace, IosCrashStackFrame } from './parseIosCrashTrace';\nexport { resolveCrashErrorMessage, shouldSkipCrashReport } from './crashErrorMessage';\n"]}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseIosCrashTrace = parseIosCrashTrace;
4
+ /**
5
+ * iOS PLCrashReporter stack trace line format:
6
+ * "0 libsystem_kernel.dylib 0x00000001a2b3c000"
7
+ * frame_number library_name instruction_pointer
8
+ */
9
+ var IOS_STACK_FRAME_LINE = /^\s*(\d+)\s+(.+?)\s+(0x[0-9a-fA-F]+)\s*$/;
10
+ /**
11
+ * Parse a raw iOS crash trace from PLCrashReporter into structured stack frames.
12
+ *
13
+ * iOS crashes from PLCrashReporter come with formatted stack traces where each line
14
+ * contains: frame number, library name, and instruction pointer hex address.
15
+ *
16
+ * The collector will use the library name and instruction pointer for symbolication
17
+ * with dSYM files or Breakpad symbols.
18
+ */
19
+ function parseIosCrashTrace(trace, _options) {
20
+ var trimmed = trace.trim();
21
+ if (!trimmed) {
22
+ return null;
23
+ }
24
+ var lines = trimmed.split('\n');
25
+ var frames = [];
26
+ for (var _i = 0, lines_1 = lines; _i < lines_1.length; _i++) {
27
+ var line = lines_1[_i];
28
+ var frameMatch = line.match(IOS_STACK_FRAME_LINE);
29
+ if (frameMatch) {
30
+ var frameNumber = frameMatch[1], libraryName = frameMatch[2], instructionPointer = frameMatch[3];
31
+ if (!libraryName || !instructionPointer || !frameNumber) {
32
+ continue;
33
+ }
34
+ frames.push({
35
+ module: libraryName.trim(),
36
+ function: instructionPointer,
37
+ filename: libraryName.trim(),
38
+ lineno: parseInt(frameNumber, 10),
39
+ instructionPointer: instructionPointer,
40
+ });
41
+ }
42
+ }
43
+ if (frames.length === 0) {
44
+ return null;
45
+ }
46
+ return { frames: frames };
47
+ }
48
+ //# sourceMappingURL=parseIosCrashTrace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseIosCrashTrace.js","sourceRoot":"","sources":["../../../../../src/instrumentations/crashReporting/ios/parseIosCrashTrace.ts"],"names":[],"mappings":";;AAgDA,gDAkCC;AAlDD;;;;GAIG;AACH,IAAM,oBAAoB,GAAG,0CAA0C,CAAC;AAExE;;;;;;;;GAQG;AACH,SAAgB,kBAAkB,CAAC,KAAa,EAAE,QAAoC;IACpF,IAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,IAAM,MAAM,GAAyB,EAAE,CAAC;IAExC,KAAmB,UAAK,EAAL,eAAK,EAAL,mBAAK,EAAL,IAAK,EAAE,CAAC;QAAtB,IAAM,IAAI,cAAA;QACb,IAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QAEpD,IAAI,UAAU,EAAE,CAAC;YACN,IAAA,WAAW,GAAqC,UAAU,GAA/C,EAAE,WAAW,GAAwB,UAAU,GAAlC,EAAE,kBAAkB,GAAI,UAAU,GAAd,CAAe;YAEpE,IAAI,CAAC,WAAW,IAAI,CAAC,kBAAkB,IAAI,CAAC,WAAW,EAAE,CAAC;gBACxD,SAAS;YACX,CAAC;YAED,MAAM,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,WAAW,CAAC,IAAI,EAAE;gBAC1B,QAAQ,EAAE,kBAAkB;gBAC5B,QAAQ,EAAE,WAAW,CAAC,IAAI,EAAE;gBAC5B,MAAM,EAAE,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;gBACjC,kBAAkB,EAAE,kBAAkB;aACvC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,EAAE,MAAM,QAAA,EAAE,CAAC;AACpB,CAAC","sourcesContent":["import type { ExceptionStackFrame } from '@grafana/faro-core';\n\n/**\n * iOS PLCrashReporter stack frames include library name and instruction pointers.\n * Format: \"0 libsystem_kernel.dylib 0x00000001a2b3c000\"\n */\nexport interface IosCrashStackFrame extends ExceptionStackFrame {\n /** Library/module name (e.g., \"MyApp\", \"UIKitCore\") */\n module: string;\n /** Instruction pointer address (hex string) */\n instructionPointer?: string;\n /** Library base address (hex string) */\n libraryBaseAddress?: string;\n}\n\nexport interface ParseIosCrashTraceOptions {\n releaseBundleFilename?: string;\n}\n\nexport interface ParsedIosCrashTrace {\n /** Signal name (e.g., \"SIGSEGV\", \"SIGABRT\") */\n signalName?: string;\n /** Human-readable signal description */\n signalDescription?: string;\n /** Exception name for uncaught exceptions (e.g., \"NSInternalInconsistencyException\") */\n exceptionName?: string;\n /** Exception reason/message for uncaught exceptions */\n exceptionReason?: string;\n /** iOS native frames (library + instruction pointer for symbolication) */\n frames: IosCrashStackFrame[];\n}\n\n/**\n * iOS PLCrashReporter stack trace line format:\n * \"0 libsystem_kernel.dylib 0x00000001a2b3c000\"\n * frame_number library_name instruction_pointer\n */\nconst IOS_STACK_FRAME_LINE = /^\\s*(\\d+)\\s+(.+?)\\s+(0x[0-9a-fA-F]+)\\s*$/;\n\n/**\n * Parse a raw iOS crash trace from PLCrashReporter into structured stack frames.\n *\n * iOS crashes from PLCrashReporter come with formatted stack traces where each line\n * contains: frame number, library name, and instruction pointer hex address.\n *\n * The collector will use the library name and instruction pointer for symbolication\n * with dSYM files or Breakpad symbols.\n */\nexport function parseIosCrashTrace(trace: string, _options?: ParseIosCrashTraceOptions): ParsedIosCrashTrace | null {\n const trimmed = trace.trim();\n if (!trimmed) {\n return null;\n }\n\n const lines = trimmed.split('\\n');\n const frames: IosCrashStackFrame[] = [];\n\n for (const line of lines) {\n const frameMatch = line.match(IOS_STACK_FRAME_LINE);\n\n if (frameMatch) {\n const [, frameNumber, libraryName, instructionPointer] = frameMatch;\n\n if (!libraryName || !instructionPointer || !frameNumber) {\n continue;\n }\n\n frames.push({\n module: libraryName.trim(),\n function: instructionPointer,\n filename: libraryName.trim(),\n lineno: parseInt(frameNumber, 10),\n instructionPointer: instructionPointer,\n });\n }\n }\n\n if (frames.length === 0) {\n return null;\n }\n\n return { frames };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/instrumentations/crashReporting/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Configuration options for Crash Reporting instrumentation.\n *\n * **Platform Support**:\n * - **Android**: Uses ApplicationExitInfo API (Android 11+ / API 30+)\n * Captures: CRASH, CRASH_NATIVE, ANR, LOW_MEMORY, EXCESSIVE_RESOURCE_USAGE\n * - **iOS**: Uses PLCrashReporter (automatically included via podspec)\n * Captures: Signal crashes (SIGSEGV, SIGABRT, etc.) and Mach exceptions\n */\nexport interface CrashReportingOptions {\n /**\n * Whether to enable crash reporting.\n * Default: true\n */\n enabled?: boolean;\n}\n\n/**\n * Crash report data from native module.\n *\n * Field names match Faro Flutter SDK for consistency across mobile platforms.\n * Both Android (ApplicationExitInfo) and iOS (PLCrashReporter) produce JSON\n * matching this interface.\n */\nexport interface CrashReport {\n /**\n * Reason for the crash (e.g., \"CRASH\", \"CRASH_NATIVE\", \"ANR\", \"LOW_MEMORY\")\n */\n reason: string;\n\n /**\n * Timestamp when the crash occurred (milliseconds since epoch)\n */\n timestamp: number;\n\n /**\n * Exit status code\n */\n status?: number;\n\n /**\n * Description of the crash\n */\n description?: string;\n\n /**\n * Process importance level\n */\n importance?: number;\n\n /**\n * Process ID\n */\n pid?: number;\n\n /**\n * Process name\n */\n processName?: string;\n\n /**\n * Stack trace (if available)\n */\n trace?: string;\n\n /**\n * Signal name (for iOS crashes)\n */\n signal?: string;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/instrumentations/crashReporting/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Crash report data structure returned from native module.\n */\nexport interface CrashReport {\n trace?: string;\n signal?: string;\n timestamp?: number;\n description?: string;\n processName?: string;\n pid?: number;\n importance?: number;\n // iOS-specific fields\n reason?: string; // Signal name (e.g., 'SIGSEGV')\n status?: number; // Exit status code\n}\n\n/**\n * Configuration options for crash reporting instrumentation.\n */\nexport interface CrashReportingOptions {\n /**\n * Enable or disable crash reporting. Defaults to true.\n */\n enabled?: boolean;\n\n /**\n * Optional release bundle filename hint for R8 retracing.\n * e.g., \"index.android.bundle\"\n */\n releaseBundleFilename?: string;\n}\n"]}
@@ -89,12 +89,12 @@ var ErrorsInstrumentation = /** @class */ (function (_super) {
89
89
  // Enhance error with React Native context and stack frames
90
90
  var _a = (0, stackTraceParser_1.enhanceErrorWithContext)(error, {
91
91
  mechanism: const_1.ErrorMechanism.UNCAUGHT,
92
- isFatal: String(isFatal !== null && isFatal !== void 0 ? isFatal : false),
93
92
  }, { releaseBundleFilename: _this.options.releaseBundleFilename }), enhancedError = _a.error, stackFrames = _a.stackFrames, context = _a.context;
94
93
  // Push error to Faro with enhanced data (type from error.name, matches Web SDK)
95
94
  _this.api.pushError(enhancedError, {
96
95
  type: enhancedError.name || 'Error',
97
96
  context: context,
97
+ fatal: isFatal !== null && isFatal !== void 0 ? isFatal : false,
98
98
  stackFrames: stackFrames,
99
99
  });
100
100
  // Track error fingerprint for deduplication
@@ -146,6 +146,7 @@ var ErrorsInstrumentation = /** @class */ (function (_super) {
146
146
  _this.api.pushError(enhancedError, {
147
147
  type: errorType,
148
148
  context: context,
149
+ fatal: false,
149
150
  stackFrames: stackFrames,
150
151
  });
151
152
  // Track error fingerprint for deduplication
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/instrumentations/errors/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ErrorUtils } from 'react-native';\n\nimport { BaseInstrumentation } from '@grafana/faro-core';\n\nimport { ErrorMechanism, primitiveUnhandledType } from './const';\nexport { ErrorMechanism } from './const';\nexport type { ErrorMechanismType } from './const';\nimport { enhanceErrorWithContext } from './stackTraceParser';\n\n// Access the global ErrorUtils\ndeclare const global: {\n ErrorUtils: ErrorUtils;\n addEventListener?: (event: string, handler: (event: PromiseRejectionEvent) => void) => void;\n removeEventListener?: (event: string, handler: (event: PromiseRejectionEvent) => void) => void;\n};\n\ntype ErrorHandlerCallback = (error: Error | unknown, isFatal?: boolean) => void;\n\nexport interface ErrorsInstrumentationOptions {\n /**\n * Patterns to ignore errors by message\n * @example [/network timeout/i, /cancelled/i]\n */\n ignoreErrors?: RegExp[];\n\n /**\n * Enable error deduplication (default: true)\n * Prevents sending the same error multiple times within a time window\n */\n enableDeduplication?: boolean;\n\n /**\n * Deduplication time window in milliseconds (default: 5000)\n * Errors with same message/stack within this window are considered duplicates\n */\n deduplicationWindow?: number;\n\n /**\n * Maximum number of errors to track for deduplication (default: 50)\n * Older errors are removed when this limit is reached\n */\n maxDeduplicationEntries?: number;\n\n /**\n * Bundle filename for Hermes/minified release lines (`func@line:col`).\n * Must match the Metro plugin source map `file` field (default `bundle.js`).\n */\n releaseBundleFilename?: string;\n}\n\ninterface ErrorFingerprint {\n message: string;\n stack: string;\n timestamp: number;\n}\n\n/**\n * Errors instrumentation for React Native\n *\n * Features:\n * - Captures unhandled errors and promise rejections using ErrorUtils\n * - Parses React Native stack traces (dev, release, Metro bundler formats)\n * - Adds platform context (OS, version, Hermes engine)\n * - Error deduplication to prevent duplicate reports\n * - Configurable error filtering\n *\n * @example\n * ```tsx\n * import { ErrorsInstrumentation, initializeFaro } from '@grafana/faro-react-native';\n *\n * await initializeFaro({\n * // ...config\n * instrumentations: [\n * new ErrorsInstrumentation({\n * ignoreErrors: [/network timeout/i, /cancelled/i],\n * enableDeduplication: true,\n * deduplicationWindow: 5000,\n * }),\n * ],\n * });\n * ```\n */\nexport class ErrorsInstrumentation extends BaseInstrumentation {\n readonly name = '@grafana/faro-react-native-errors';\n readonly version = '1.0.0';\n\n private originalErrorHandler?: ErrorHandlerCallback;\n private unhandledRejectionListener?: (event: PromiseRejectionEvent) => void;\n private options: Required<Omit<ErrorsInstrumentationOptions, 'releaseBundleFilename'>> & {\n releaseBundleFilename?: string;\n };\n private errorFingerprints: ErrorFingerprint[] = [];\n\n constructor(options: ErrorsInstrumentationOptions = {}) {\n super();\n this.options = {\n ignoreErrors: options.ignoreErrors ?? [],\n enableDeduplication: options.enableDeduplication ?? true,\n deduplicationWindow: options.deduplicationWindow ?? 5000,\n maxDeduplicationEntries: options.maxDeduplicationEntries ?? 50,\n releaseBundleFilename: options.releaseBundleFilename,\n };\n }\n\n initialize(): void {\n // Capture unhandled JavaScript errors\n this.setupGlobalErrorHandler();\n\n // Capture unhandled promise rejections\n this.setupUnhandledRejectionHandler();\n }\n\n private setupGlobalErrorHandler(): void {\n // Store the original error handler\n this.originalErrorHandler = global.ErrorUtils.getGlobalHandler();\n\n // Set our custom handler\n global.ErrorUtils.setGlobalHandler((error: Error, isFatal?: boolean) => {\n try {\n // Check if error should be ignored\n if (this.shouldIgnoreError(error)) {\n return;\n }\n\n // Check for duplicate errors\n if (this.options.enableDeduplication && this.isDuplicateError(error)) {\n return;\n }\n\n // Enhance error with React Native context and stack frames\n const {\n error: enhancedError,\n stackFrames,\n context,\n } = enhanceErrorWithContext(\n error,\n {\n mechanism: ErrorMechanism.UNCAUGHT,\n isFatal: String(isFatal ?? false),\n },\n { releaseBundleFilename: this.options.releaseBundleFilename }\n );\n\n // Push error to Faro with enhanced data (type from error.name, matches Web SDK)\n this.api.pushError(enhancedError, {\n type: enhancedError.name || 'Error',\n context,\n stackFrames,\n });\n\n // Track error fingerprint for deduplication\n if (this.options.enableDeduplication) {\n this.addErrorFingerprint(error);\n }\n } catch (_e) {\n // Don't let error reporting cause more errors\n } finally {\n // Always call the original handler to maintain normal error behavior\n if (this.originalErrorHandler) {\n this.originalErrorHandler(error, isFatal);\n }\n }\n });\n }\n\n private setupUnhandledRejectionHandler(): void {\n // React Native supports the standard unhandledrejection event\n this.unhandledRejectionListener = (event: PromiseRejectionEvent) => {\n try {\n const reason = event.reason;\n\n // Convert reason to an Error if it isn't one (matches Web SDK approach)\n const isPrimitiveRejection = !(reason instanceof Error);\n let error: Error;\n if (reason instanceof Error) {\n error = reason;\n } else {\n error = new Error(\n `Unhandled Promise Rejection: ${typeof reason === 'object' ? JSON.stringify(reason) : String(reason)}`\n );\n }\n\n // Check if error should be ignored\n if (this.shouldIgnoreError(error)) {\n return;\n }\n\n // Check for duplicate errors\n if (this.options.enableDeduplication && this.isDuplicateError(error)) {\n return;\n }\n\n // Enhance error with React Native context and stack frames\n const {\n error: enhancedError,\n stackFrames,\n context,\n } = enhanceErrorWithContext(\n error,\n {\n mechanism: ErrorMechanism.UNHANDLED_REJECTION,\n },\n { releaseBundleFilename: this.options.releaseBundleFilename }\n );\n\n // Type: use actual error type for Error objects; 'UnhandledRejection' for primitives (Web SDK)\n const errorType = isPrimitiveRejection ? primitiveUnhandledType : enhancedError.name || 'Error';\n\n this.api.pushError(enhancedError, {\n type: errorType,\n context,\n stackFrames,\n });\n\n // Track error fingerprint for deduplication\n if (this.options.enableDeduplication) {\n this.addErrorFingerprint(error);\n }\n } catch (_e) {\n // Don't let error reporting cause more errors\n }\n };\n\n // Add the listener\n global.addEventListener?.('unhandledrejection', this.unhandledRejectionListener);\n }\n\n /**\n * Check if error should be ignored based on ignoreErrors patterns\n */\n private shouldIgnoreError(error: Error): boolean {\n if (!error || !error.message) {\n return false;\n }\n\n return this.options.ignoreErrors.some((pattern) => pattern.test(error.message));\n }\n\n /**\n * Check if error is a duplicate based on message and stack\n */\n private isDuplicateError(error: Error): boolean {\n const message = error.message || '';\n const stack = error.stack || '';\n const now = Date.now();\n\n // Clean up old entries first\n this.cleanupOldFingerprints(now);\n\n // Check if we've seen this error recently\n return this.errorFingerprints.some((fingerprint) => {\n return (\n fingerprint.message === message &&\n fingerprint.stack === stack &&\n now - fingerprint.timestamp < this.options.deduplicationWindow\n );\n });\n }\n\n /**\n * Add error fingerprint for deduplication tracking\n */\n private addErrorFingerprint(error: Error): void {\n const message = error.message || '';\n const stack = error.stack || '';\n const timestamp = Date.now();\n\n this.errorFingerprints.push({ message, stack, timestamp });\n\n // Limit the number of tracked fingerprints\n if (this.errorFingerprints.length > this.options.maxDeduplicationEntries) {\n this.errorFingerprints.shift();\n }\n }\n\n /**\n * Remove error fingerprints older than the deduplication window\n */\n private cleanupOldFingerprints(now: number): void {\n this.errorFingerprints = this.errorFingerprints.filter(\n (fingerprint) => now - fingerprint.timestamp < this.options.deduplicationWindow\n );\n }\n\n unpatch(): void {\n // Restore original error handler\n if (this.originalErrorHandler) {\n global.ErrorUtils.setGlobalHandler(this.originalErrorHandler);\n }\n\n // Remove unhandled rejection listener\n if (this.unhandledRejectionListener) {\n global.removeEventListener?.('unhandledrejection', this.unhandledRejectionListener);\n }\n\n // Clear deduplication tracking\n this.errorFingerprints = [];\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/instrumentations/errors/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ErrorUtils } from 'react-native';\n\nimport { BaseInstrumentation } from '@grafana/faro-core';\n\nimport { ErrorMechanism, primitiveUnhandledType } from './const';\nexport { ErrorMechanism } from './const';\nexport type { ErrorMechanismType } from './const';\nimport { enhanceErrorWithContext } from './stackTraceParser';\n\n// Access the global ErrorUtils\ndeclare const global: {\n ErrorUtils: ErrorUtils;\n addEventListener?: (event: string, handler: (event: PromiseRejectionEvent) => void) => void;\n removeEventListener?: (event: string, handler: (event: PromiseRejectionEvent) => void) => void;\n};\n\ntype ErrorHandlerCallback = (error: Error | unknown, isFatal?: boolean) => void;\n\nexport interface ErrorsInstrumentationOptions {\n /**\n * Patterns to ignore errors by message\n * @example [/network timeout/i, /cancelled/i]\n */\n ignoreErrors?: RegExp[];\n\n /**\n * Enable error deduplication (default: true)\n * Prevents sending the same error multiple times within a time window\n */\n enableDeduplication?: boolean;\n\n /**\n * Deduplication time window in milliseconds (default: 5000)\n * Errors with same message/stack within this window are considered duplicates\n */\n deduplicationWindow?: number;\n\n /**\n * Maximum number of errors to track for deduplication (default: 50)\n * Older errors are removed when this limit is reached\n */\n maxDeduplicationEntries?: number;\n\n /**\n * Bundle filename for Hermes/minified release lines (`func@line:col`).\n * Must match the Metro plugin source map `file` field (default `bundle.js`).\n */\n releaseBundleFilename?: string;\n}\n\ninterface ErrorFingerprint {\n message: string;\n stack: string;\n timestamp: number;\n}\n\n/**\n * Errors instrumentation for React Native\n *\n * Features:\n * - Captures unhandled errors and promise rejections using ErrorUtils\n * - Parses React Native stack traces (dev, release, Metro bundler formats)\n * - Adds platform context (OS, version, Hermes engine)\n * - Error deduplication to prevent duplicate reports\n * - Configurable error filtering\n *\n * @example\n * ```tsx\n * import { ErrorsInstrumentation, initializeFaro } from '@grafana/faro-react-native';\n *\n * await initializeFaro({\n * // ...config\n * instrumentations: [\n * new ErrorsInstrumentation({\n * ignoreErrors: [/network timeout/i, /cancelled/i],\n * enableDeduplication: true,\n * deduplicationWindow: 5000,\n * }),\n * ],\n * });\n * ```\n */\nexport class ErrorsInstrumentation extends BaseInstrumentation {\n readonly name = '@grafana/faro-react-native-errors';\n readonly version = '1.0.0';\n\n private originalErrorHandler?: ErrorHandlerCallback;\n private unhandledRejectionListener?: (event: PromiseRejectionEvent) => void;\n private options: Required<Omit<ErrorsInstrumentationOptions, 'releaseBundleFilename'>> & {\n releaseBundleFilename?: string;\n };\n private errorFingerprints: ErrorFingerprint[] = [];\n\n constructor(options: ErrorsInstrumentationOptions = {}) {\n super();\n this.options = {\n ignoreErrors: options.ignoreErrors ?? [],\n enableDeduplication: options.enableDeduplication ?? true,\n deduplicationWindow: options.deduplicationWindow ?? 5000,\n maxDeduplicationEntries: options.maxDeduplicationEntries ?? 50,\n releaseBundleFilename: options.releaseBundleFilename,\n };\n }\n\n initialize(): void {\n // Capture unhandled JavaScript errors\n this.setupGlobalErrorHandler();\n\n // Capture unhandled promise rejections\n this.setupUnhandledRejectionHandler();\n }\n\n private setupGlobalErrorHandler(): void {\n // Store the original error handler\n this.originalErrorHandler = global.ErrorUtils.getGlobalHandler();\n\n // Set our custom handler\n global.ErrorUtils.setGlobalHandler((error: Error, isFatal?: boolean) => {\n try {\n // Check if error should be ignored\n if (this.shouldIgnoreError(error)) {\n return;\n }\n\n // Check for duplicate errors\n if (this.options.enableDeduplication && this.isDuplicateError(error)) {\n return;\n }\n\n // Enhance error with React Native context and stack frames\n const {\n error: enhancedError,\n stackFrames,\n context,\n } = enhanceErrorWithContext(\n error,\n {\n mechanism: ErrorMechanism.UNCAUGHT,\n },\n { releaseBundleFilename: this.options.releaseBundleFilename }\n );\n\n // Push error to Faro with enhanced data (type from error.name, matches Web SDK)\n this.api.pushError(enhancedError, {\n type: enhancedError.name || 'Error',\n context,\n fatal: isFatal ?? false,\n stackFrames,\n });\n\n // Track error fingerprint for deduplication\n if (this.options.enableDeduplication) {\n this.addErrorFingerprint(error);\n }\n } catch (_e) {\n // Don't let error reporting cause more errors\n } finally {\n // Always call the original handler to maintain normal error behavior\n if (this.originalErrorHandler) {\n this.originalErrorHandler(error, isFatal);\n }\n }\n });\n }\n\n private setupUnhandledRejectionHandler(): void {\n // React Native supports the standard unhandledrejection event\n this.unhandledRejectionListener = (event: PromiseRejectionEvent) => {\n try {\n const reason = event.reason;\n\n // Convert reason to an Error if it isn't one (matches Web SDK approach)\n const isPrimitiveRejection = !(reason instanceof Error);\n let error: Error;\n if (reason instanceof Error) {\n error = reason;\n } else {\n error = new Error(\n `Unhandled Promise Rejection: ${typeof reason === 'object' ? JSON.stringify(reason) : String(reason)}`\n );\n }\n\n // Check if error should be ignored\n if (this.shouldIgnoreError(error)) {\n return;\n }\n\n // Check for duplicate errors\n if (this.options.enableDeduplication && this.isDuplicateError(error)) {\n return;\n }\n\n // Enhance error with React Native context and stack frames\n const {\n error: enhancedError,\n stackFrames,\n context,\n } = enhanceErrorWithContext(\n error,\n {\n mechanism: ErrorMechanism.UNHANDLED_REJECTION,\n },\n { releaseBundleFilename: this.options.releaseBundleFilename }\n );\n\n // Type: use actual error type for Error objects; 'UnhandledRejection' for primitives (Web SDK)\n const errorType = isPrimitiveRejection ? primitiveUnhandledType : enhancedError.name || 'Error';\n\n this.api.pushError(enhancedError, {\n type: errorType,\n context,\n fatal: false,\n stackFrames,\n });\n\n // Track error fingerprint for deduplication\n if (this.options.enableDeduplication) {\n this.addErrorFingerprint(error);\n }\n } catch (_e) {\n // Don't let error reporting cause more errors\n }\n };\n\n // Add the listener\n global.addEventListener?.('unhandledrejection', this.unhandledRejectionListener);\n }\n\n /**\n * Check if error should be ignored based on ignoreErrors patterns\n */\n private shouldIgnoreError(error: Error): boolean {\n if (!error || !error.message) {\n return false;\n }\n\n return this.options.ignoreErrors.some((pattern) => pattern.test(error.message));\n }\n\n /**\n * Check if error is a duplicate based on message and stack\n */\n private isDuplicateError(error: Error): boolean {\n const message = error.message || '';\n const stack = error.stack || '';\n const now = Date.now();\n\n // Clean up old entries first\n this.cleanupOldFingerprints(now);\n\n // Check if we've seen this error recently\n return this.errorFingerprints.some((fingerprint) => {\n return (\n fingerprint.message === message &&\n fingerprint.stack === stack &&\n now - fingerprint.timestamp < this.options.deduplicationWindow\n );\n });\n }\n\n /**\n * Add error fingerprint for deduplication tracking\n */\n private addErrorFingerprint(error: Error): void {\n const message = error.message || '';\n const stack = error.stack || '';\n const timestamp = Date.now();\n\n this.errorFingerprints.push({ message, stack, timestamp });\n\n // Limit the number of tracked fingerprints\n if (this.errorFingerprints.length > this.options.maxDeduplicationEntries) {\n this.errorFingerprints.shift();\n }\n }\n\n /**\n * Remove error fingerprints older than the deduplication window\n */\n private cleanupOldFingerprints(now: number): void {\n this.errorFingerprints = this.errorFingerprints.filter(\n (fingerprint) => now - fingerprint.timestamp < this.options.deduplicationWindow\n );\n }\n\n unpatch(): void {\n // Restore original error handler\n if (this.originalErrorHandler) {\n global.ErrorUtils.setGlobalHandler(this.originalErrorHandler);\n }\n\n // Remove unhandled rejection listener\n if (this.unhandledRejectionListener) {\n global.removeEventListener?.('unhandledrejection', this.unhandledRejectionListener);\n }\n\n // Clear deduplication tracking\n this.errorFingerprints = [];\n }\n}\n"]}
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ var __importDefault = (this && this.__importDefault) || function (mod) {
39
+ return (mod && mod.__esModule) ? mod : { "default": mod };
40
+ };
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.getInstallationId = getInstallationId;
43
+ var async_storage_1 = __importDefault(require("@react-native-async-storage/async-storage"));
44
+ var INSTALLATION_ID_STORAGE_KEY = '@grafana/faro-react-native/installation_id';
45
+ function createRandomBytes(length) {
46
+ var bytes = new Uint8Array(length);
47
+ var cryptoObject = globalThis.crypto;
48
+ if (cryptoObject && typeof cryptoObject.getRandomValues === 'function') {
49
+ cryptoObject.getRandomValues(bytes);
50
+ return bytes;
51
+ }
52
+ for (var i = 0; i < bytes.length; i++) {
53
+ bytes[i] = Math.floor(Math.random() * 256);
54
+ }
55
+ return bytes;
56
+ }
57
+ function generateInstallationId() {
58
+ var _a, _b;
59
+ var bytes = createRandomBytes(16);
60
+ bytes[6] = (((_a = bytes[6]) !== null && _a !== void 0 ? _a : 0) & 0x0f) | 0x40;
61
+ bytes[8] = (((_b = bytes[8]) !== null && _b !== void 0 ? _b : 0) & 0x3f) | 0x80;
62
+ var hex = Array.from(bytes, function (byte) { return byte.toString(16).padStart(2, '0'); }).join('');
63
+ return "".concat(hex.slice(0, 8), "-").concat(hex.slice(8, 12), "-").concat(hex.slice(12, 16), "-").concat(hex.slice(16, 20), "-").concat(hex.slice(20));
64
+ }
65
+ function getInstallationId() {
66
+ return __awaiter(this, void 0, void 0, function () {
67
+ var storedInstallationId, installationId, _error_1;
68
+ return __generator(this, function (_a) {
69
+ switch (_a.label) {
70
+ case 0:
71
+ _a.trys.push([0, 3, , 4]);
72
+ return [4 /*yield*/, async_storage_1.default.getItem(INSTALLATION_ID_STORAGE_KEY)];
73
+ case 1:
74
+ storedInstallationId = _a.sent();
75
+ if (storedInstallationId) {
76
+ return [2 /*return*/, storedInstallationId];
77
+ }
78
+ installationId = generateInstallationId();
79
+ return [4 /*yield*/, async_storage_1.default.setItem(INSTALLATION_ID_STORAGE_KEY, installationId)];
80
+ case 2:
81
+ _a.sent();
82
+ return [2 /*return*/, installationId];
83
+ case 3:
84
+ _error_1 = _a.sent();
85
+ return [2 /*return*/, undefined];
86
+ case 4: return [2 /*return*/];
87
+ }
88
+ });
89
+ });
90
+ }
91
+ //# sourceMappingURL=installationId.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installationId.js","sourceRoot":"","sources":["../../../../src/instrumentations/session/installationId.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,8CAaC;AA1CD,4FAAqE;AAErE,IAAM,2BAA2B,GAAG,4CAA4C,CAAC;AAEjF,SAAS,iBAAiB,CAAC,MAAc;IACvC,IAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IACrC,IAAM,YAAY,GAAG,UAAU,CAAC,MAAM,CAAC;IAEvC,IAAI,YAAY,IAAI,OAAO,YAAY,CAAC,eAAe,KAAK,UAAU,EAAE,CAAC;QACvE,YAAY,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QACpC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,sBAAsB;;IAC7B,IAAM,KAAK,GAAG,iBAAiB,CAAC,EAAE,CAAC,CAAC;IACpC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAA,KAAK,CAAC,CAAC,CAAC,mCAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3C,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAA,KAAK,CAAC,CAAC,CAAC,mCAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAE3C,IAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,UAAC,IAAI,IAAK,OAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAlC,CAAkC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACrF,OAAO,UAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,cAAI,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,cAAI,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,cAAI,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,cAAI,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAE,CAAC;AAC7G,CAAC;AAED,SAAsB,iBAAiB;;;;;;;oBAEN,qBAAM,uBAAY,CAAC,OAAO,CAAC,2BAA2B,CAAC,EAAA;;oBAA9E,oBAAoB,GAAG,SAAuD;oBACpF,IAAI,oBAAoB,EAAE,CAAC;wBACzB,sBAAO,oBAAoB,EAAC;oBAC9B,CAAC;oBAEK,cAAc,GAAG,sBAAsB,EAAE,CAAC;oBAChD,qBAAM,uBAAY,CAAC,OAAO,CAAC,2BAA2B,EAAE,cAAc,CAAC,EAAA;;oBAAvE,SAAuE,CAAC;oBACxE,sBAAO,cAAc,EAAC;;;oBAEtB,sBAAO,SAAS,EAAC;;;;;CAEpB","sourcesContent":["import AsyncStorage from '@react-native-async-storage/async-storage';\n\nconst INSTALLATION_ID_STORAGE_KEY = '@grafana/faro-react-native/installation_id';\n\nfunction createRandomBytes(length: number): Uint8Array {\n const bytes = new Uint8Array(length);\n const cryptoObject = globalThis.crypto;\n\n if (cryptoObject && typeof cryptoObject.getRandomValues === 'function') {\n cryptoObject.getRandomValues(bytes);\n return bytes;\n }\n\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n\n return bytes;\n}\n\nfunction generateInstallationId(): string {\n const bytes = createRandomBytes(16);\n bytes[6] = ((bytes[6] ?? 0) & 0x0f) | 0x40;\n bytes[8] = ((bytes[8] ?? 0) & 0x3f) | 0x80;\n\n const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('');\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\nexport async function getInstallationId(): Promise<string | undefined> {\n try {\n const storedInstallationId = await AsyncStorage.getItem(INSTALLATION_ID_STORAGE_KEY);\n if (storedInstallationId) {\n return storedInstallationId;\n }\n\n const installationId = generateInstallationId();\n await AsyncStorage.setItem(INSTALLATION_ID_STORAGE_KEY, installationId);\n return installationId;\n } catch (_error) {\n return undefined;\n }\n}\n"]}