@grafana/faro-react-native 1.2.1 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +118 -36
- package/android/consumer-proguard-rules.pro +2 -0
- package/android/src/main/java/com/grafana/faro/reactnative/ANRTracker.kt +61 -9
- package/android/src/main/java/com/grafana/faro/reactnative/AnrThreadDumpParser.kt +70 -0
- package/android/src/main/java/com/grafana/faro/reactnative/ApplicationExitTraceReader.kt +142 -0
- package/android/src/main/java/com/grafana/faro/reactnative/FaroAnrCache.kt +163 -0
- package/android/src/main/java/com/grafana/faro/reactnative/FaroAnrReporter.kt +163 -0
- package/android/src/main/java/com/grafana/faro/reactnative/FaroCrashReporter.kt +243 -50
- package/android/src/main/java/com/grafana/faro/reactnative/FaroCrashTraceCache.kt +75 -0
- package/android/src/main/java/com/grafana/faro/reactnative/FaroNativeCrashTrace.kt +39 -0
- package/android/src/main/java/com/grafana/faro/reactnative/FaroReactNativeModule.kt +99 -8
- package/android/src/main/java/com/grafana/faro/reactnative/FaroReactNativePackage.kt +1 -0
- package/android/src/main/java/com/grafana/faro/reactnative/FaroUncaughtExceptionHandler.kt +62 -0
- package/android/src/main/java/com/grafana/faro/reactnative/TombstoneBacktraceFormatter.kt +117 -0
- package/android/src/main/java/com/grafana/faro/reactnative/TombstoneModels.kt +35 -0
- package/android/src/main/java/com/grafana/faro/reactnative/TombstoneWireParser.kt +235 -0
- package/android/src/main/proto/tombstone.proto +62 -0
- package/android/src/test/java/com/grafana/faro/reactnative/AnrStackFiltersTest.kt +28 -0
- package/android/src/test/java/com/grafana/faro/reactnative/AnrThreadDumpParserTest.kt +38 -0
- package/android/src/test/java/com/grafana/faro/reactnative/FaroAnrCacheTest.kt +81 -0
- package/android/src/test/java/com/grafana/faro/reactnative/TombstoneWireParserTest.kt +51 -0
- package/dist/cjs/config/getRNInstrumentations.js +3 -1
- package/dist/cjs/config/getRNInstrumentations.js.map +1 -1
- package/dist/cjs/config/makeRNConfig.js +48 -9
- package/dist/cjs/config/makeRNConfig.js.map +1 -1
- package/dist/cjs/config/types.js.map +1 -1
- package/dist/cjs/generated/faroRNPackageMeta.js +1 -1
- package/dist/cjs/generated/faroRNPackageMeta.js.map +1 -1
- package/dist/cjs/index.js +3 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/initialize.js +14 -8
- package/dist/cjs/initialize.js.map +1 -1
- package/dist/cjs/instrumentations/anr/anrStack.js +19 -0
- package/dist/cjs/instrumentations/anr/anrStack.js.map +1 -0
- package/dist/cjs/instrumentations/anr/instrumentation.js +374 -72
- package/dist/cjs/instrumentations/anr/instrumentation.js.map +1 -1
- package/dist/cjs/instrumentations/anr/types.js.map +1 -1
- package/dist/cjs/instrumentations/console/index.js +5 -1
- package/dist/cjs/instrumentations/console/index.js.map +1 -1
- package/dist/cjs/instrumentations/crashReporting/{instrumentation.js → BaseCrashReportingInstrumentation.js} +110 -103
- package/dist/cjs/instrumentations/crashReporting/BaseCrashReportingInstrumentation.js.map +1 -0
- package/dist/cjs/instrumentations/crashReporting/NoOpCrashReportingInstrumentation.js +41 -0
- package/dist/cjs/instrumentations/crashReporting/NoOpCrashReportingInstrumentation.js.map +1 -0
- package/dist/cjs/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.js +87 -0
- package/dist/cjs/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.js.map +1 -0
- package/dist/cjs/instrumentations/crashReporting/android/crashErrorMessage.js +123 -0
- package/dist/cjs/instrumentations/crashReporting/android/crashErrorMessage.js.map +1 -0
- package/dist/cjs/instrumentations/crashReporting/android/index.js +12 -0
- package/dist/cjs/instrumentations/crashReporting/android/index.js.map +1 -0
- package/dist/cjs/instrumentations/crashReporting/android/nativeTombstoneTrace.js +11 -0
- package/dist/cjs/instrumentations/crashReporting/android/nativeTombstoneTrace.js.map +1 -0
- package/dist/cjs/instrumentations/crashReporting/android/parseAndroidCrashTrace.js +181 -0
- package/dist/cjs/instrumentations/crashReporting/android/parseAndroidCrashTrace.js.map +1 -0
- package/dist/cjs/instrumentations/crashReporting/index.js +35 -2
- package/dist/cjs/instrumentations/crashReporting/index.js.map +1 -1
- package/dist/cjs/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.js +78 -0
- package/dist/cjs/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.js.map +1 -0
- package/dist/cjs/instrumentations/crashReporting/ios/crashErrorMessage.js +103 -0
- package/dist/cjs/instrumentations/crashReporting/ios/crashErrorMessage.js.map +1 -0
- package/dist/cjs/instrumentations/crashReporting/ios/index.js +11 -0
- package/dist/cjs/instrumentations/crashReporting/ios/index.js.map +1 -0
- package/dist/cjs/instrumentations/crashReporting/ios/parseIosCrashTrace.js +48 -0
- package/dist/cjs/instrumentations/crashReporting/ios/parseIosCrashTrace.js.map +1 -0
- package/dist/cjs/instrumentations/crashReporting/types.js.map +1 -1
- package/dist/cjs/instrumentations/errors/index.js +2 -1
- package/dist/cjs/instrumentations/errors/index.js.map +1 -1
- package/dist/cjs/instrumentations/session/installationId.js +91 -0
- package/dist/cjs/instrumentations/session/installationId.js.map +1 -0
- package/dist/cjs/instrumentations/session/sessionAttributes.js +152 -89
- package/dist/cjs/instrumentations/session/sessionAttributes.js.map +1 -1
- package/dist/cjs/metas/appBuildIdentity.js +95 -0
- package/dist/cjs/metas/appBuildIdentity.js.map +1 -0
- package/dist/cjs/testUtils/mockDeviceInfo.js +5 -0
- package/dist/cjs/testUtils/mockDeviceInfo.js.map +1 -1
- package/dist/cjs/testUtils/setupTests.js +7 -0
- package/dist/cjs/testUtils/setupTests.js.map +1 -1
- package/dist/esm/config/getRNInstrumentations.js +3 -1
- package/dist/esm/config/getRNInstrumentations.js.map +1 -1
- package/dist/esm/config/makeRNConfig.js +49 -10
- package/dist/esm/config/makeRNConfig.js.map +1 -1
- package/dist/esm/config/types.js.map +1 -1
- package/dist/esm/generated/faroRNPackageMeta.js +1 -1
- package/dist/esm/generated/faroRNPackageMeta.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/initialize.js +11 -5
- package/dist/esm/initialize.js.map +1 -1
- package/dist/esm/instrumentations/anr/anrStack.js +16 -0
- package/dist/esm/instrumentations/anr/anrStack.js.map +1 -0
- package/dist/esm/instrumentations/anr/instrumentation.js +260 -67
- package/dist/esm/instrumentations/anr/instrumentation.js.map +1 -1
- package/dist/esm/instrumentations/anr/types.js.map +1 -1
- package/dist/esm/instrumentations/console/index.js +5 -1
- package/dist/esm/instrumentations/console/index.js.map +1 -1
- package/dist/esm/instrumentations/crashReporting/{instrumentation.js → BaseCrashReportingInstrumentation.js} +76 -94
- package/dist/esm/instrumentations/crashReporting/BaseCrashReportingInstrumentation.js.map +1 -0
- package/dist/esm/instrumentations/crashReporting/NoOpCrashReportingInstrumentation.js +18 -0
- package/dist/esm/instrumentations/crashReporting/NoOpCrashReportingInstrumentation.js.map +1 -0
- package/dist/esm/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.js +56 -0
- package/dist/esm/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.js.map +1 -0
- package/dist/esm/instrumentations/crashReporting/android/crashErrorMessage.js +116 -0
- package/dist/esm/instrumentations/crashReporting/android/crashErrorMessage.js.map +1 -0
- package/dist/esm/instrumentations/crashReporting/android/index.js +4 -0
- package/dist/esm/instrumentations/crashReporting/android/index.js.map +1 -0
- package/dist/esm/instrumentations/crashReporting/android/nativeTombstoneTrace.js +8 -0
- package/dist/esm/instrumentations/crashReporting/android/nativeTombstoneTrace.js.map +1 -0
- package/dist/esm/instrumentations/crashReporting/android/parseAndroidCrashTrace.js +174 -0
- package/dist/esm/instrumentations/crashReporting/android/parseAndroidCrashTrace.js.map +1 -0
- package/dist/esm/instrumentations/crashReporting/index.js +35 -1
- package/dist/esm/instrumentations/crashReporting/index.js.map +1 -1
- package/dist/esm/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.js +56 -0
- package/dist/esm/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.js.map +1 -0
- package/dist/esm/instrumentations/crashReporting/ios/crashErrorMessage.js +98 -0
- package/dist/esm/instrumentations/crashReporting/ios/crashErrorMessage.js.map +1 -0
- package/dist/esm/instrumentations/crashReporting/ios/index.js +4 -0
- package/dist/esm/instrumentations/crashReporting/ios/index.js.map +1 -0
- package/dist/esm/instrumentations/crashReporting/ios/parseIosCrashTrace.js +44 -0
- package/dist/esm/instrumentations/crashReporting/ios/parseIosCrashTrace.js.map +1 -0
- package/dist/esm/instrumentations/crashReporting/types.js.map +1 -1
- package/dist/esm/instrumentations/errors/index.js +2 -1
- package/dist/esm/instrumentations/errors/index.js.map +1 -1
- package/dist/esm/instrumentations/session/installationId.js +48 -0
- package/dist/esm/instrumentations/session/installationId.js.map +1 -0
- package/dist/esm/instrumentations/session/sessionAttributes.js +83 -38
- package/dist/esm/instrumentations/session/sessionAttributes.js.map +1 -1
- package/dist/esm/metas/appBuildIdentity.js +56 -0
- package/dist/esm/metas/appBuildIdentity.js.map +1 -0
- package/dist/esm/testUtils/mockDeviceInfo.js +5 -0
- package/dist/esm/testUtils/mockDeviceInfo.js.map +1 -1
- package/dist/esm/testUtils/setupTests.js +7 -0
- package/dist/esm/testUtils/setupTests.js.map +1 -1
- package/dist/types/config/makeRNConfig.d.ts +4 -3
- package/dist/types/config/types.d.ts +2 -1
- package/dist/types/generated/faroRNPackageMeta.d.ts +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/initialize.d.ts +4 -2
- package/dist/types/instrumentations/anr/anrStack.d.ts +7 -0
- package/dist/types/instrumentations/anr/instrumentation.d.ts +23 -28
- package/dist/types/instrumentations/anr/types.d.ts +5 -1
- package/dist/types/instrumentations/appState/index.d.ts +1 -1
- package/dist/types/instrumentations/console/index.d.ts +1 -1
- package/dist/types/instrumentations/crashReporting/BaseCrashReportingInstrumentation.d.ts +56 -0
- package/dist/types/instrumentations/crashReporting/NoOpCrashReportingInstrumentation.d.ts +12 -0
- package/dist/types/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.d.ts +26 -0
- package/dist/types/instrumentations/crashReporting/android/crashErrorMessage.d.ts +23 -0
- package/dist/types/instrumentations/crashReporting/android/index.d.ts +4 -0
- package/dist/types/instrumentations/crashReporting/android/nativeTombstoneTrace.d.ts +2 -0
- package/dist/types/instrumentations/crashReporting/android/parseAndroidCrashTrace.d.ts +45 -0
- package/dist/types/instrumentations/crashReporting/index.d.ts +25 -2
- package/dist/types/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.d.ts +28 -0
- package/dist/types/instrumentations/crashReporting/ios/crashErrorMessage.d.ts +14 -0
- package/dist/types/instrumentations/crashReporting/ios/index.d.ts +4 -0
- package/dist/types/instrumentations/crashReporting/ios/parseIosCrashTrace.d.ts +38 -0
- package/dist/types/instrumentations/crashReporting/types.d.ts +18 -51
- package/dist/types/instrumentations/frameMonitoring/instrumentation.d.ts +1 -1
- package/dist/types/instrumentations/http/index.d.ts +1 -1
- package/dist/types/instrumentations/performance/index.d.ts +1 -1
- package/dist/types/instrumentations/session/index.d.ts +1 -1
- package/dist/types/instrumentations/session/installationId.d.ts +1 -0
- package/dist/types/instrumentations/session/sessionAttributes.d.ts +13 -4
- package/dist/types/instrumentations/startup/index.d.ts +1 -1
- package/dist/types/instrumentations/userActions/index.d.ts +1 -1
- package/dist/types/instrumentations/view/index.d.ts +1 -1
- package/dist/types/instrumentations/xhr/index.d.ts +1 -1
- package/dist/types/metas/appBuildIdentity.d.ts +16 -0
- package/dist/types/testUtils/mockFaroReactNativeTracing.d.ts +1 -1
- package/dist/types/transports/console/transport.d.ts +1 -1
- package/dist/types/transports/fetch/transport.d.ts +1 -1
- package/dist/types/transports/offline/transport.d.ts +1 -1
- package/package.json +4 -4
- package/src/config/getRNInstrumentations.ts +5 -1
- package/src/config/makeRNConfig.test.ts +59 -3
- package/src/config/makeRNConfig.ts +48 -9
- package/src/config/types.ts +2 -1
- package/src/generated/faroRNPackageMeta.ts +1 -1
- package/src/index.ts +2 -1
- package/src/initialize.test.ts +71 -15
- package/src/initialize.ts +11 -5
- package/src/instrumentations/anr/anrStack.test.ts +27 -0
- package/src/instrumentations/anr/anrStack.ts +19 -0
- package/src/instrumentations/anr/instrumentation.test.ts +45 -0
- package/src/instrumentations/anr/instrumentation.ts +301 -67
- package/src/instrumentations/anr/types.ts +7 -1
- package/src/instrumentations/console/index.ts +5 -1
- package/src/instrumentations/console/instrumentation.test.ts +5 -0
- package/src/instrumentations/crashReporting/{instrumentation.ts → BaseCrashReportingInstrumentation.ts} +119 -93
- package/src/instrumentations/crashReporting/NoOpCrashReportingInstrumentation.ts +23 -0
- package/src/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.ts +62 -0
- package/src/instrumentations/crashReporting/android/crashErrorMessage.test.ts +182 -0
- package/src/instrumentations/crashReporting/android/crashErrorMessage.ts +135 -0
- package/src/instrumentations/crashReporting/android/index.ts +4 -0
- package/src/instrumentations/crashReporting/android/nativeTombstoneTrace.test.ts +19 -0
- package/src/instrumentations/crashReporting/android/nativeTombstoneTrace.ts +8 -0
- package/src/instrumentations/crashReporting/android/parseAndroidCrashTrace.test.ts +232 -0
- package/src/instrumentations/crashReporting/android/parseAndroidCrashTrace.ts +235 -0
- package/src/instrumentations/crashReporting/index.ts +43 -2
- package/src/instrumentations/crashReporting/instrumentation.test.ts +42 -0
- package/src/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.ts +62 -0
- package/src/instrumentations/crashReporting/ios/crashErrorMessage.test.ts +170 -0
- package/src/instrumentations/crashReporting/ios/crashErrorMessage.ts +111 -0
- package/src/instrumentations/crashReporting/ios/index.ts +4 -0
- package/src/instrumentations/crashReporting/ios/parseIosCrashTrace.test.ts +86 -0
- package/src/instrumentations/crashReporting/ios/parseIosCrashTrace.ts +83 -0
- package/src/instrumentations/crashReporting/types.ts +19 -58
- package/src/instrumentations/errors/index.ts +2 -1
- package/src/instrumentations/errors/instrumentation.test.ts +8 -2
- package/src/instrumentations/errors/stackTraceParser.test.ts +1 -1
- package/src/instrumentations/session/installationId.ts +43 -0
- package/src/instrumentations/session/sessionAttributes.test.ts +260 -30
- package/src/instrumentations/session/sessionAttributes.ts +112 -22
- package/src/metas/appBuildIdentity.test.ts +48 -0
- package/src/metas/appBuildIdentity.ts +50 -0
- package/src/testUtils/mockDeviceInfo.ts +5 -0
- package/src/testUtils/setupTests.ts +7 -0
- package/dist/cjs/instrumentations/crashReporting/instrumentation.js.map +0 -1
- package/dist/esm/instrumentations/crashReporting/instrumentation.js.map +0 -1
- package/dist/types/instrumentations/crashReporting/instrumentation.d.ts +0 -58
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
11
|
+
const INSTALLATION_ID_STORAGE_KEY = '@grafana/faro-react-native/installation_id';
|
|
12
|
+
function createRandomBytes(length) {
|
|
13
|
+
const bytes = new Uint8Array(length);
|
|
14
|
+
const cryptoObject = globalThis.crypto;
|
|
15
|
+
if (cryptoObject && typeof cryptoObject.getRandomValues === 'function') {
|
|
16
|
+
cryptoObject.getRandomValues(bytes);
|
|
17
|
+
return bytes;
|
|
18
|
+
}
|
|
19
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
20
|
+
bytes[i] = Math.floor(Math.random() * 256);
|
|
21
|
+
}
|
|
22
|
+
return bytes;
|
|
23
|
+
}
|
|
24
|
+
function generateInstallationId() {
|
|
25
|
+
var _a, _b;
|
|
26
|
+
const bytes = createRandomBytes(16);
|
|
27
|
+
bytes[6] = (((_a = bytes[6]) !== null && _a !== void 0 ? _a : 0) & 0x0f) | 0x40;
|
|
28
|
+
bytes[8] = (((_b = bytes[8]) !== null && _b !== void 0 ? _b : 0) & 0x3f) | 0x80;
|
|
29
|
+
const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('');
|
|
30
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
31
|
+
}
|
|
32
|
+
export function getInstallationId() {
|
|
33
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
try {
|
|
35
|
+
const storedInstallationId = yield AsyncStorage.getItem(INSTALLATION_ID_STORAGE_KEY);
|
|
36
|
+
if (storedInstallationId) {
|
|
37
|
+
return storedInstallationId;
|
|
38
|
+
}
|
|
39
|
+
const installationId = generateInstallationId();
|
|
40
|
+
yield AsyncStorage.setItem(INSTALLATION_ID_STORAGE_KEY, installationId);
|
|
41
|
+
return installationId;
|
|
42
|
+
}
|
|
43
|
+
catch (_error) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=installationId.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installationId.js","sourceRoot":"","sources":["../../../../src/instrumentations/session/installationId.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,YAAY,MAAM,2CAA2C,CAAC;AAErE,MAAM,2BAA2B,GAAG,4CAA4C,CAAC;AAEjF,SAAS,iBAAiB,CAAC,MAAc;IACvC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,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,MAAM,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,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACrF,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;AAC7G,CAAC;AAED,MAAM,UAAgB,iBAAiB;;QACrC,IAAI,CAAC;YACH,MAAM,oBAAoB,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC;YACrF,IAAI,oBAAoB,EAAE,CAAC;gBACzB,OAAO,oBAAoB,CAAC;YAC9B,CAAC;YAED,MAAM,cAAc,GAAG,sBAAsB,EAAE,CAAC;YAChD,MAAM,YAAY,CAAC,OAAO,CAAC,2BAA2B,EAAE,cAAc,CAAC,CAAC;YACxE,OAAO,cAAc,CAAC;QACxB,CAAC;QAAC,OAAO,MAAM,EAAE,CAAC;YAChB,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;CAAA","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"]}
|
|
@@ -9,6 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { Platform } from 'react-native';
|
|
11
11
|
import DeviceInfo from 'react-native-device-info';
|
|
12
|
+
import { getInstallationId } from './installationId';
|
|
12
13
|
/**
|
|
13
14
|
* React Native framework version from `Platform.constants` (host app runtime), not `@grafana/faro-react-native` semver.
|
|
14
15
|
*/
|
|
@@ -29,20 +30,35 @@ function getReactNativeVersion() {
|
|
|
29
30
|
return 'unknown';
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
33
|
+
function getStructuredDeviceBrand(model, brand) {
|
|
34
|
+
if (Platform.OS !== 'ios') {
|
|
35
|
+
return brand;
|
|
36
|
+
}
|
|
37
|
+
return model.toLowerCase().includes('ipad') ? 'iPad' : 'iPhone';
|
|
38
|
+
}
|
|
39
|
+
function getStructuredDeviceManufacturer(manufacturer) {
|
|
40
|
+
return Platform.OS === 'ios' ? manufacturer.toLowerCase() : manufacturer;
|
|
41
|
+
}
|
|
42
|
+
function getStructuredDeviceModelIdentifier(model) {
|
|
43
|
+
// Android getDeviceId() returns a board code, so use Build.MODEL for the Faro
|
|
44
|
+
// model identifier.
|
|
45
|
+
if (Platform.OS === 'android') {
|
|
46
|
+
return model;
|
|
47
|
+
}
|
|
48
|
+
// React Native reports iPhone and iPadOS apps as Platform.OS === 'ios'.
|
|
49
|
+
// react-native-device-info exposes the Apple hardware identifier here.
|
|
50
|
+
if (Platform.OS === 'ios') {
|
|
51
|
+
return DeviceInfo.getDeviceId();
|
|
52
|
+
}
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
function getMobileDeviceType(isTablet) {
|
|
56
|
+
// iPadOS is still reported as Platform.OS === 'ios'; DeviceInfo.isTablet()
|
|
57
|
+
// distinguishes iPad/tablet form factor from phone form factor.
|
|
58
|
+
if (Platform.OS === 'ios' || Platform.OS === 'android') {
|
|
59
|
+
return isTablet ? 'tablet' : 'mobile';
|
|
60
|
+
}
|
|
61
|
+
return undefined;
|
|
46
62
|
}
|
|
47
63
|
/**
|
|
48
64
|
* Get OS detail string matching Flutter SDK format
|
|
@@ -65,6 +81,19 @@ function getDeviceOsDetail() {
|
|
|
65
81
|
return `${systemName} ${systemVersion}`;
|
|
66
82
|
});
|
|
67
83
|
}
|
|
84
|
+
function getDeviceOsBuildId() {
|
|
85
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
86
|
+
try {
|
|
87
|
+
// RN device-info exposes a useful OS build id on both Android and iOS.
|
|
88
|
+
// Keep it omitted when unavailable instead of sending "unknown".
|
|
89
|
+
const buildId = yield DeviceInfo.getBuildId();
|
|
90
|
+
return buildId && buildId !== 'unknown' ? buildId : undefined;
|
|
91
|
+
}
|
|
92
|
+
catch (_error) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
68
97
|
/**
|
|
69
98
|
* Session attributes without device props when async collection or DeviceInfo is unavailable.
|
|
70
99
|
* No synchronous DeviceInfo reads — use {@link getSessionAttributes} or the package async `initializeFaro`.
|
|
@@ -91,20 +120,29 @@ export function minimalSessionDeviceAttributes() {
|
|
|
91
120
|
* - device_carrier
|
|
92
121
|
*/
|
|
93
122
|
export function getSessionAttributes() {
|
|
123
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
124
|
+
return (yield collectMobileMeta()).sessionAttributes;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function collectMobileMeta() {
|
|
94
128
|
return __awaiter(this, void 0, void 0, function* () {
|
|
95
129
|
try {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
130
|
+
const [deviceOsDetail, deviceOsBuildId, installationId] = yield Promise.all([
|
|
131
|
+
getDeviceOsDetail(),
|
|
132
|
+
getDeviceOsBuildId(),
|
|
133
|
+
getInstallationId(),
|
|
134
|
+
]);
|
|
99
135
|
// Get synchronous device info
|
|
100
136
|
const systemName = DeviceInfo.getSystemName();
|
|
101
137
|
const systemVersion = DeviceInfo.getSystemVersion();
|
|
102
138
|
const manufacturer = DeviceInfo.getManufacturerSync();
|
|
103
139
|
const model = DeviceInfo.getModel();
|
|
140
|
+
const modelIdentifier = getStructuredDeviceModelIdentifier(model);
|
|
104
141
|
const deviceName = DeviceInfo.getDeviceNameSync();
|
|
105
142
|
const brand = DeviceInfo.getBrand();
|
|
106
143
|
const isEmulator = DeviceInfo.isEmulatorSync();
|
|
107
144
|
const isTablet = DeviceInfo.isTablet();
|
|
145
|
+
const deviceType = getMobileDeviceType(isTablet);
|
|
108
146
|
// Memory info
|
|
109
147
|
const totalMemory = DeviceInfo.getTotalMemorySync();
|
|
110
148
|
const usedMemory = DeviceInfo.getUsedMemorySync();
|
|
@@ -146,32 +184,39 @@ export function getSessionAttributes() {
|
|
|
146
184
|
catch (_error) {
|
|
147
185
|
// Carrier not available
|
|
148
186
|
}
|
|
149
|
-
const attributes = {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
device_memory_total: String(totalMemory),
|
|
162
|
-
device_memory_used: String(usedMemory),
|
|
163
|
-
device_battery_level: batteryLevel,
|
|
164
|
-
device_is_charging: isCharging,
|
|
165
|
-
device_low_power_mode: lowPowerMode,
|
|
166
|
-
device_carrier: carrier,
|
|
187
|
+
const attributes = Object.assign(Object.assign(Object.assign({ react_native_version: reactNativeVersion, device_os: systemName, device_os_version: systemVersion, device_os_detail: deviceOsDetail, device_manufacturer: manufacturer.toLowerCase(), device_model: model, device_model_name: deviceName, device_brand: brand, device_is_physical: String(!isEmulator) }, (installationId ? { device_id: installationId } : {})), (deviceType ? { device_type: deviceType } : {})), { device_memory_total: String(totalMemory), device_memory_used: String(usedMemory), device_battery_level: batteryLevel, device_is_charging: isCharging, device_low_power_mode: lowPowerMode, device_carrier: carrier });
|
|
188
|
+
const appMeta = installationId ? { installationId } : {};
|
|
189
|
+
const structuredDeviceBrand = getStructuredDeviceBrand(model, brand);
|
|
190
|
+
const structuredDeviceManufacturer = getStructuredDeviceManufacturer(manufacturer);
|
|
191
|
+
const osMeta = Object.assign(Object.assign({}, (deviceOsBuildId ? { build_id: deviceOsBuildId } : {})), { detail: deviceOsDetail, name: systemName, version: systemVersion });
|
|
192
|
+
return {
|
|
193
|
+
sessionAttributes: attributes,
|
|
194
|
+
meta: {
|
|
195
|
+
app: appMeta,
|
|
196
|
+
device: Object.assign(Object.assign(Object.assign({ brand: structuredDeviceBrand, is_physical: !isEmulator, manufacturer: structuredDeviceManufacturer }, (modelIdentifier ? { model_identifier: modelIdentifier } : {})), { model_name: model }), (deviceType ? { type: deviceType } : {})),
|
|
197
|
+
os: osMeta,
|
|
198
|
+
},
|
|
167
199
|
};
|
|
168
|
-
return attributes;
|
|
169
200
|
}
|
|
170
201
|
catch (_error) {
|
|
171
|
-
|
|
202
|
+
const installationId = yield getInstallationId();
|
|
203
|
+
return {
|
|
204
|
+
sessionAttributes: minimalSessionDeviceAttributes(),
|
|
205
|
+
meta: {
|
|
206
|
+
app: installationId ? { installationId } : {},
|
|
207
|
+
},
|
|
208
|
+
};
|
|
172
209
|
}
|
|
173
210
|
});
|
|
174
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Get structured mobile meta plus flat session attributes for async `initializeFaro`.
|
|
214
|
+
*/
|
|
215
|
+
export function loadMobileMetaForInit() {
|
|
216
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
217
|
+
return collectMobileMeta();
|
|
218
|
+
});
|
|
219
|
+
}
|
|
175
220
|
/**
|
|
176
221
|
* Await full async session device attributes (battery, carrier, etc.), then fall back to
|
|
177
222
|
* {@link minimalSessionDeviceAttributes} if anything throws. Used by async `initializeFaro`.
|
|
@@ -179,7 +224,7 @@ export function getSessionAttributes() {
|
|
|
179
224
|
export function loadSessionDeviceAttributesForInit() {
|
|
180
225
|
return __awaiter(this, void 0, void 0, function* () {
|
|
181
226
|
try {
|
|
182
|
-
return yield
|
|
227
|
+
return (yield loadMobileMetaForInit()).sessionAttributes;
|
|
183
228
|
}
|
|
184
229
|
catch (_a) {
|
|
185
230
|
return minimalSessionDeviceAttributes();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionAttributes.js","sourceRoot":"","sources":["../../../../src/instrumentations/session/sessionAttributes.ts"],"names":[],"mappings":"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","sourcesContent":["import { Platform } from 'react-native';\nimport DeviceInfo from 'react-native-device-info';\n\n/**\n * Session attributes for React Native\n * These attributes are automatically included with every telemetry event\n *\n * Core attributes match Flutter SDK format, with additional mobile-specific\n * monitoring fields (memory, device type, battery, etc.)\n *\n * SDK name, core version, and npm adapter are on Faro meta `sdk` (`getSdkMeta` in `metas/sdk.ts`).\n *\n * `react_native_version` is the host app's React Native **framework** version from `Platform`, not the Faro package.\n */\nexport interface SessionAttributes {\n /** Host app's React Native framework version (e.g. \"0.75.1\") from `Platform.constants`. */\n react_native_version: string;\n\n /** Operating system (\"iOS\" or \"Android\") */\n device_os?: string;\n\n /** OS version (e.g., \"17.0\" for iOS, \"15\" for Android) */\n device_os_version?: string;\n\n /** Detailed OS info (e.g., \"iOS 17.0\" or \"Android 15 (SDK 35)\") */\n device_os_detail?: string;\n\n /** Device manufacturer (e.g., \"apple\", \"samsung\") */\n device_manufacturer?: string;\n\n /** Raw model identifier (e.g., \"iPhone16,1\", \"SM-A155F\") */\n device_model?: string;\n\n /** Human-readable model name (e.g., \"iPhone 15 Pro\") */\n device_model_name?: string;\n\n /** Device brand (e.g., \"iPhone\", \"samsung\") */\n device_brand?: string;\n\n /** Whether device is physical or emulator (\"true\" or \"false\") */\n device_is_physical?: string;\n\n /** Unique device ID (UUID) */\n device_id?: string;\n\n /** Device type (\"mobile\" or \"tablet\") */\n device_type?: string;\n\n /** Total device memory in bytes */\n device_memory_total?: string;\n\n /** Currently used memory in bytes */\n device_memory_used?: string;\n\n /** Battery level percentage (e.g., \"85\") - empty if unavailable */\n device_battery_level?: string;\n\n /** Whether device is charging (\"true\" or \"false\") - empty if unavailable */\n device_is_charging?: string;\n\n /** Whether low power mode is enabled (\"true\" or \"false\") - empty if unavailable */\n device_low_power_mode?: string;\n\n /** Mobile carrier name (e.g., \"Verizon\") - empty if unavailable */\n device_carrier?: string;\n}\n\n/**\n * React Native framework version from `Platform.constants` (host app runtime), not `@grafana/faro-react-native` semver.\n */\nfunction getReactNativeVersion(): string {\n try {\n const version = Platform.constants.reactNativeVersion;\n if (version && typeof version === 'object') {\n const { major, minor, patch, prerelease } = version as {\n major: number;\n minor: number;\n patch: number;\n prerelease?: number;\n };\n let versionString = `${major}.${minor}.${patch}`;\n if (prerelease) {\n versionString += `-rc.${prerelease}`;\n }\n return versionString;\n }\n return 'unknown';\n } catch (_error) {\n return 'unknown';\n }\n}\n\n/**\n * Get device ID using react-native-device-info\n * Returns unique device identifier or 'unknown' on error\n */\nasync function getDeviceId(): Promise<string> {\n try {\n // getUniqueId returns a UUID that persists across app installations\n return await DeviceInfo.getUniqueId();\n } catch (_error) {\n return 'unknown';\n }\n}\n\n/**\n * Get OS detail string matching Flutter SDK format\n * iOS: \"iOS 17.0\"\n * Android: \"Android 15 (SDK 35)\"\n */\nasync function getDeviceOsDetail(): Promise<string> {\n const systemName = DeviceInfo.getSystemName();\n const systemVersion = DeviceInfo.getSystemVersion();\n\n if (Platform.OS === 'android') {\n try {\n const apiLevel = await DeviceInfo.getApiLevel();\n return `${systemName} ${systemVersion} (SDK ${apiLevel})`;\n } catch (_error) {\n return `${systemName} ${systemVersion}`;\n }\n }\n\n return `${systemName} ${systemVersion}`;\n}\n\n/**\n * Session attributes without device props when async collection or DeviceInfo is unavailable.\n * No synchronous DeviceInfo reads — use {@link getSessionAttributes} or the package async `initializeFaro`.\n */\nexport function minimalSessionDeviceAttributes(): SessionAttributes {\n return {\n react_native_version: getReactNativeVersion(),\n };\n}\n\n/**\n * Get all session attributes\n * These attributes are automatically included with every telemetry event\n *\n * Core attributes matching Flutter SDK:\n * - react_native_version (RN framework in the host app)\n * - device_os, device_os_version, device_os_detail\n * - device_manufacturer, device_model, device_model_name\n * - device_brand, device_is_physical, device_id\n *\n * Additional monitoring attributes:\n * - device_type (mobile/tablet)\n * - device_memory_total, device_memory_used\n * - device_battery_level, device_is_charging, device_low_power_mode\n * - device_carrier\n */\nexport async function getSessionAttributes(): Promise<SessionAttributes> {\n try {\n // Get device ID asynchronously\n const deviceId = await getDeviceId();\n const deviceOsDetail = await getDeviceOsDetail();\n\n // Get synchronous device info\n const systemName = DeviceInfo.getSystemName();\n const systemVersion = DeviceInfo.getSystemVersion();\n const manufacturer = DeviceInfo.getManufacturerSync();\n const model = DeviceInfo.getModel();\n const deviceName = DeviceInfo.getDeviceNameSync();\n const brand = DeviceInfo.getBrand();\n const isEmulator = DeviceInfo.isEmulatorSync();\n const isTablet = DeviceInfo.isTablet();\n\n // Memory info\n const totalMemory = DeviceInfo.getTotalMemorySync();\n const usedMemory = DeviceInfo.getUsedMemorySync();\n const reactNativeVersion = getReactNativeVersion();\n\n // Try to get async device info (battery, carrier)\n let batteryLevel: string | undefined;\n let isCharging: string | undefined;\n let lowPowerMode: string | undefined;\n let carrier: string | undefined;\n\n try {\n const battery = await DeviceInfo.getBatteryLevel();\n if (battery >= 0) {\n batteryLevel = String(Math.round(battery * 100));\n }\n } catch (_error) {\n // Battery info not available\n }\n\n try {\n isCharging = String(await DeviceInfo.isBatteryCharging());\n } catch (_error) {\n // Charging status not available\n }\n\n try {\n if ('isPowerSaveMode' in DeviceInfo) {\n lowPowerMode = String(\n await (DeviceInfo as typeof DeviceInfo & { isPowerSaveMode: () => Promise<boolean> }).isPowerSaveMode()\n );\n }\n } catch (_error) {\n // Low power mode not available\n }\n\n try {\n const carrierName = await DeviceInfo.getCarrier();\n if (carrierName && carrierName !== 'unknown') {\n carrier = carrierName;\n }\n } catch (_error) {\n // Carrier not available\n }\n\n const attributes: SessionAttributes = {\n react_native_version: reactNativeVersion,\n device_os: systemName,\n device_os_version: systemVersion,\n device_os_detail: deviceOsDetail,\n device_manufacturer: manufacturer.toLowerCase(),\n device_model: model,\n device_model_name: deviceName,\n device_brand: brand,\n device_is_physical: String(!isEmulator),\n device_id: deviceId,\n device_type: isTablet ? 'tablet' : 'mobile',\n device_memory_total: String(totalMemory),\n device_memory_used: String(usedMemory),\n device_battery_level: batteryLevel,\n device_is_charging: isCharging,\n device_low_power_mode: lowPowerMode,\n device_carrier: carrier,\n };\n\n return attributes;\n } catch (_error) {\n return minimalSessionDeviceAttributes();\n }\n}\n\n/**\n * Await full async session device attributes (battery, carrier, etc.), then fall back to\n * {@link minimalSessionDeviceAttributes} if anything throws. Used by async `initializeFaro`.\n */\nexport async function loadSessionDeviceAttributesForInit(): Promise<SessionAttributes> {\n try {\n return await getSessionAttributes();\n } catch {\n return minimalSessionDeviceAttributes();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sessionAttributes.js","sourceRoot":"","sources":["../../../../src/instrumentations/session/sessionAttributes.ts"],"names":[],"mappings":"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","sourcesContent":["import { Platform } from 'react-native';\nimport DeviceInfo from 'react-native-device-info';\n\nimport type { Meta } from '@grafana/faro-core';\n\nimport { getInstallationId } from './installationId';\n\n/**\n * Session attributes for React Native\n * These attributes are automatically included with every telemetry event\n *\n * Core attributes match Flutter SDK format, with additional mobile-specific\n * monitoring fields (memory, device type, battery, etc.)\n *\n * SDK name, core version, and npm adapter are on Faro meta `sdk` (`getSdkMeta` in `metas/sdk.ts`).\n *\n * `react_native_version` is the host app's React Native **framework** version from `Platform`, not the Faro package.\n */\nexport interface SessionAttributes {\n /** Host app's React Native framework version (e.g. \"0.75.1\") from `Platform.constants`. */\n react_native_version: string;\n\n /** Operating system (\"iOS\" or \"Android\") */\n device_os?: string;\n\n /** OS version (e.g., \"17.0\" for iOS, \"15\" for Android) */\n device_os_version?: string;\n\n /** Detailed OS info (e.g., \"iOS 17.0\" or \"Android 15 (SDK 35)\") */\n device_os_detail?: string;\n\n /** Device manufacturer (e.g., \"apple\", \"samsung\", \"Google\") */\n device_manufacturer?: string;\n\n /** Device model in flat session attributes (e.g., \"iPhone 15 Pro\", \"SM-A155F\") */\n device_model?: string;\n\n /** Human-readable model name (e.g., \"iPhone 15 Pro\") */\n device_model_name?: string;\n\n /** Device brand in flat session attributes (e.g., \"Apple\", \"samsung\") */\n device_brand?: string;\n\n /** Whether device is physical or emulator (\"true\" or \"false\") */\n device_is_physical?: string;\n\n /** Temporary flat attribute mirroring `app.installationId` during migration. */\n device_id?: string;\n\n /** Device type (\"mobile\" or \"tablet\") */\n device_type?: string;\n\n /** Total device memory in bytes */\n device_memory_total?: string;\n\n /** Currently used memory in bytes */\n device_memory_used?: string;\n\n /** Battery level percentage (e.g., \"85\") - empty if unavailable */\n device_battery_level?: string;\n\n /** Whether device is charging (\"true\" or \"false\") - empty if unavailable */\n device_is_charging?: string;\n\n /** Whether low power mode is enabled (\"true\" or \"false\") - empty if unavailable */\n device_low_power_mode?: string;\n\n /** Mobile carrier name (e.g., \"Verizon\") - empty if unavailable */\n device_carrier?: string;\n}\n\nexport interface PreloadedMobileMeta {\n sessionAttributes: SessionAttributes;\n meta: Pick<Meta, 'app' | 'device' | 'os'>;\n}\n\n/**\n * React Native framework version from `Platform.constants` (host app runtime), not `@grafana/faro-react-native` semver.\n */\nfunction getReactNativeVersion(): string {\n try {\n const version = Platform.constants.reactNativeVersion;\n if (version && typeof version === 'object') {\n const { major, minor, patch, prerelease } = version as {\n major: number;\n minor: number;\n patch: number;\n prerelease?: number;\n };\n let versionString = `${major}.${minor}.${patch}`;\n if (prerelease) {\n versionString += `-rc.${prerelease}`;\n }\n return versionString;\n }\n return 'unknown';\n } catch (_error) {\n return 'unknown';\n }\n}\n\nfunction getStructuredDeviceBrand(model: string, brand: string): string {\n if (Platform.OS !== 'ios') {\n return brand;\n }\n\n return model.toLowerCase().includes('ipad') ? 'iPad' : 'iPhone';\n}\n\nfunction getStructuredDeviceManufacturer(manufacturer: string): string {\n return Platform.OS === 'ios' ? manufacturer.toLowerCase() : manufacturer;\n}\n\nfunction getStructuredDeviceModelIdentifier(model: string): string | undefined {\n // Android getDeviceId() returns a board code, so use Build.MODEL for the Faro\n // model identifier.\n if (Platform.OS === 'android') {\n return model;\n }\n\n // React Native reports iPhone and iPadOS apps as Platform.OS === 'ios'.\n // react-native-device-info exposes the Apple hardware identifier here.\n if (Platform.OS === 'ios') {\n return DeviceInfo.getDeviceId();\n }\n\n return undefined;\n}\n\nfunction getMobileDeviceType(isTablet: boolean): 'mobile' | 'tablet' | undefined {\n // iPadOS is still reported as Platform.OS === 'ios'; DeviceInfo.isTablet()\n // distinguishes iPad/tablet form factor from phone form factor.\n if (Platform.OS === 'ios' || Platform.OS === 'android') {\n return isTablet ? 'tablet' : 'mobile';\n }\n\n return undefined;\n}\n\n/**\n * Get OS detail string matching Flutter SDK format\n * iOS: \"iOS 17.0\"\n * Android: \"Android 15 (SDK 35)\"\n */\nasync function getDeviceOsDetail(): Promise<string> {\n const systemName = DeviceInfo.getSystemName();\n const systemVersion = DeviceInfo.getSystemVersion();\n\n if (Platform.OS === 'android') {\n try {\n const apiLevel = await DeviceInfo.getApiLevel();\n return `${systemName} ${systemVersion} (SDK ${apiLevel})`;\n } catch (_error) {\n return `${systemName} ${systemVersion}`;\n }\n }\n\n return `${systemName} ${systemVersion}`;\n}\n\nasync function getDeviceOsBuildId(): Promise<string | undefined> {\n try {\n // RN device-info exposes a useful OS build id on both Android and iOS.\n // Keep it omitted when unavailable instead of sending \"unknown\".\n const buildId = await DeviceInfo.getBuildId();\n return buildId && buildId !== 'unknown' ? buildId : undefined;\n } catch (_error) {\n return undefined;\n }\n}\n\n/**\n * Session attributes without device props when async collection or DeviceInfo is unavailable.\n * No synchronous DeviceInfo reads — use {@link getSessionAttributes} or the package async `initializeFaro`.\n */\nexport function minimalSessionDeviceAttributes(): SessionAttributes {\n return {\n react_native_version: getReactNativeVersion(),\n };\n}\n\n/**\n * Get all session attributes\n * These attributes are automatically included with every telemetry event\n *\n * Core attributes matching Flutter SDK:\n * - react_native_version (RN framework in the host app)\n * - device_os, device_os_version, device_os_detail\n * - device_manufacturer, device_model, device_model_name\n * - device_brand, device_is_physical, device_id\n *\n * Additional monitoring attributes:\n * - device_type (mobile/tablet)\n * - device_memory_total, device_memory_used\n * - device_battery_level, device_is_charging, device_low_power_mode\n * - device_carrier\n */\nexport async function getSessionAttributes(): Promise<SessionAttributes> {\n return (await collectMobileMeta()).sessionAttributes;\n}\n\nasync function collectMobileMeta(): Promise<PreloadedMobileMeta> {\n try {\n const [deviceOsDetail, deviceOsBuildId, installationId] = await Promise.all([\n getDeviceOsDetail(),\n getDeviceOsBuildId(),\n getInstallationId(),\n ]);\n\n // Get synchronous device info\n const systemName = DeviceInfo.getSystemName();\n const systemVersion = DeviceInfo.getSystemVersion();\n const manufacturer = DeviceInfo.getManufacturerSync();\n const model = DeviceInfo.getModel();\n const modelIdentifier = getStructuredDeviceModelIdentifier(model);\n const deviceName = DeviceInfo.getDeviceNameSync();\n const brand = DeviceInfo.getBrand();\n const isEmulator = DeviceInfo.isEmulatorSync();\n const isTablet = DeviceInfo.isTablet();\n const deviceType = getMobileDeviceType(isTablet);\n\n // Memory info\n const totalMemory = DeviceInfo.getTotalMemorySync();\n const usedMemory = DeviceInfo.getUsedMemorySync();\n const reactNativeVersion = getReactNativeVersion();\n\n // Try to get async device info (battery, carrier)\n let batteryLevel: string | undefined;\n let isCharging: string | undefined;\n let lowPowerMode: string | undefined;\n let carrier: string | undefined;\n\n try {\n const battery = await DeviceInfo.getBatteryLevel();\n if (battery >= 0) {\n batteryLevel = String(Math.round(battery * 100));\n }\n } catch (_error) {\n // Battery info not available\n }\n\n try {\n isCharging = String(await DeviceInfo.isBatteryCharging());\n } catch (_error) {\n // Charging status not available\n }\n\n try {\n if ('isPowerSaveMode' in DeviceInfo) {\n lowPowerMode = String(\n await (DeviceInfo as typeof DeviceInfo & { isPowerSaveMode: () => Promise<boolean> }).isPowerSaveMode()\n );\n }\n } catch (_error) {\n // Low power mode not available\n }\n\n try {\n const carrierName = await DeviceInfo.getCarrier();\n if (carrierName && carrierName !== 'unknown') {\n carrier = carrierName;\n }\n } catch (_error) {\n // Carrier not available\n }\n\n const attributes: SessionAttributes = {\n react_native_version: reactNativeVersion,\n device_os: systemName,\n device_os_version: systemVersion,\n device_os_detail: deviceOsDetail,\n device_manufacturer: manufacturer.toLowerCase(),\n device_model: model,\n device_model_name: deviceName,\n device_brand: brand,\n device_is_physical: String(!isEmulator),\n ...(installationId ? { device_id: installationId } : {}),\n ...(deviceType ? { device_type: deviceType } : {}),\n device_memory_total: String(totalMemory),\n device_memory_used: String(usedMemory),\n device_battery_level: batteryLevel,\n device_is_charging: isCharging,\n device_low_power_mode: lowPowerMode,\n device_carrier: carrier,\n };\n const appMeta = installationId ? { installationId } : {};\n const structuredDeviceBrand = getStructuredDeviceBrand(model, brand);\n const structuredDeviceManufacturer = getStructuredDeviceManufacturer(manufacturer);\n const osMeta = {\n ...(deviceOsBuildId ? { build_id: deviceOsBuildId } : {}),\n detail: deviceOsDetail,\n name: systemName,\n version: systemVersion,\n };\n\n return {\n sessionAttributes: attributes,\n meta: {\n app: appMeta,\n device: {\n brand: structuredDeviceBrand,\n is_physical: !isEmulator,\n manufacturer: structuredDeviceManufacturer,\n ...(modelIdentifier ? { model_identifier: modelIdentifier } : {}),\n model_name: model,\n ...(deviceType ? { type: deviceType } : {}),\n },\n os: osMeta,\n },\n };\n } catch (_error) {\n const installationId = await getInstallationId();\n\n return {\n sessionAttributes: minimalSessionDeviceAttributes(),\n meta: {\n app: installationId ? { installationId } : {},\n },\n };\n }\n}\n\n/**\n * Get structured mobile meta plus flat session attributes for async `initializeFaro`.\n */\nexport async function loadMobileMetaForInit(): Promise<PreloadedMobileMeta> {\n return collectMobileMeta();\n}\n\n/**\n * Await full async session device attributes (battery, carrier, etc.), then fall back to\n * {@link minimalSessionDeviceAttributes} if anything throws. Used by async `initializeFaro`.\n */\nexport async function loadSessionDeviceAttributesForInit(): Promise<SessionAttributes> {\n try {\n return (await loadMobileMetaForInit()).sessionAttributes;\n } catch {\n return minimalSessionDeviceAttributes();\n }\n}\n"]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import DeviceInfo from 'react-native-device-info';
|
|
11
|
+
import { globalObject } from '@grafana/faro-core';
|
|
12
|
+
const BUNDLE_ID_SEPARATOR = '@';
|
|
13
|
+
/** Metro / webpack preamble bundle id for JS source maps (`__faroBundleId_<appName>`). */
|
|
14
|
+
export function getMetroInjectedBundleId(appName) {
|
|
15
|
+
if (!appName) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
const key = `__faroBundleId_${appName}`;
|
|
19
|
+
const fromGlobal = globalObject[key];
|
|
20
|
+
if (typeof fromGlobal === 'string' && fromGlobal !== '') {
|
|
21
|
+
return fromGlobal;
|
|
22
|
+
}
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Encodes the Android/iOS build identity used as `meta.app.bundleId` for
|
|
27
|
+
* server-side symbol retrace. Must match the symbols upload bundle id
|
|
28
|
+
* (`{applicationId}@{versionCode}@{versionName}`).
|
|
29
|
+
*/
|
|
30
|
+
export function formatSymbolsBundleId(applicationId, versionCode, versionName) {
|
|
31
|
+
return `${applicationId}${BUNDLE_ID_SEPARATOR}${versionCode}${BUNDLE_ID_SEPARATOR}${versionName}`;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Reads the installed build's identity from `react-native-device-info` and
|
|
35
|
+
* returns the encoded bundle id when all parts are available.
|
|
36
|
+
*
|
|
37
|
+
* Values must match what the symbol uploader (Gradle plugin / faro-cli) sends
|
|
38
|
+
* for the same build so the collector can locate the mapping for retrace.
|
|
39
|
+
*/
|
|
40
|
+
export function loadAppSymbolsBundleIdForInit() {
|
|
41
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
try {
|
|
43
|
+
const applicationId = DeviceInfo.getBundleId();
|
|
44
|
+
const versionName = DeviceInfo.getVersion();
|
|
45
|
+
const versionCodeRaw = DeviceInfo.getBuildNumber();
|
|
46
|
+
if (!applicationId || versionCodeRaw === '' || versionCodeRaw == null || !versionName) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
return formatSymbolsBundleId(applicationId, String(versionCodeRaw), versionName);
|
|
50
|
+
}
|
|
51
|
+
catch (_a) {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=appBuildIdentity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"appBuildIdentity.js","sourceRoot":"","sources":["../../../src/metas/appBuildIdentity.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,UAAU,MAAM,0BAA0B,CAAC;AAElD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEhC,0FAA0F;AAC1F,MAAM,UAAU,wBAAwB,CAAC,OAA2B;IAClE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,GAAG,GAAG,kBAAkB,OAAO,EAAE,CAAC;IACxC,MAAM,UAAU,GAAI,YAAwC,CAAC,GAAG,CAAC,CAAC;IAClE,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,EAAE,EAAE,CAAC;QACxD,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,aAAqB,EAAE,WAAmB,EAAE,WAAmB;IACnG,OAAO,GAAG,aAAa,GAAG,mBAAmB,GAAG,WAAW,GAAG,mBAAmB,GAAG,WAAW,EAAE,CAAC;AACpG,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAgB,6BAA6B;;QACjD,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;YAC/C,MAAM,WAAW,GAAG,UAAU,CAAC,UAAU,EAAE,CAAC;YAC5C,MAAM,cAAc,GAAG,UAAU,CAAC,cAAc,EAAE,CAAC;YAEnD,IAAI,CAAC,aAAa,IAAI,cAAc,KAAK,EAAE,IAAI,cAAc,IAAI,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACtF,OAAO,SAAS,CAAC;YACnB,CAAC;YAED,OAAO,qBAAqB,CAAC,aAAa,EAAE,MAAM,CAAC,cAAc,CAAC,EAAE,WAAW,CAAC,CAAC;QACnF,CAAC;QAAC,WAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;CAAA","sourcesContent":["import DeviceInfo from 'react-native-device-info';\n\nimport { globalObject } from '@grafana/faro-core';\n\nconst BUNDLE_ID_SEPARATOR = '@';\n\n/** Metro / webpack preamble bundle id for JS source maps (`__faroBundleId_<appName>`). */\nexport function getMetroInjectedBundleId(appName: string | undefined): string | undefined {\n if (!appName) {\n return undefined;\n }\n const key = `__faroBundleId_${appName}`;\n const fromGlobal = (globalObject as Record<string, unknown>)[key];\n if (typeof fromGlobal === 'string' && fromGlobal !== '') {\n return fromGlobal;\n }\n return undefined;\n}\n\n/**\n * Encodes the Android/iOS build identity used as `meta.app.bundleId` for\n * server-side symbol retrace. Must match the symbols upload bundle id\n * (`{applicationId}@{versionCode}@{versionName}`).\n */\nexport function formatSymbolsBundleId(applicationId: string, versionCode: string, versionName: string): string {\n return `${applicationId}${BUNDLE_ID_SEPARATOR}${versionCode}${BUNDLE_ID_SEPARATOR}${versionName}`;\n}\n\n/**\n * Reads the installed build's identity from `react-native-device-info` and\n * returns the encoded bundle id when all parts are available.\n *\n * Values must match what the symbol uploader (Gradle plugin / faro-cli) sends\n * for the same build so the collector can locate the mapping for retrace.\n */\nexport async function loadAppSymbolsBundleIdForInit(): Promise<string | undefined> {\n try {\n const applicationId = DeviceInfo.getBundleId();\n const versionName = DeviceInfo.getVersion();\n const versionCodeRaw = DeviceInfo.getBuildNumber();\n\n if (!applicationId || versionCodeRaw === '' || versionCodeRaw == null || !versionName) {\n return undefined;\n }\n\n return formatSymbolsBundleId(applicationId, String(versionCodeRaw), versionName);\n } catch {\n return undefined;\n }\n}\n"]}
|
|
@@ -6,10 +6,15 @@ export function mockDeviceInfo() {
|
|
|
6
6
|
default: {
|
|
7
7
|
getBrand: jest.fn(() => 'Apple'),
|
|
8
8
|
getDeviceId: jest.fn(() => 'iPhone14,2'),
|
|
9
|
+
getDeviceNameSync: jest.fn(() => "Test's iPhone"),
|
|
10
|
+
getUniqueId: jest.fn(() => Promise.resolve('test-device-id')),
|
|
9
11
|
getModel: jest.fn(() => 'iPhone 13 Pro'),
|
|
12
|
+
getManufacturerSync: jest.fn(() => 'Apple'),
|
|
10
13
|
getSystemName: jest.fn(() => 'iOS'),
|
|
11
14
|
getSystemVersion: jest.fn(() => '16.0'),
|
|
12
15
|
getVersion: jest.fn(() => '1.0.0'),
|
|
16
|
+
getApiLevel: jest.fn(() => Promise.resolve(35)),
|
|
17
|
+
getBuildId: jest.fn(() => Promise.resolve('22B83')),
|
|
13
18
|
isTablet: jest.fn(() => false),
|
|
14
19
|
isEmulatorSync: jest.fn(() => false),
|
|
15
20
|
getTotalMemorySync: jest.fn(() => 6442450944), // 6GB in bytes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mockDeviceInfo.js","sourceRoot":"","sources":["../../../src/testUtils/mockDeviceInfo.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC,IAAI,CAAC,0BAA0B,EAAE,GAAG,EAAE,CAAC,CAAC;QAC3C,OAAO,EAAE;YACP,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC;YAChC,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC;YACxC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC;YACxC,aAAa,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC;YACnC,gBAAgB,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC;YACvC,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC;YAClC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC;YAC9B,cAAc,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC;YACpC,kBAAkB,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,EAAE,eAAe;YAC9D,iBAAiB,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,EAAE,eAAe;YAC7D,eAAe,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACrD,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YACtD,eAAe,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACtD,iBAAiB,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;SACzD;KACF,CAAC,CAAC,CAAC;AACN,CAAC","sourcesContent":["/**\n * Mock react-native-device-info for testing\n */\nexport function mockDeviceInfo(): void {\n jest.mock('react-native-device-info', () => ({\n default: {\n getBrand: jest.fn(() => 'Apple'),\n getDeviceId: jest.fn(() => 'iPhone14,2'),\n getModel: jest.fn(() => 'iPhone 13 Pro'),\n getSystemName: jest.fn(() => 'iOS'),\n getSystemVersion: jest.fn(() => '16.0'),\n getVersion: jest.fn(() => '1.0.0'),\n isTablet: jest.fn(() => false),\n isEmulatorSync: jest.fn(() => false),\n getTotalMemorySync: jest.fn(() => 6442450944), // 6GB in bytes\n getUsedMemorySync: jest.fn(() => 2147483648), // 2GB in bytes\n getBatteryLevel: jest.fn(() => Promise.resolve(0.75)),\n getCarrier: jest.fn(() => Promise.resolve('T-Mobile')),\n isPowerSaveMode: jest.fn(() => Promise.resolve(false)),\n isBatteryCharging: jest.fn(() => Promise.resolve(false)),\n },\n }));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"mockDeviceInfo.js","sourceRoot":"","sources":["../../../src/testUtils/mockDeviceInfo.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC,IAAI,CAAC,0BAA0B,EAAE,GAAG,EAAE,CAAC,CAAC;QAC3C,OAAO,EAAE;YACP,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC;YAChC,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC;YACxC,iBAAiB,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC;YACjD,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;YAC7D,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC;YACxC,mBAAmB,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC;YAC3C,aAAa,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC;YACnC,gBAAgB,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC;YACvC,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC;YAClC,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAC/C,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACnD,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC;YAC9B,cAAc,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC;YACpC,kBAAkB,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,EAAE,eAAe;YAC9D,iBAAiB,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,EAAE,eAAe;YAC7D,eAAe,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACrD,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YACtD,eAAe,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACtD,iBAAiB,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;SACzD;KACF,CAAC,CAAC,CAAC;AACN,CAAC","sourcesContent":["/**\n * Mock react-native-device-info for testing\n */\nexport function mockDeviceInfo(): void {\n jest.mock('react-native-device-info', () => ({\n default: {\n getBrand: jest.fn(() => 'Apple'),\n getDeviceId: jest.fn(() => 'iPhone14,2'),\n getDeviceNameSync: jest.fn(() => \"Test's iPhone\"),\n getUniqueId: jest.fn(() => Promise.resolve('test-device-id')),\n getModel: jest.fn(() => 'iPhone 13 Pro'),\n getManufacturerSync: jest.fn(() => 'Apple'),\n getSystemName: jest.fn(() => 'iOS'),\n getSystemVersion: jest.fn(() => '16.0'),\n getVersion: jest.fn(() => '1.0.0'),\n getApiLevel: jest.fn(() => Promise.resolve(35)),\n getBuildId: jest.fn(() => Promise.resolve('22B83')),\n isTablet: jest.fn(() => false),\n isEmulatorSync: jest.fn(() => false),\n getTotalMemorySync: jest.fn(() => 6442450944), // 6GB in bytes\n getUsedMemorySync: jest.fn(() => 2147483648), // 2GB in bytes\n getBatteryLevel: jest.fn(() => Promise.resolve(0.75)),\n getCarrier: jest.fn(() => Promise.resolve('T-Mobile')),\n isPowerSaveMode: jest.fn(() => Promise.resolve(false)),\n isBatteryCharging: jest.fn(() => Promise.resolve(false)),\n },\n }));\n}\n"]}
|
|
@@ -8,10 +8,17 @@ jest.mock('react-native-device-info', () => {
|
|
|
8
8
|
const mockDeviceInfo = {
|
|
9
9
|
getBrand: jest.fn(() => 'Apple'),
|
|
10
10
|
getDeviceId: jest.fn(() => 'iPhone14,2'),
|
|
11
|
+
getDeviceNameSync: jest.fn(() => "Test's iPhone"),
|
|
12
|
+
getUniqueId: jest.fn(() => Promise.resolve('test-device-id')),
|
|
11
13
|
getModel: jest.fn(() => 'iPhone 13 Pro'),
|
|
14
|
+
getManufacturerSync: jest.fn(() => 'Apple'),
|
|
12
15
|
getSystemName: jest.fn(() => 'iOS'),
|
|
13
16
|
getSystemVersion: jest.fn(() => '16.0'),
|
|
14
17
|
getVersion: jest.fn(() => '1.0.0'),
|
|
18
|
+
getBundleId: jest.fn(() => 'com.example.myapp'),
|
|
19
|
+
getBuildNumber: jest.fn(() => '42'),
|
|
20
|
+
getApiLevel: jest.fn(() => Promise.resolve(35)),
|
|
21
|
+
getBuildId: jest.fn(() => Promise.resolve('22B83')),
|
|
15
22
|
isTablet: jest.fn(() => false),
|
|
16
23
|
isEmulatorSync: jest.fn(() => false),
|
|
17
24
|
getTotalMemorySync: jest.fn(() => 6442450944), // 6GB in bytes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setupTests.js","sourceRoot":"","sources":["../../../src/testUtils/setupTests.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Jest setup file for React Native tests\n * Mocks third-party React Native dependencies\n */\n\n// Mock react-native-device-info\njest.mock('react-native-device-info', () => {\n const mockDeviceInfo = {\n getBrand: jest.fn(() => 'Apple'),\n getDeviceId: jest.fn(() => 'iPhone14,2'),\n getModel: jest.fn(() => 'iPhone 13 Pro'),\n getSystemName: jest.fn(() => 'iOS'),\n getSystemVersion: jest.fn(() => '16.0'),\n getVersion: jest.fn(() => '1.0.0'),\n isTablet: jest.fn(() => false),\n isEmulatorSync: jest.fn(() => false),\n getTotalMemorySync: jest.fn(() => 6442450944), // 6GB in bytes\n getUsedMemorySync: jest.fn(() => 2147483648), // 2GB in bytes\n getBatteryLevel: jest.fn(() => Promise.resolve(0.75)),\n getCarrier: jest.fn(() => Promise.resolve('T-Mobile')),\n isPowerSaveMode: jest.fn(() => Promise.resolve(false)),\n isBatteryCharging: jest.fn(() => Promise.resolve(false)),\n };\n return {\n __esModule: true,\n default: mockDeviceInfo,\n ...mockDeviceInfo,\n };\n});\n\n// Mock @react-native-async-storage/async-storage\n// Using a global storage object that can be accessed by tests\n(global as any).mockAsyncStorage = {};\n\nconst mockAsyncStorageImpl = {\n getItem: jest.fn((key: string) => {\n const storage = (global as any).mockAsyncStorage;\n return Promise.resolve(storage[key] ?? null);\n }),\n setItem: jest.fn((key: string, value: string) => {\n const storage = (global as any).mockAsyncStorage;\n storage[key] = value;\n return Promise.resolve();\n }),\n removeItem: jest.fn((key: string) => {\n const storage = (global as any).mockAsyncStorage;\n delete storage[key];\n return Promise.resolve();\n }),\n clear: jest.fn(() => {\n (global as any).mockAsyncStorage = {};\n return Promise.resolve();\n }),\n getAllKeys: jest.fn(() => {\n const storage = (global as any).mockAsyncStorage;\n return Promise.resolve(Object.keys(storage));\n }),\n multiGet: jest.fn((keys: string[]) => {\n const storage = (global as any).mockAsyncStorage;\n return Promise.resolve(keys.map((key) => [key, storage[key] ?? null]));\n }),\n multiSet: jest.fn((keyValuePairs: Array<[string, string]>) => {\n const storage = (global as any).mockAsyncStorage;\n keyValuePairs.forEach(([key, value]) => {\n storage[key] = value;\n });\n return Promise.resolve();\n }),\n multiRemove: jest.fn((keys: string[]) => {\n const storage = (global as any).mockAsyncStorage;\n keys.forEach((key) => delete storage[key]);\n return Promise.resolve();\n }),\n};\n\njest.mock('@react-native-async-storage/async-storage', () => ({\n __esModule: true,\n default: mockAsyncStorageImpl,\n}));\n\n// Ensure Platform.Version is properly mocked\n// The react-native preset mocks Platform, but we need to ensure Version is accessible\njest.mock(\n 'react-native/Libraries/Utilities/Platform',\n () => ({\n OS: 'ios',\n Version: '16.0',\n select: jest.fn((obj) => obj.ios || obj.default),\n }),\n { virtual: true }\n);\n\n// Mock fetch API globals for HTTP instrumentation tests\nif (typeof global.Response === 'undefined') {\n global.Response = class Response {\n ok: boolean;\n status: number;\n statusText: string;\n body: any;\n\n constructor(body?: BodyInit | null, init?: ResponseInit) {\n this.body = body;\n this.status = init?.status ?? 200;\n this.statusText = init?.statusText ?? 'OK';\n this.ok = this.status >= 200 && this.status < 300;\n }\n } as any;\n}\n\nif (typeof global.Request === 'undefined') {\n global.Request = class Request {\n url: string;\n method: string;\n\n constructor(input: RequestInfo | URL, init?: RequestInit) {\n if (typeof input === 'string') {\n this.url = input;\n this.method = init?.method ?? 'GET';\n } else if (input instanceof URL) {\n this.url = input.href;\n this.method = init?.method ?? 'GET';\n } else {\n // input is a Request object\n const req = input as Request;\n this.url = req.url;\n this.method = init?.method ?? req.method ?? 'GET';\n }\n }\n } as any;\n}\n\nif (typeof global.URL === 'undefined') {\n global.URL = class URL {\n href: string;\n\n constructor(url: string) {\n this.href = url;\n }\n } as any;\n}\n\n/**\n * Minimal XMLHttpRequest for Jest (Node has no XHR). Patches in XHRInstrumentation\n * tests attach to this prototype; send() completes asynchronously like a real request.\n */\nif (typeof global.XMLHttpRequest === 'undefined') {\n class MockXMLHttpRequest {\n static readonly DONE = 4;\n\n readyState = 0;\n status = 200;\n statusText = 'OK';\n onreadystatechange: ((this: XMLHttpRequest, ev: Event) => unknown) | null = null;\n\n private readonly listeners = new Map<string, Set<EventListener>>();\n\n open(_method: string, _url: string | URL): void {\n // Real open is replaced by instrumentation; baseline is a no-op.\n }\n\n send(_body?: Document | XMLHttpRequestBodyInit | null): void {\n // Synchronous completion matches test doubles and ensures Faro pushEvent runs in the same turn as send().\n this.readyState = MockXMLHttpRequest.DONE;\n const ev = { type: 'readystatechange' } as Event;\n if (this.onreadystatechange) {\n this.onreadystatechange.call(this as unknown as XMLHttpRequest, ev);\n }\n const load = this.listeners.get('load');\n if (load) {\n load.forEach((fn) => {\n fn.call(this as unknown as XMLHttpRequest, ev);\n });\n }\n }\n\n setRequestHeader(_name: string, _value: string): void {}\n\n getResponseHeader(_name: string): string | null {\n return null;\n }\n\n addEventListener(type: string, listener: EventListener): void {\n let set = this.listeners.get(type);\n if (!set) {\n set = new Set();\n this.listeners.set(type, set);\n }\n set.add(listener);\n }\n\n removeEventListener(type: string, listener: EventListener): void {\n this.listeners.get(type)?.delete(listener);\n }\n\n abort(): void {}\n }\n\n global.XMLHttpRequest = MockXMLHttpRequest as unknown as typeof XMLHttpRequest;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"setupTests.js","sourceRoot":"","sources":["../../../src/testUtils/setupTests.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Jest setup file for React Native tests\n * Mocks third-party React Native dependencies\n */\n\n// Mock react-native-device-info\njest.mock('react-native-device-info', () => {\n const mockDeviceInfo = {\n getBrand: jest.fn(() => 'Apple'),\n getDeviceId: jest.fn(() => 'iPhone14,2'),\n getDeviceNameSync: jest.fn(() => \"Test's iPhone\"),\n getUniqueId: jest.fn(() => Promise.resolve('test-device-id')),\n getModel: jest.fn(() => 'iPhone 13 Pro'),\n getManufacturerSync: jest.fn(() => 'Apple'),\n getSystemName: jest.fn(() => 'iOS'),\n getSystemVersion: jest.fn(() => '16.0'),\n getVersion: jest.fn(() => '1.0.0'),\n getBundleId: jest.fn(() => 'com.example.myapp'),\n getBuildNumber: jest.fn(() => '42'),\n getApiLevel: jest.fn(() => Promise.resolve(35)),\n getBuildId: jest.fn(() => Promise.resolve('22B83')),\n isTablet: jest.fn(() => false),\n isEmulatorSync: jest.fn(() => false),\n getTotalMemorySync: jest.fn(() => 6442450944), // 6GB in bytes\n getUsedMemorySync: jest.fn(() => 2147483648), // 2GB in bytes\n getBatteryLevel: jest.fn(() => Promise.resolve(0.75)),\n getCarrier: jest.fn(() => Promise.resolve('T-Mobile')),\n isPowerSaveMode: jest.fn(() => Promise.resolve(false)),\n isBatteryCharging: jest.fn(() => Promise.resolve(false)),\n };\n return {\n __esModule: true,\n default: mockDeviceInfo,\n ...mockDeviceInfo,\n };\n});\n\n// Mock @react-native-async-storage/async-storage\n// Using a global storage object that can be accessed by tests\n(global as any).mockAsyncStorage = {};\n\nconst mockAsyncStorageImpl = {\n getItem: jest.fn((key: string) => {\n const storage = (global as any).mockAsyncStorage;\n return Promise.resolve(storage[key] ?? null);\n }),\n setItem: jest.fn((key: string, value: string) => {\n const storage = (global as any).mockAsyncStorage;\n storage[key] = value;\n return Promise.resolve();\n }),\n removeItem: jest.fn((key: string) => {\n const storage = (global as any).mockAsyncStorage;\n delete storage[key];\n return Promise.resolve();\n }),\n clear: jest.fn(() => {\n (global as any).mockAsyncStorage = {};\n return Promise.resolve();\n }),\n getAllKeys: jest.fn(() => {\n const storage = (global as any).mockAsyncStorage;\n return Promise.resolve(Object.keys(storage));\n }),\n multiGet: jest.fn((keys: string[]) => {\n const storage = (global as any).mockAsyncStorage;\n return Promise.resolve(keys.map((key) => [key, storage[key] ?? null]));\n }),\n multiSet: jest.fn((keyValuePairs: Array<[string, string]>) => {\n const storage = (global as any).mockAsyncStorage;\n keyValuePairs.forEach(([key, value]) => {\n storage[key] = value;\n });\n return Promise.resolve();\n }),\n multiRemove: jest.fn((keys: string[]) => {\n const storage = (global as any).mockAsyncStorage;\n keys.forEach((key) => delete storage[key]);\n return Promise.resolve();\n }),\n};\n\njest.mock('@react-native-async-storage/async-storage', () => ({\n __esModule: true,\n default: mockAsyncStorageImpl,\n}));\n\n// Ensure Platform.Version is properly mocked\n// The react-native preset mocks Platform, but we need to ensure Version is accessible\njest.mock(\n 'react-native/Libraries/Utilities/Platform',\n () => ({\n OS: 'ios',\n Version: '16.0',\n select: jest.fn((obj) => obj.ios || obj.default),\n }),\n { virtual: true }\n);\n\n// Mock fetch API globals for HTTP instrumentation tests\nif (typeof global.Response === 'undefined') {\n global.Response = class Response {\n ok: boolean;\n status: number;\n statusText: string;\n body: any;\n\n constructor(body?: BodyInit | null, init?: ResponseInit) {\n this.body = body;\n this.status = init?.status ?? 200;\n this.statusText = init?.statusText ?? 'OK';\n this.ok = this.status >= 200 && this.status < 300;\n }\n } as any;\n}\n\nif (typeof global.Request === 'undefined') {\n global.Request = class Request {\n url: string;\n method: string;\n\n constructor(input: RequestInfo | URL, init?: RequestInit) {\n if (typeof input === 'string') {\n this.url = input;\n this.method = init?.method ?? 'GET';\n } else if (input instanceof URL) {\n this.url = input.href;\n this.method = init?.method ?? 'GET';\n } else {\n // input is a Request object\n const req = input as Request;\n this.url = req.url;\n this.method = init?.method ?? req.method ?? 'GET';\n }\n }\n } as any;\n}\n\nif (typeof global.URL === 'undefined') {\n global.URL = class URL {\n href: string;\n\n constructor(url: string) {\n this.href = url;\n }\n } as any;\n}\n\n/**\n * Minimal XMLHttpRequest for Jest (Node has no XHR). Patches in XHRInstrumentation\n * tests attach to this prototype; send() completes asynchronously like a real request.\n */\nif (typeof global.XMLHttpRequest === 'undefined') {\n class MockXMLHttpRequest {\n static readonly DONE = 4;\n\n readyState = 0;\n status = 200;\n statusText = 'OK';\n onreadystatechange: ((this: XMLHttpRequest, ev: Event) => unknown) | null = null;\n\n private readonly listeners = new Map<string, Set<EventListener>>();\n\n open(_method: string, _url: string | URL): void {\n // Real open is replaced by instrumentation; baseline is a no-op.\n }\n\n send(_body?: Document | XMLHttpRequestBodyInit | null): void {\n // Synchronous completion matches test doubles and ensures Faro pushEvent runs in the same turn as send().\n this.readyState = MockXMLHttpRequest.DONE;\n const ev = { type: 'readystatechange' } as Event;\n if (this.onreadystatechange) {\n this.onreadystatechange.call(this as unknown as XMLHttpRequest, ev);\n }\n const load = this.listeners.get('load');\n if (load) {\n load.forEach((fn) => {\n fn.call(this as unknown as XMLHttpRequest, ev);\n });\n }\n }\n\n setRequestHeader(_name: string, _value: string): void {}\n\n getResponseHeader(_name: string): string | null {\n return null;\n }\n\n addEventListener(type: string, listener: EventListener): void {\n let set = this.listeners.get(type);\n if (!set) {\n set = new Set();\n this.listeners.set(type, set);\n }\n set.add(listener);\n }\n\n removeEventListener(type: string, listener: EventListener): void {\n this.listeners.get(type)?.delete(listener);\n }\n\n abort(): void {}\n }\n\n global.XMLHttpRequest = MockXMLHttpRequest as unknown as typeof XMLHttpRequest;\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PreloadedMobileMeta } from '../instrumentations/session/sessionAttributes';
|
|
2
2
|
import type { ReactNativeConfig, ReactNativeFullConfig } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Creates a full Faro config from React Native flag-based config.
|
|
@@ -6,6 +6,7 @@ import type { ReactNativeConfig, ReactNativeFullConfig } from './types';
|
|
|
6
6
|
* Based on flags, builds instrumentations and transports automatically.
|
|
7
7
|
* Client just enables what they need; makeRNConfig does the rest.
|
|
8
8
|
*
|
|
9
|
-
* @param
|
|
9
|
+
* @param preloadedMobileMeta Device/session fields and structured mobile meta (passed from async `initializeFaro`).
|
|
10
|
+
* @param appSymbolsBundleId Encoded `meta.app.bundleId` for server-side symbol retrace.
|
|
10
11
|
*/
|
|
11
|
-
export declare function makeRNConfig(config: ReactNativeConfig,
|
|
12
|
+
export declare function makeRNConfig(config: ReactNativeConfig, preloadedMobileMeta?: PreloadedMobileMeta, appSymbolsBundleId?: string): ReactNativeFullConfig;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Config } from '@grafana/faro-core';
|
|
2
2
|
import type { ANRInstrumentationOptions } from '../instrumentations/anr';
|
|
3
3
|
import type { FrameMonitoringOptions } from '../instrumentations/frameMonitoring';
|
|
4
|
-
import type { SessionAttributes } from '../instrumentations/session/sessionAttributes';
|
|
4
|
+
import type { PreloadedMobileMeta, SessionAttributes } from '../instrumentations/session/sessionAttributes';
|
|
5
5
|
import type { Sampling } from './sampling';
|
|
6
6
|
/**
|
|
7
7
|
* React Native session tracking config.
|
|
@@ -79,6 +79,7 @@ export type ReactNativeConfig = Partial<Omit<Config, 'sessionTracking' | 'consol
|
|
|
79
79
|
* Extends faro-core `Config` with RN-specific fields that instrumentations need at init time.
|
|
80
80
|
*/
|
|
81
81
|
export type ReactNativeFullConfig = Config & {
|
|
82
|
+
preloadedMobileMeta?: PreloadedMobileMeta['meta'];
|
|
82
83
|
preloadedSessionDeviceAttributes?: SessionAttributes;
|
|
83
84
|
};
|
|
84
85
|
export {};
|
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
* NPM package identity for this build. Generated by scripts/sync-faro-rn-package-meta.mjs - do not edit.
|
|
3
3
|
*/
|
|
4
4
|
export declare const FARO_REACT_NATIVE_NPM_NAME: "@grafana/faro-react-native";
|
|
5
|
-
export declare const FARO_REACT_NATIVE_NPM_VERSION: "1.
|
|
5
|
+
export declare const FARO_REACT_NATIVE_NPM_VERSION: "1.3.1";
|
package/dist/types/index.d.ts
CHANGED
|
@@ -7,8 +7,8 @@ export { ErrorMechanism, ErrorsInstrumentation } from './instrumentations/errors
|
|
|
7
7
|
export type { ErrorMechanismType, ErrorsInstrumentationOptions } from './instrumentations/errors';
|
|
8
8
|
export { ConsoleInstrumentation } from './instrumentations/console';
|
|
9
9
|
export { SessionInstrumentation } from './instrumentations/session';
|
|
10
|
-
export { getSessionAttributes, loadSessionDeviceAttributesForInit, minimalSessionDeviceAttributes, } from './instrumentations/session/sessionAttributes';
|
|
11
|
-
export type { SessionAttributes } from './instrumentations/session/sessionAttributes';
|
|
10
|
+
export { getSessionAttributes, loadMobileMetaForInit, loadSessionDeviceAttributesForInit, minimalSessionDeviceAttributes, } from './instrumentations/session/sessionAttributes';
|
|
11
|
+
export type { PreloadedMobileMeta, SessionAttributes } from './instrumentations/session/sessionAttributes';
|
|
12
12
|
export { ViewInstrumentation } from './instrumentations/view';
|
|
13
13
|
export { AppStateInstrumentation } from './instrumentations/appState';
|
|
14
14
|
export { UserActionInstrumentation } from './instrumentations/userActions';
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { type Faro } from '@grafana/faro-core';
|
|
2
2
|
import type { ReactNativeConfig } from './config/types';
|
|
3
3
|
/**
|
|
4
|
-
* Awaits async device/session attribute collection
|
|
5
|
-
*
|
|
4
|
+
* Awaits async device/session attribute collection and the build identity used
|
|
5
|
+
* for server-side symbol retrace, then initializes Faro with core
|
|
6
|
+
* `initializeFaro`. On failure during collection, uses
|
|
7
|
+
* `minimalSessionDeviceAttributes` / an empty build identity before init.
|
|
6
8
|
*/
|
|
7
9
|
export declare function initializeFaro(config: ReactNativeConfig): Promise<Faro>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns true when an ANR stack was sampled on the crash-killer path instead of
|
|
3
|
+
* the blocked main thread (common when ANRTracker fires during process teardown).
|
|
4
|
+
*
|
|
5
|
+
* Uses only Android framework and Faro SDK frame names — no app-specific identifiers.
|
|
6
|
+
*/
|
|
7
|
+
export declare function isInvalidAnrCaptureStack(stack: string | undefined): boolean;
|