@grafana/faro-react-native 1.3.1 → 1.4.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/README.md +176 -30
- package/android/build.gradle +17 -12
- package/android/src/main/java/com/grafana/faro/reactnative/FaroCrashIds.kt +44 -0
- package/android/src/main/java/com/grafana/faro/reactnative/FaroCrashReporter.kt +134 -38
- package/android/src/main/java/com/grafana/faro/reactnative/FaroCrashSessionStore.kt +433 -0
- package/android/src/main/java/com/grafana/faro/reactnative/FaroCrashTraceCache.kt +11 -2
- package/android/src/main/java/com/grafana/faro/reactnative/FaroReactNativeModule.kt +128 -17
- package/android/src/main/java/com/grafana/faro/reactnative/FaroSessionProcess.kt +88 -0
- package/android/src/main/java/com/grafana/faro/reactnative/FrameMonitor.kt +34 -42
- package/android/src/test/java/com/grafana/faro/reactnative/FaroCrashReporterBelowApi30Test.kt +21 -0
- package/android/src/test/java/com/grafana/faro/reactnative/FaroCrashReporterTest.kt +59 -0
- package/android/src/test/java/com/grafana/faro/reactnative/FaroCrashSessionStoreTest.kt +268 -0
- package/android/src/test/java/com/grafana/faro/reactnative/FaroCrashTraceCacheTest.kt +52 -0
- package/android/src/test/java/com/grafana/faro/reactnative/FaroSessionProcessTest.kt +127 -0
- package/dist/cjs/config/getRNInstrumentations.js +6 -8
- package/dist/cjs/config/getRNInstrumentations.js.map +1 -1
- package/dist/cjs/config/makeRNConfig.js +5 -5
- package/dist/cjs/config/makeRNConfig.js.map +1 -1
- package/dist/cjs/config/sampling.js.map +1 -1
- package/dist/cjs/config/types.js.map +1 -1
- package/dist/cjs/dataCollection/DataCollectionPolicy.js +1 -2
- package/dist/cjs/dataCollection/DataCollectionPolicy.js.map +1 -1
- package/dist/cjs/generated/faroRNPackageMeta.js +1 -1
- package/dist/cjs/generated/faroRNPackageMeta.js.map +1 -1
- package/dist/cjs/index.js +8 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/instrumentations/anr/instrumentation.js +10 -1
- package/dist/cjs/instrumentations/anr/instrumentation.js.map +1 -1
- package/dist/cjs/instrumentations/appState/index.js +8 -2
- package/dist/cjs/instrumentations/appState/index.js.map +1 -1
- package/dist/cjs/instrumentations/crashReporting/BaseCrashReportingInstrumentation.js +19 -6
- package/dist/cjs/instrumentations/crashReporting/BaseCrashReportingInstrumentation.js.map +1 -1
- package/dist/cjs/instrumentations/crashReporting/RecoveredCrashReportingInstrumentation.js +331 -0
- package/dist/cjs/instrumentations/crashReporting/RecoveredCrashReportingInstrumentation.js.map +1 -0
- package/dist/cjs/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.js +2 -2
- package/dist/cjs/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.js.map +1 -1
- package/dist/cjs/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.js +2 -2
- package/dist/cjs/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.js.map +1 -1
- package/dist/cjs/instrumentations/crashReporting/types.js.map +1 -1
- package/dist/cjs/instrumentations/errors/index.js +8 -3
- package/dist/cjs/instrumentations/errors/index.js.map +1 -1
- package/dist/cjs/instrumentations/frameMonitoring/instrumentation.js +20 -31
- package/dist/cjs/instrumentations/frameMonitoring/instrumentation.js.map +1 -1
- package/dist/cjs/instrumentations/frameMonitoring/types.js.map +1 -1
- package/dist/cjs/instrumentations/performance/index.js +2 -6
- package/dist/cjs/instrumentations/performance/index.js.map +1 -1
- package/dist/cjs/instrumentations/session/FaroSessionActivityBoundary.js +48 -0
- package/dist/cjs/instrumentations/session/FaroSessionActivityBoundary.js.map +1 -0
- package/dist/cjs/instrumentations/session/directSessionActivity.js +37 -0
- package/dist/cjs/instrumentations/session/directSessionActivity.js.map +1 -0
- package/dist/cjs/instrumentations/session/index.js +214 -45
- package/dist/cjs/instrumentations/session/index.js.map +1 -1
- package/dist/cjs/instrumentations/session/sessionActivity.js +43 -0
- package/dist/cjs/instrumentations/session/sessionActivity.js.map +1 -0
- package/dist/cjs/instrumentations/session/sessionAttributes.js +8 -8
- package/dist/cjs/instrumentations/session/sessionAttributes.js.map +1 -1
- package/dist/cjs/instrumentations/session/sessionManager/MmkvPersistentSessionsManager.js +199 -24
- package/dist/cjs/instrumentations/session/sessionManager/MmkvPersistentSessionsManager.js.map +1 -1
- package/dist/cjs/instrumentations/session/sessionManager/VolatileSessionManager.js +31 -13
- package/dist/cjs/instrumentations/session/sessionManager/VolatileSessionManager.js.map +1 -1
- package/dist/cjs/instrumentations/session/sessionManager/persistentSessionRecord.js +72 -0
- package/dist/cjs/instrumentations/session/sessionManager/persistentSessionRecord.js.map +1 -0
- package/dist/cjs/instrumentations/session/sessionManager/sessionConstants.js +1 -1
- package/dist/cjs/instrumentations/session/sessionManager/sessionConstants.js.map +1 -1
- package/dist/cjs/instrumentations/session/sessionManager/sessionManagerUtils.js +124 -96
- package/dist/cjs/instrumentations/session/sessionManager/sessionManagerUtils.js.map +1 -1
- package/dist/cjs/instrumentations/session/sessionManager/types.js.map +1 -1
- package/dist/cjs/instrumentations/session/sessionProcess.js +96 -0
- package/dist/cjs/instrumentations/session/sessionProcess.js.map +1 -0
- package/dist/cjs/instrumentations/startup/index.js +2 -6
- package/dist/cjs/instrumentations/startup/index.js.map +1 -1
- package/dist/cjs/navigation/utils.js +3 -1
- package/dist/cjs/navigation/utils.js.map +1 -1
- package/dist/cjs/transports/fetch/index.js.map +1 -1
- package/dist/cjs/transports/fetch/transport.js +56 -25
- package/dist/cjs/transports/fetch/transport.js.map +1 -1
- package/dist/cjs/transports/fetch/types.js.map +1 -1
- package/dist/cjs/transports/offline/ConnectivityService.js +1 -1
- package/dist/cjs/transports/offline/ConnectivityService.js.map +1 -1
- package/dist/cjs/transports/offline/OfflineCache.js +2 -2
- package/dist/cjs/transports/offline/OfflineCache.js.map +1 -1
- package/dist/cjs/transports/offline/transport.js +3 -4
- package/dist/cjs/transports/offline/transport.js.map +1 -1
- package/dist/cjs/userPersistence/UserPersistence.js +1 -2
- package/dist/cjs/userPersistence/UserPersistence.js.map +1 -1
- package/dist/esm/config/getRNInstrumentations.js +6 -8
- package/dist/esm/config/getRNInstrumentations.js.map +1 -1
- package/dist/esm/config/makeRNConfig.js +5 -5
- package/dist/esm/config/makeRNConfig.js.map +1 -1
- package/dist/esm/config/sampling.js.map +1 -1
- package/dist/esm/config/types.js.map +1 -1
- package/dist/esm/dataCollection/DataCollectionPolicy.js +1 -2
- package/dist/esm/dataCollection/DataCollectionPolicy.js.map +1 -1
- package/dist/esm/generated/faroRNPackageMeta.js +1 -1
- package/dist/esm/generated/faroRNPackageMeta.js.map +1 -1
- package/dist/esm/index.js +4 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/instrumentations/anr/instrumentation.js +6 -1
- package/dist/esm/instrumentations/anr/instrumentation.js.map +1 -1
- package/dist/esm/instrumentations/appState/index.js +8 -2
- package/dist/esm/instrumentations/appState/index.js.map +1 -1
- package/dist/esm/instrumentations/crashReporting/BaseCrashReportingInstrumentation.js +15 -4
- package/dist/esm/instrumentations/crashReporting/BaseCrashReportingInstrumentation.js.map +1 -1
- package/dist/esm/instrumentations/crashReporting/RecoveredCrashReportingInstrumentation.js +230 -0
- package/dist/esm/instrumentations/crashReporting/RecoveredCrashReportingInstrumentation.js.map +1 -0
- package/dist/esm/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.js +2 -2
- package/dist/esm/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.js.map +1 -1
- package/dist/esm/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.js +2 -2
- package/dist/esm/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.js.map +1 -1
- package/dist/esm/instrumentations/crashReporting/types.js.map +1 -1
- package/dist/esm/instrumentations/errors/index.js +8 -3
- package/dist/esm/instrumentations/errors/index.js.map +1 -1
- package/dist/esm/instrumentations/frameMonitoring/instrumentation.js +17 -32
- package/dist/esm/instrumentations/frameMonitoring/instrumentation.js.map +1 -1
- package/dist/esm/instrumentations/frameMonitoring/types.js.map +1 -1
- package/dist/esm/instrumentations/performance/index.js +2 -6
- package/dist/esm/instrumentations/performance/index.js.map +1 -1
- package/dist/esm/instrumentations/session/FaroSessionActivityBoundary.js +34 -0
- package/dist/esm/instrumentations/session/FaroSessionActivityBoundary.js.map +1 -0
- package/dist/esm/instrumentations/session/directSessionActivity.js +32 -0
- package/dist/esm/instrumentations/session/directSessionActivity.js.map +1 -0
- package/dist/esm/instrumentations/session/index.js +207 -46
- package/dist/esm/instrumentations/session/index.js.map +1 -1
- package/dist/esm/instrumentations/session/sessionActivity.js +38 -0
- package/dist/esm/instrumentations/session/sessionActivity.js.map +1 -0
- package/dist/esm/instrumentations/session/sessionAttributes.js +7 -7
- package/dist/esm/instrumentations/session/sessionAttributes.js.map +1 -1
- package/dist/esm/instrumentations/session/sessionManager/MmkvPersistentSessionsManager.js +190 -27
- package/dist/esm/instrumentations/session/sessionManager/MmkvPersistentSessionsManager.js.map +1 -1
- package/dist/esm/instrumentations/session/sessionManager/VolatileSessionManager.js +31 -14
- package/dist/esm/instrumentations/session/sessionManager/VolatileSessionManager.js.map +1 -1
- package/dist/esm/instrumentations/session/sessionManager/persistentSessionRecord.js +56 -0
- package/dist/esm/instrumentations/session/sessionManager/persistentSessionRecord.js.map +1 -0
- package/dist/esm/instrumentations/session/sessionManager/sessionConstants.js +1 -1
- package/dist/esm/instrumentations/session/sessionManager/sessionConstants.js.map +1 -1
- package/dist/esm/instrumentations/session/sessionManager/sessionManagerUtils.js +120 -44
- package/dist/esm/instrumentations/session/sessionManager/sessionManagerUtils.js.map +1 -1
- package/dist/esm/instrumentations/session/sessionManager/types.js.map +1 -1
- package/dist/esm/instrumentations/session/sessionProcess.js +89 -0
- package/dist/esm/instrumentations/session/sessionProcess.js.map +1 -0
- package/dist/esm/instrumentations/startup/index.js +2 -6
- package/dist/esm/instrumentations/startup/index.js.map +1 -1
- package/dist/esm/navigation/utils.js +2 -1
- package/dist/esm/navigation/utils.js.map +1 -1
- package/dist/esm/transports/fetch/index.js.map +1 -1
- package/dist/esm/transports/fetch/transport.js +38 -14
- package/dist/esm/transports/fetch/transport.js.map +1 -1
- package/dist/esm/transports/fetch/types.js.map +1 -1
- package/dist/esm/transports/offline/ConnectivityService.js +1 -1
- package/dist/esm/transports/offline/ConnectivityService.js.map +1 -1
- package/dist/esm/transports/offline/OfflineCache.js +2 -2
- package/dist/esm/transports/offline/OfflineCache.js.map +1 -1
- package/dist/esm/transports/offline/transport.js +3 -4
- package/dist/esm/transports/offline/transport.js.map +1 -1
- package/dist/esm/userPersistence/UserPersistence.js +1 -2
- package/dist/esm/userPersistence/UserPersistence.js.map +1 -1
- package/dist/types/config/getRNInstrumentations.d.ts +1 -2
- package/dist/types/config/sampling.d.ts +0 -3
- package/dist/types/config/types.d.ts +5 -3
- package/dist/types/dataCollection/DataCollectionPolicy.d.ts +1 -2
- package/dist/types/generated/faroRNPackageMeta.d.ts +1 -1
- package/dist/types/index.d.ts +4 -1
- package/dist/types/instrumentations/crashReporting/BaseCrashReportingInstrumentation.d.ts +14 -4
- package/dist/types/instrumentations/crashReporting/RecoveredCrashReportingInstrumentation.d.ts +27 -0
- package/dist/types/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.d.ts +2 -2
- package/dist/types/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.d.ts +2 -2
- package/dist/types/instrumentations/crashReporting/types.d.ts +6 -0
- package/dist/types/instrumentations/frameMonitoring/instrumentation.d.ts +2 -2
- package/dist/types/instrumentations/frameMonitoring/types.d.ts +4 -6
- package/dist/types/instrumentations/performance/index.d.ts +0 -2
- package/dist/types/instrumentations/session/FaroSessionActivityBoundary.d.ts +8 -0
- package/dist/types/instrumentations/session/directSessionActivity.d.ts +13 -0
- package/dist/types/instrumentations/session/index.d.ts +20 -1
- package/dist/types/instrumentations/session/sessionActivity.d.ts +9 -0
- package/dist/types/instrumentations/session/sessionAttributes.d.ts +6 -3
- package/dist/types/instrumentations/session/sessionManager/MmkvPersistentSessionsManager.d.ts +16 -3
- package/dist/types/instrumentations/session/sessionManager/VolatileSessionManager.d.ts +9 -3
- package/dist/types/instrumentations/session/sessionManager/persistentSessionRecord.d.ts +4 -0
- package/dist/types/instrumentations/session/sessionManager/sessionManagerUtils.d.ts +19 -7
- package/dist/types/instrumentations/session/sessionManager/types.d.ts +6 -0
- package/dist/types/instrumentations/session/sessionProcess.d.ts +17 -0
- package/dist/types/instrumentations/startup/index.d.ts +2 -6
- package/dist/types/navigation/utils.d.ts +1 -0
- package/dist/types/transports/fetch/index.d.ts +1 -1
- package/dist/types/transports/fetch/transport.d.ts +8 -1
- package/dist/types/transports/fetch/types.d.ts +5 -0
- package/dist/types/transports/offline/ConnectivityService.d.ts +1 -1
- package/dist/types/transports/offline/OfflineCache.d.ts +2 -2
- package/dist/types/transports/offline/transport.d.ts +3 -4
- package/dist/types/userPersistence/UserPersistence.d.ts +1 -2
- package/ios/FaroCrashReporter.swift +214 -21
- package/ios/FaroReactNative.swift +24 -0
- package/ios/FaroReactNativeModule.h +2 -1
- package/ios/FaroReactNativeModule.mm +121 -6
- package/ios/RefreshRateVitals.swift +34 -38
- package/package.json +7 -5
- package/src/config/getRNInstrumentations.ts +6 -8
- package/src/config/makeRNConfig.test.ts +6 -0
- package/src/config/makeRNConfig.ts +10 -9
- package/src/config/sampling.ts +0 -3
- package/src/config/types.ts +5 -3
- package/src/dataCollection/DataCollectionPolicy.ts +1 -2
- package/src/generated/faroRNPackageMeta.ts +1 -1
- package/src/index.ts +8 -2
- package/src/initialize.test.ts +63 -2
- package/src/instrumentations/anr/instrumentation.ts +8 -1
- package/src/instrumentations/appState/index.ts +10 -2
- package/src/instrumentations/crashReporting/BaseCrashReportingInstrumentation.ts +28 -8
- package/src/instrumentations/crashReporting/RecoveredCrashReportingInstrumentation.ts +277 -0
- package/src/instrumentations/crashReporting/android/AndroidCrashReportingInstrumentation.ts +2 -2
- package/src/instrumentations/crashReporting/instrumentation.test.ts +433 -5
- package/src/instrumentations/crashReporting/ios/IosCrashReportingInstrumentation.ts +2 -2
- package/src/instrumentations/crashReporting/types.ts +7 -0
- package/src/instrumentations/errors/index.ts +12 -4
- package/src/instrumentations/errors/instrumentation.test.ts +35 -0
- package/src/instrumentations/frameMonitoring/instrumentation.test.ts +155 -0
- package/src/instrumentations/frameMonitoring/instrumentation.ts +19 -38
- package/src/instrumentations/frameMonitoring/types.ts +4 -6
- package/src/instrumentations/performance/index.ts +2 -6
- package/src/instrumentations/session/FaroSessionActivityBoundary.test.ts +60 -0
- package/src/instrumentations/session/FaroSessionActivityBoundary.tsx +41 -0
- package/src/instrumentations/session/beforeSendHook.test.ts +246 -0
- package/src/instrumentations/session/directSessionActivity.test.ts +158 -0
- package/src/instrumentations/session/directSessionActivity.ts +36 -0
- package/src/instrumentations/session/index.ts +269 -46
- package/src/instrumentations/session/persistentColdStart.test.ts +196 -0
- package/src/instrumentations/session/sessionActivity.test.ts +68 -0
- package/src/instrumentations/session/sessionActivity.ts +58 -0
- package/src/instrumentations/session/sessionAttributes.test.ts +37 -2
- package/src/instrumentations/session/sessionAttributes.ts +12 -6
- package/src/instrumentations/session/sessionCleanup.test.ts +410 -0
- package/src/instrumentations/session/sessionManager/MmkvPersistentSessionsManager.test.ts +552 -0
- package/src/instrumentations/session/sessionManager/MmkvPersistentSessionsManager.ts +249 -33
- package/src/instrumentations/session/sessionManager/VolatileSessionManager.ts +38 -18
- package/src/instrumentations/session/sessionManager/persistentSessionRecord.test.ts +103 -0
- package/src/instrumentations/session/sessionManager/persistentSessionRecord.ts +78 -0
- package/src/instrumentations/session/sessionManager/sampling.test.ts +1 -1
- package/src/instrumentations/session/sessionManager/sessionConstants.ts +1 -1
- package/src/instrumentations/session/sessionManager/sessionManagerUtils.test.ts +256 -18
- package/src/instrumentations/session/sessionManager/sessionManagerUtils.ts +180 -39
- package/src/instrumentations/session/sessionManager/types.ts +8 -0
- package/src/instrumentations/session/sessionManagerInstance.test.ts +65 -0
- package/src/instrumentations/session/sessionProcess.test.ts +136 -0
- package/src/instrumentations/session/sessionProcess.ts +114 -0
- package/src/instrumentations/session/startNewSession.test.ts +337 -0
- package/src/instrumentations/startup/index.ts +2 -6
- package/src/navigation/utils.ts +3 -1
- package/src/transports/fetch/index.ts +6 -1
- package/src/transports/fetch/transport.test.ts +86 -2
- package/src/transports/fetch/transport.ts +38 -16
- package/src/transports/fetch/types.ts +7 -0
- package/src/transports/offline/ConnectivityService.ts +1 -1
- package/src/transports/offline/OfflineCache.ts +2 -2
- package/src/transports/offline/transport.ts +3 -4
- package/src/userPersistence/UserPersistence.ts +1 -2
- package/dist/cjs/utils/throttle.js +0 -42
- package/dist/cjs/utils/throttle.js.map +0 -1
- package/dist/esm/utils/throttle.js +0 -34
- package/dist/esm/utils/throttle.js.map +0 -1
- package/dist/types/utils/throttle.d.ts +0 -9
- package/src/utils/throttle.test.ts +0 -141
- package/src/utils/throttle.ts +0 -34
package/dist/esm/instrumentations/session/sessionManager/MmkvPersistentSessionsManager.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MmkvPersistentSessionsManager.js","sourceRoot":"","sources":["../../../../../src/instrumentations/session/sessionManager/MmkvPersistentSessionsManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { AppState, type AppStateStatus } from 'react-native';\nimport type { MMKV } from 'react-native-mmkv';\n\nimport { faro, stringifyExternalJson } from '@grafana/faro-core';\n\nimport { throttle } from '../../../utils/throttle';\n\nimport { STORAGE_KEY, STORAGE_UPDATE_DELAY } from './sessionConstants';\nimport { getSessionMetaUpdateHandler, getUserSessionUpdater } from './sessionManagerUtils';\nimport type { FaroUserSession } from './types';\n\nfunction createMmkvInstance(): MMKV {\n try {\n const { MMKV } = require('react-native-mmkv');\n return new MMKV({ id: 'grafana-faro-react-native-session' });\n } catch {\n throw new Error(\n 'sessionTracking.persistent is true but react-native-mmkv could not be loaded. Install it: yarn add react-native-mmkv, then rebuild native projects.'\n );\n }\n}\n\nlet mmkvSingleton: MMKV | undefined;\n\nfunction getMmkv(): MMKV {\n if (mmkvSingleton == null) {\n mmkvSingleton = createMmkvInstance();\n }\n return mmkvSingleton;\n}\n\n/** @internal */\nexport function resetMmkvSingletonForTests(): void {\n mmkvSingleton = undefined;\n}\n\n/**\n * Persistent session storage backed by MMKV (synchronous reads/writes).\n * Used when `sessionTracking.persistent` is true.\n */\nexport class MmkvPersistentSessionsManager {\n private updateUserSession: ReturnType<typeof getUserSessionUpdater>;\n private appStateSubscription: ReturnType<typeof AppState.addEventListener> | null = null;\n private metaUnsubscribe: (() => void) | null = null;\n\n constructor() {\n this.updateUserSession = getUserSessionUpdater({\n fetchUserSession: MmkvPersistentSessionsManager.fetchUserSession,\n storeUserSession: MmkvPersistentSessionsManager.storeUserSession,\n });\n\n this.init();\n }\n\n static removeUserSession(): void {\n try {\n getMmkv().remove(STORAGE_KEY);\n } catch (error) {\n faro.unpatchedConsole?.warn?.('Failed to remove session from MMKV:', error);\n }\n }\n\n static storeUserSession(session: FaroUserSession): void {\n try {\n getMmkv().set(STORAGE_KEY, stringifyExternalJson(session));\n } catch (error) {\n faro.unpatchedConsole?.warn?.('Failed to store session in MMKV:', error);\n }\n }\n\n static fetchUserSession(): FaroUserSession | null {\n try {\n const storedSession = getMmkv().getString(STORAGE_KEY);\n if (storedSession) {\n return JSON.parse(storedSession) as FaroUserSession;\n }\n return null;\n } catch (error) {\n faro.unpatchedConsole?.warn?.('Failed to fetch session from MMKV:', error);\n return null;\n }\n }\n\n updateSession = throttle(() => this.updateUserSession(), STORAGE_UPDATE_DELAY);\n\n private handleAppStateChange = (nextAppState: AppStateStatus) => {\n if (nextAppState === 'active') {\n this.updateSession();\n }\n };\n\n private init(): void {\n this.appStateSubscription = AppState.addEventListener('change', this.handleAppStateChange);\n\n const unsubscribe = faro.metas.addListener(\n getSessionMetaUpdateHandler({\n fetchUserSession: MmkvPersistentSessionsManager.fetchUserSession,\n storeUserSession: MmkvPersistentSessionsManager.storeUserSession,\n })\n );\n this.metaUnsubscribe = typeof unsubscribe === 'function' ? unsubscribe : null;\n }\n\n unpatch(): void {\n if (this.appStateSubscription) {\n this.appStateSubscription.remove();\n this.appStateSubscription = null;\n }\n\n if (this.metaUnsubscribe) {\n this.metaUnsubscribe();\n this.metaUnsubscribe = null;\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"MmkvPersistentSessionsManager.js","sourceRoot":"","sources":["../../../../../src/instrumentations/session/sessionManager/MmkvPersistentSessionsManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { AppState, type AppStateStatus, Platform } from 'react-native';\nimport type { MMKV } from 'react-native-mmkv';\n\nimport { dateNow, faro } from '@grafana/faro-core';\nimport type { Metas } from '@grafana/faro-core';\n\nimport { SessionActivityKind } from '../sessionActivity';\nimport {\n claimSessionPersistenceStorageId,\n getSessionProcessInfo,\n releaseSessionPersistenceOwnership,\n} from '../sessionProcess';\n\nimport { parsePersistentSession, serializePersistentSession } from './persistentSessionRecord';\nimport { STORAGE_KEY, STORAGE_UPDATE_DELAY } from './sessionConstants';\nimport {\n getSessionMetaUpdateHandler,\n getUserSessionResetter,\n getUserSessionUpdater,\n toStorableSessionMeta,\n} from './sessionManagerUtils';\nimport type { FaroUserSession } from './types';\n\ntype MmkvConfiguration = {\n id: string;\n mode?: number | 'multi-process';\n};\n\ntype MmkvModule = {\n createMMKV?: (configuration: MmkvConfiguration) => MMKV;\n MMKV?: new (configuration: MmkvConfiguration) => MMKV;\n Mode?: { MULTI_PROCESS?: number };\n};\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction loadMmkvModule(): MmkvModule {\n try {\n return require('react-native-mmkv') as MmkvModule;\n } catch (error) {\n throw new Error(\n `react-native-mmkv could not be loaded. Install it and rebuild the native project. ${errorMessage(error)}`\n );\n }\n}\n\nfunction mmkvConfiguration(mmkv: MmkvModule, storageId: string, isIosExtension: boolean): MmkvConfiguration {\n if (!isIosExtension) {\n return { id: storageId };\n }\n\n if (typeof mmkv.createMMKV === 'function') {\n return { id: storageId, mode: 'multi-process' };\n }\n\n const legacyMultiProcessMode = mmkv.Mode?.MULTI_PROCESS;\n if (typeof legacyMultiProcessMode !== 'number') {\n throw new Error('Persisting sessions in an iOS extension requires react-native-mmkv v3 or newer.');\n }\n\n return { id: storageId, mode: legacyMultiProcessMode };\n}\n\nfunction createMmkvInstance(): MMKV {\n // Load MMKV before taking native ownership so a missing dependency cannot\n // leave the process-wide claim occupied.\n const mmkv = loadMmkvModule();\n const processInfo = getSessionProcessInfo();\n const storageId = claimSessionPersistenceStorageId();\n if (storageId == null || processInfo == null) {\n throw new Error(\n 'Native session-storage coordination is unavailable or already owned by another runtime. Rebuild the native app after upgrading Faro, or use sessionTracking.persistent=false in runtimes that cannot own storage.'\n );\n }\n\n try {\n const configuration = mmkvConfiguration(mmkv, storageId, Platform.OS === 'ios' && !processInfo.isMain);\n // react-native-mmkv v4 was rewritten to Nitro and removed the `new MMKV()`\n // class constructor in favor of a `createMMKV()` factory (see the v4 upgrade\n // guide). Support both so v2/v3 (class) and v4+ (factory) work.\n if (typeof mmkv.createMMKV === 'function') {\n return mmkv.createMMKV(configuration);\n }\n if (typeof mmkv.MMKV !== 'function') {\n throw new Error('The installed react-native-mmkv package does not expose a supported storage API.');\n }\n return new mmkv.MMKV(configuration);\n } catch (error) {\n releaseSessionPersistenceOwnership();\n throw new Error(`Session persistence could not be initialized. ${errorMessage(error)}`);\n }\n}\n\n// undefined means MMKV has not been resolved; null means it is unavailable.\nlet mmkvSingleton: MMKV | null | undefined;\n// undefined means storage has not been read, null means no persisted state is\n// available, and a session is the live value for this JavaScript runtime.\nlet runtimeSession: FaroUserSession | null | undefined;\n\nfunction tryGetMmkv(): MMKV | null {\n if (mmkvSingleton !== undefined) {\n return mmkvSingleton;\n }\n\n try {\n mmkvSingleton = createMmkvInstance();\n } catch (error) {\n mmkvSingleton = null;\n faro.unpatchedConsole?.warn?.('Session persistence is unavailable; using an in-memory session:', error);\n }\n\n return mmkvSingleton;\n}\n\nfunction removeMmkvValue(mmkv: MMKV, key: string): void {\n const compatibleMmkv = mmkv as MMKV & {\n delete?: (storageKey: string) => void;\n remove?: (storageKey: string) => void;\n };\n\n if (typeof compatibleMmkv.remove === 'function') {\n compatibleMmkv.remove(key);\n return;\n }\n if (typeof compatibleMmkv.delete === 'function') {\n compatibleMmkv.delete(key);\n return;\n }\n\n throw new Error('The installed react-native-mmkv version cannot remove stored values.');\n}\n\n/** @internal */\nexport function resetMmkvSingletonForTests(): void {\n mmkvSingleton = undefined;\n runtimeSession = undefined;\n}\n\n/**\n * Persistent session storage backed by MMKV (synchronous reads/writes).\n * Used when `sessionTracking.persistent` is true.\n */\nexport class MmkvPersistentSessionsManager {\n private resetUserSession: ReturnType<typeof getUserSessionResetter>;\n private updateUserSession: ReturnType<typeof getUserSessionUpdater>;\n private appStateSubscription: ReturnType<typeof AppState.addEventListener> | null = null;\n private activityWriteTimer: ReturnType<typeof setTimeout> | null = null;\n private hasPendingActivityWrite = false;\n private lastActivityWrite = 0;\n private wasBackgrounded = AppState.currentState === 'background';\n private metaUpdateHandler: ReturnType<typeof getSessionMetaUpdateHandler> | null = null;\n private readonly metas: Metas;\n\n constructor(metas: Metas = faro.metas) {\n this.metas = metas;\n this.updateUserSession = getUserSessionUpdater({\n fetchUserSession: MmkvPersistentSessionsManager.fetchUserSession,\n recordUserSessionActivity: this.recordUserSessionActivity,\n storeUserSession: MmkvPersistentSessionsManager.storeUserSession,\n });\n this.resetUserSession = getUserSessionResetter({\n fetchUserSession: MmkvPersistentSessionsManager.fetchUserSession,\n storeUserSession: MmkvPersistentSessionsManager.storeUserSession,\n });\n\n this.init();\n }\n\n static removeUserSession(): void {\n runtimeSession = null;\n const mmkv = tryGetMmkv();\n if (mmkv == null) {\n return;\n }\n try {\n removeMmkvValue(mmkv, STORAGE_KEY);\n } catch (error) {\n faro.unpatchedConsole?.warn?.('Failed to remove session from MMKV:', error);\n }\n }\n\n static storeUserSession(session: FaroUserSession): void {\n MmkvPersistentSessionsManager.setRuntimeSession(session);\n MmkvPersistentSessionsManager.persistSession(session);\n }\n\n private static setRuntimeSession(session: FaroUserSession): void {\n runtimeSession =\n session.sessionMeta == null\n ? session\n : {\n ...session,\n sessionMeta: toStorableSessionMeta(session.sessionMeta),\n };\n }\n\n private static persistSession(session: FaroUserSession): void {\n const mmkv = tryGetMmkv();\n if (mmkv == null) {\n return;\n }\n try {\n mmkv.set(STORAGE_KEY, serializePersistentSession(session));\n } catch (error) {\n faro.unpatchedConsole?.warn?.('Failed to store session in MMKV:', error);\n }\n }\n\n static fetchUserSession(): FaroUserSession | null {\n if (runtimeSession !== undefined) {\n return runtimeSession;\n }\n\n const mmkv = tryGetMmkv();\n if (mmkv == null) {\n runtimeSession = null;\n return null;\n }\n\n try {\n const storedSession = mmkv.getString(STORAGE_KEY);\n if (storedSession == null) {\n runtimeSession = null;\n return null;\n }\n\n runtimeSession = parsePersistentSession(storedSession);\n if (runtimeSession == null) {\n removeMmkvValue(mmkv, STORAGE_KEY);\n }\n return runtimeSession;\n } catch (error) {\n runtimeSession = null;\n faro.unpatchedConsole?.warn?.('Failed to fetch session from MMKV:', error);\n return null;\n }\n }\n\n checkSession(activity: SessionActivityKind, currentSession?: FaroUserSession | null): FaroUserSession {\n return this.updateUserSession(activity, currentSession);\n }\n\n resetSession(): FaroUserSession {\n if (this.activityWriteTimer != null) {\n clearTimeout(this.activityWriteTimer);\n this.activityWriteTimer = null;\n }\n this.hasPendingActivityWrite = false;\n\n const session = this.resetUserSession();\n this.lastActivityWrite = dateNow();\n return session;\n }\n\n private flushActivityWrite = (): void => {\n if (this.activityWriteTimer != null) {\n clearTimeout(this.activityWriteTimer);\n this.activityWriteTimer = null;\n }\n\n if (!this.hasPendingActivityWrite) {\n return;\n }\n\n const session = MmkvPersistentSessionsManager.fetchUserSession();\n this.hasPendingActivityWrite = false;\n if (session == null) {\n return;\n }\n\n MmkvPersistentSessionsManager.persistSession(session);\n this.lastActivityWrite = dateNow();\n };\n\n private recordUserSessionActivity = (session: FaroUserSession): void => {\n // Keep expiry checks exact in memory while limiting native storage writes.\n MmkvPersistentSessionsManager.setRuntimeSession(session);\n this.hasPendingActivityWrite = true;\n\n const elapsed = dateNow() - this.lastActivityWrite;\n if (this.lastActivityWrite === 0 || elapsed < 0 || elapsed >= STORAGE_UPDATE_DELAY) {\n this.flushActivityWrite();\n return;\n }\n\n if (this.activityWriteTimer == null) {\n this.activityWriteTimer = setTimeout(this.flushActivityWrite, STORAGE_UPDATE_DELAY - elapsed);\n }\n };\n\n private handleAppStateChange = (nextAppState: AppStateStatus) => {\n if (nextAppState === 'background') {\n this.wasBackgrounded = true;\n this.flushActivityWrite();\n return;\n }\n\n if (nextAppState === 'active' && this.wasBackgrounded) {\n this.wasBackgrounded = false;\n this.checkSession(SessionActivityKind.Meaningful);\n }\n };\n\n private init(): void {\n this.appStateSubscription = AppState.addEventListener('change', this.handleAppStateChange);\n\n const metaUpdateHandler = getSessionMetaUpdateHandler({\n fetchUserSession: MmkvPersistentSessionsManager.fetchUserSession,\n storeUserSession: MmkvPersistentSessionsManager.storeUserSession,\n });\n this.metas.addListener(metaUpdateHandler);\n this.metaUpdateHandler = metaUpdateHandler;\n }\n\n unpatch(): void {\n this.flushActivityWrite();\n\n if (this.appStateSubscription) {\n this.appStateSubscription.remove();\n this.appStateSubscription = null;\n }\n\n const metaUpdateHandler = this.metaUpdateHandler;\n this.metaUpdateHandler = null;\n if (metaUpdateHandler) {\n this.metas.removeListener(metaUpdateHandler);\n }\n }\n}\n"]}
|
|
@@ -1,22 +1,31 @@
|
|
|
1
1
|
import { AppState } from 'react-native';
|
|
2
2
|
import { faro } from '@grafana/faro-core';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { getSessionMetaUpdateHandler, getUserSessionUpdater } from './sessionManagerUtils';
|
|
3
|
+
import { SessionActivityKind } from '../sessionActivity';
|
|
4
|
+
import { getSessionMetaUpdateHandler, getUserSessionResetter, getUserSessionUpdater } from './sessionManagerUtils';
|
|
6
5
|
export class VolatileSessionsManager {
|
|
7
|
-
constructor() {
|
|
6
|
+
constructor(metas = faro.metas) {
|
|
8
7
|
this.appStateSubscription = null;
|
|
9
|
-
this.
|
|
10
|
-
this.
|
|
8
|
+
this.wasBackgrounded = AppState.currentState === 'background';
|
|
9
|
+
this.metaUpdateHandler = null;
|
|
11
10
|
this.handleAppStateChange = (nextAppState) => {
|
|
12
|
-
if (nextAppState === '
|
|
13
|
-
this.
|
|
11
|
+
if (nextAppState === 'background') {
|
|
12
|
+
this.wasBackgrounded = true;
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
if (nextAppState === 'active' && this.wasBackgrounded) {
|
|
16
|
+
this.wasBackgrounded = false;
|
|
17
|
+
this.checkSession(SessionActivityKind.Meaningful);
|
|
14
18
|
}
|
|
15
19
|
};
|
|
20
|
+
this.metas = metas;
|
|
16
21
|
this.updateUserSession = getUserSessionUpdater({
|
|
17
22
|
fetchUserSession: VolatileSessionsManager.fetchUserSession,
|
|
18
23
|
storeUserSession: VolatileSessionsManager.storeUserSession,
|
|
19
24
|
});
|
|
25
|
+
this.resetUserSession = getUserSessionResetter({
|
|
26
|
+
fetchUserSession: VolatileSessionsManager.fetchUserSession,
|
|
27
|
+
storeUserSession: VolatileSessionsManager.storeUserSession,
|
|
28
|
+
});
|
|
20
29
|
this.init();
|
|
21
30
|
}
|
|
22
31
|
static removeUserSession() {
|
|
@@ -28,15 +37,22 @@ export class VolatileSessionsManager {
|
|
|
28
37
|
static fetchUserSession() {
|
|
29
38
|
return VolatileSessionsManager.volatileStorage;
|
|
30
39
|
}
|
|
40
|
+
checkSession(activity, currentSession) {
|
|
41
|
+
return this.updateUserSession(activity, currentSession);
|
|
42
|
+
}
|
|
43
|
+
resetSession() {
|
|
44
|
+
return this.resetUserSession();
|
|
45
|
+
}
|
|
31
46
|
init() {
|
|
32
47
|
// Listen to app state changes (equivalent to visibilitychange in web)
|
|
33
48
|
this.appStateSubscription = AppState.addEventListener('change', this.handleAppStateChange);
|
|
34
49
|
// Users can call the setSession() method, so we need to sync this with the in-memory session
|
|
35
|
-
const
|
|
50
|
+
const metaUpdateHandler = getSessionMetaUpdateHandler({
|
|
36
51
|
fetchUserSession: VolatileSessionsManager.fetchUserSession,
|
|
37
52
|
storeUserSession: VolatileSessionsManager.storeUserSession,
|
|
38
|
-
})
|
|
39
|
-
this.
|
|
53
|
+
});
|
|
54
|
+
this.metas.addListener(metaUpdateHandler);
|
|
55
|
+
this.metaUpdateHandler = metaUpdateHandler;
|
|
40
56
|
}
|
|
41
57
|
/**
|
|
42
58
|
* Clean up listeners when the instrumentation is unpatched
|
|
@@ -46,9 +62,10 @@ export class VolatileSessionsManager {
|
|
|
46
62
|
this.appStateSubscription.remove();
|
|
47
63
|
this.appStateSubscription = null;
|
|
48
64
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
65
|
+
const metaUpdateHandler = this.metaUpdateHandler;
|
|
66
|
+
this.metaUpdateHandler = null;
|
|
67
|
+
if (metaUpdateHandler) {
|
|
68
|
+
this.metas.removeListener(metaUpdateHandler);
|
|
52
69
|
}
|
|
53
70
|
}
|
|
54
71
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VolatileSessionManager.js","sourceRoot":"","sources":["../../../../../src/instrumentations/session/sessionManager/VolatileSessionManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAuB,MAAM,cAAc,CAAC;AAE7D,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"VolatileSessionManager.js","sourceRoot":"","sources":["../../../../../src/instrumentations/session/sessionManager/VolatileSessionManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { AppState, type AppStateStatus } from 'react-native';\n\nimport { faro } from '@grafana/faro-core';\nimport type { Metas } from '@grafana/faro-core';\n\nimport { SessionActivityKind } from '../sessionActivity';\n\nimport { getSessionMetaUpdateHandler, getUserSessionResetter, getUserSessionUpdater } from './sessionManagerUtils';\nimport type { FaroUserSession } from './types';\n\nexport class VolatileSessionsManager {\n private static volatileStorage: FaroUserSession | null = null;\n private resetUserSession: ReturnType<typeof getUserSessionResetter>;\n private updateUserSession: ReturnType<typeof getUserSessionUpdater>;\n private appStateSubscription: ReturnType<typeof AppState.addEventListener> | null = null;\n private wasBackgrounded = AppState.currentState === 'background';\n private metaUpdateHandler: ReturnType<typeof getSessionMetaUpdateHandler> | null = null;\n private readonly metas: Metas;\n\n constructor(metas: Metas = faro.metas) {\n this.metas = metas;\n this.updateUserSession = getUserSessionUpdater({\n fetchUserSession: VolatileSessionsManager.fetchUserSession,\n storeUserSession: VolatileSessionsManager.storeUserSession,\n });\n this.resetUserSession = getUserSessionResetter({\n fetchUserSession: VolatileSessionsManager.fetchUserSession,\n storeUserSession: VolatileSessionsManager.storeUserSession,\n });\n\n this.init();\n }\n\n static removeUserSession(): void {\n VolatileSessionsManager.volatileStorage = null;\n }\n\n static storeUserSession(session: FaroUserSession): void {\n VolatileSessionsManager.volatileStorage = session;\n }\n\n static fetchUserSession(): FaroUserSession | null {\n return VolatileSessionsManager.volatileStorage;\n }\n\n checkSession(activity: SessionActivityKind, currentSession?: FaroUserSession | null): FaroUserSession {\n return this.updateUserSession(activity, currentSession);\n }\n\n resetSession(): FaroUserSession {\n return this.resetUserSession();\n }\n\n private handleAppStateChange = (nextAppState: AppStateStatus) => {\n if (nextAppState === 'background') {\n this.wasBackgrounded = true;\n return;\n }\n\n if (nextAppState === 'active' && this.wasBackgrounded) {\n this.wasBackgrounded = false;\n this.checkSession(SessionActivityKind.Meaningful);\n }\n };\n\n private init(): void {\n // Listen to app state changes (equivalent to visibilitychange in web)\n this.appStateSubscription = AppState.addEventListener('change', this.handleAppStateChange);\n\n // Users can call the setSession() method, so we need to sync this with the in-memory session\n const metaUpdateHandler = getSessionMetaUpdateHandler({\n fetchUserSession: VolatileSessionsManager.fetchUserSession,\n storeUserSession: VolatileSessionsManager.storeUserSession,\n });\n this.metas.addListener(metaUpdateHandler);\n this.metaUpdateHandler = metaUpdateHandler;\n }\n\n /**\n * Clean up listeners when the instrumentation is unpatched\n */\n unpatch(): void {\n if (this.appStateSubscription) {\n this.appStateSubscription.remove();\n this.appStateSubscription = null;\n }\n\n const metaUpdateHandler = this.metaUpdateHandler;\n this.metaUpdateHandler = null;\n if (metaUpdateHandler) {\n this.metas.removeListener(metaUpdateHandler);\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export const PERSISTED_SESSION_SCHEMA_VERSION = 1;
|
|
2
|
+
function isRecord(value) {
|
|
3
|
+
return typeof value === 'object' && value != null && !Array.isArray(value);
|
|
4
|
+
}
|
|
5
|
+
function isNonEmptyString(value) {
|
|
6
|
+
return typeof value === 'string' && value.length > 0;
|
|
7
|
+
}
|
|
8
|
+
function isValidTimestamp(value) {
|
|
9
|
+
return typeof value === 'number' && Number.isFinite(value) && value >= 0;
|
|
10
|
+
}
|
|
11
|
+
export function serializePersistentSession(session) {
|
|
12
|
+
var _a, _b;
|
|
13
|
+
const previousSession = (_b = (_a = session.sessionMeta) === null || _a === void 0 ? void 0 : _a.attributes) === null || _b === void 0 ? void 0 : _b['previousSession'];
|
|
14
|
+
const record = {
|
|
15
|
+
schemaVersion: PERSISTED_SESSION_SCHEMA_VERSION,
|
|
16
|
+
currentSessionId: session.sessionId,
|
|
17
|
+
previousSessionId: isNonEmptyString(previousSession) ? previousSession : null,
|
|
18
|
+
startedAt: session.started,
|
|
19
|
+
// Preserve the record invariant if the device clock moves backwards after
|
|
20
|
+
// the session starts.
|
|
21
|
+
lastActivityAt: Math.max(session.started, session.lastActivity),
|
|
22
|
+
isSampled: session.isSampled,
|
|
23
|
+
};
|
|
24
|
+
return JSON.stringify(record);
|
|
25
|
+
}
|
|
26
|
+
export function parsePersistentSession(serialized) {
|
|
27
|
+
let value;
|
|
28
|
+
try {
|
|
29
|
+
value = JSON.parse(serialized);
|
|
30
|
+
}
|
|
31
|
+
catch (_a) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
if (!isRecord(value) ||
|
|
35
|
+
value['schemaVersion'] !== PERSISTED_SESSION_SCHEMA_VERSION ||
|
|
36
|
+
!isNonEmptyString(value['currentSessionId']) ||
|
|
37
|
+
!(value['previousSessionId'] === null || isNonEmptyString(value['previousSessionId'])) ||
|
|
38
|
+
!isValidTimestamp(value['startedAt']) ||
|
|
39
|
+
!isValidTimestamp(value['lastActivityAt']) ||
|
|
40
|
+
value['lastActivityAt'] < value['startedAt'] ||
|
|
41
|
+
typeof value['isSampled'] !== 'boolean') {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
const previousSessionId = value['previousSessionId'];
|
|
45
|
+
return {
|
|
46
|
+
sessionId: value['currentSessionId'],
|
|
47
|
+
started: value['startedAt'],
|
|
48
|
+
lastActivity: value['lastActivityAt'],
|
|
49
|
+
isSampled: value['isSampled'],
|
|
50
|
+
sessionMeta: {
|
|
51
|
+
id: value['currentSessionId'],
|
|
52
|
+
attributes: Object.assign({ isSampled: value['isSampled'].toString() }, (previousSessionId == null ? {} : { previousSession: previousSessionId })),
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=persistentSessionRecord.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistentSessionRecord.js","sourceRoot":"","sources":["../../../../../src/instrumentations/session/sessionManager/persistentSessionRecord.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC;AAWlD,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC7E,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc;IACtC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc;IACtC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,OAAwB;;IACjE,MAAM,eAAe,GAAG,MAAA,MAAA,OAAO,CAAC,WAAW,0CAAE,UAAU,0CAAG,iBAAiB,CAAC,CAAC;IAC7E,MAAM,MAAM,GAA2B;QACrC,aAAa,EAAE,gCAAgC;QAC/C,gBAAgB,EAAE,OAAO,CAAC,SAAS;QACnC,iBAAiB,EAAE,gBAAgB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI;QAC7E,SAAS,EAAE,OAAO,CAAC,OAAO;QAC1B,0EAA0E;QAC1E,sBAAsB;QACtB,cAAc,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC;QAC/D,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC;IAEF,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,UAAkB;IACvD,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACjC,CAAC;IAAC,WAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IACE,CAAC,QAAQ,CAAC,KAAK,CAAC;QAChB,KAAK,CAAC,eAAe,CAAC,KAAK,gCAAgC;QAC3D,CAAC,gBAAgB,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAC5C,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,KAAK,IAAI,IAAI,gBAAgB,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC;QACtF,CAAC,gBAAgB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACrC,CAAC,gBAAgB,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAC1C,KAAK,CAAC,gBAAgB,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC;QAC5C,OAAO,KAAK,CAAC,WAAW,CAAC,KAAK,SAAS,EACvC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,iBAAiB,GAAG,KAAK,CAAC,mBAAmB,CAAC,CAAC;IAErD,OAAO;QACL,SAAS,EAAE,KAAK,CAAC,kBAAkB,CAAC;QACpC,OAAO,EAAE,KAAK,CAAC,WAAW,CAAC;QAC3B,YAAY,EAAE,KAAK,CAAC,gBAAgB,CAAC;QACrC,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC;QAC7B,WAAW,EAAE;YACX,EAAE,EAAE,KAAK,CAAC,kBAAkB,CAAC;YAC7B,UAAU,kBACR,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,IACrC,CAAC,iBAAiB,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,iBAAiB,EAAE,CAAC,CAC7E;SACF;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { FaroUserSession } from './types';\n\nexport const PERSISTED_SESSION_SCHEMA_VERSION = 1;\n\ntype PersistedSessionRecord = {\n schemaVersion: typeof PERSISTED_SESSION_SCHEMA_VERSION;\n currentSessionId: string;\n previousSessionId: string | null;\n startedAt: number;\n lastActivityAt: number;\n isSampled: boolean;\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value != null && !Array.isArray(value);\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0;\n}\n\nfunction isValidTimestamp(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0;\n}\n\nexport function serializePersistentSession(session: FaroUserSession): string {\n const previousSession = session.sessionMeta?.attributes?.['previousSession'];\n const record: PersistedSessionRecord = {\n schemaVersion: PERSISTED_SESSION_SCHEMA_VERSION,\n currentSessionId: session.sessionId,\n previousSessionId: isNonEmptyString(previousSession) ? previousSession : null,\n startedAt: session.started,\n // Preserve the record invariant if the device clock moves backwards after\n // the session starts.\n lastActivityAt: Math.max(session.started, session.lastActivity),\n isSampled: session.isSampled,\n };\n\n return JSON.stringify(record);\n}\n\nexport function parsePersistentSession(serialized: string): FaroUserSession | null {\n let value: unknown;\n try {\n value = JSON.parse(serialized);\n } catch {\n return null;\n }\n\n if (\n !isRecord(value) ||\n value['schemaVersion'] !== PERSISTED_SESSION_SCHEMA_VERSION ||\n !isNonEmptyString(value['currentSessionId']) ||\n !(value['previousSessionId'] === null || isNonEmptyString(value['previousSessionId'])) ||\n !isValidTimestamp(value['startedAt']) ||\n !isValidTimestamp(value['lastActivityAt']) ||\n value['lastActivityAt'] < value['startedAt'] ||\n typeof value['isSampled'] !== 'boolean'\n ) {\n return null;\n }\n\n const previousSessionId = value['previousSessionId'];\n\n return {\n sessionId: value['currentSessionId'],\n started: value['startedAt'],\n lastActivity: value['lastActivityAt'],\n isSampled: value['isSampled'],\n sessionMeta: {\n id: value['currentSessionId'],\n attributes: {\n isSampled: value['isSampled'].toString(),\n ...(previousSessionId == null ? {} : { previousSession: previousSessionId }),\n },\n },\n };\n}\n"]}
|
|
@@ -5,7 +5,7 @@ export const MAX_SESSION_PERSISTENCE_TIME = DEFAULT_SESSION_PERSISTENCE_MS;
|
|
|
5
5
|
/** React Native session defaults */
|
|
6
6
|
export const defaultSessionTrackingConfig = {
|
|
7
7
|
enabled: true,
|
|
8
|
-
persistent:
|
|
8
|
+
persistent: true,
|
|
9
9
|
maxSessionPersistenceTime: MAX_SESSION_PERSISTENCE_TIME,
|
|
10
10
|
};
|
|
11
11
|
//# sourceMappingURL=sessionConstants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionConstants.js","sourceRoot":"","sources":["../../../../../src/instrumentations/session/sessionManager/sessionConstants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,WAAW,GAAG,0BAA0B,CAAC;AACtD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,WAAW;AAEzD,MAAM,8BAA8B,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;AACpE,MAAM,CAAC,MAAM,4BAA4B,GAAG,8BAA8B,CAAC;AAE3E,oCAAoC;AACpC,MAAM,CAAC,MAAM,4BAA4B,GAAqC;IAC5E,OAAO,EAAE,IAAI;IACb,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"sessionConstants.js","sourceRoot":"","sources":["../../../../../src/instrumentations/session/sessionManager/sessionConstants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,WAAW,GAAG,0BAA0B,CAAC;AACtD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,WAAW;AAEzD,MAAM,8BAA8B,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;AACpE,MAAM,CAAC,MAAM,4BAA4B,GAAG,8BAA8B,CAAC;AAE3E,oCAAoC;AACpC,MAAM,CAAC,MAAM,4BAA4B,GAAqC;IAC5E,OAAO,EAAE,IAAI;IACb,UAAU,EAAE,IAAI;IAChB,yBAAyB,EAAE,4BAA4B;CACxD,CAAC","sourcesContent":["import type { ReactNativeSessionTrackingConfig } from '../../../config/types';\n\nexport const STORAGE_KEY = 'com.grafana.faro.session';\nexport const STORAGE_UPDATE_DELAY = 1 * 1000; // 1 second\n\nconst DEFAULT_SESSION_PERSISTENCE_MS = 15 * 60 * 1000; // 15 minutes\nexport const MAX_SESSION_PERSISTENCE_TIME = DEFAULT_SESSION_PERSISTENCE_MS;\n\n/** React Native session defaults */\nexport const defaultSessionTrackingConfig: ReactNativeSessionTrackingConfig = {\n enabled: true,\n persistent: true,\n maxSessionPersistenceTime: MAX_SESSION_PERSISTENCE_TIME,\n};\n"]}
|
|
@@ -1,13 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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 { dateNow, deepEqual, EVENT_OVERRIDES_SERVICE_NAME, faro, genShortID, isEmpty } from '@grafana/faro-core';
|
|
1
|
+
import { dateNow, deepEqual, EVENT_OVERRIDES_SERVICE_NAME, faro, genShortID, isEmpty, stringifyExternalJson, } from '@grafana/faro-core';
|
|
2
|
+
import { SessionActivityKind } from '../sessionActivity';
|
|
11
3
|
import { isSampled } from './sampling';
|
|
12
4
|
import { MAX_SESSION_PERSISTENCE_TIME } from './sessionConstants';
|
|
13
5
|
const DEFAULT_SESSION_EXPIRATION_MS = 4 * 60 * 60 * 1000; // 4 hours (not in faro-core)
|
|
@@ -39,33 +31,84 @@ export function isUserSessionValid(session) {
|
|
|
39
31
|
}
|
|
40
32
|
const { sessionExpirationTime, inactivityTimeout } = getSessionTimeouts();
|
|
41
33
|
const now = dateNow();
|
|
34
|
+
if (session.started > now || session.lastActivity > now) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
42
37
|
const lifetimeValid = now - session.started < sessionExpirationTime;
|
|
43
38
|
if (!lifetimeValid) {
|
|
44
39
|
return false;
|
|
45
40
|
}
|
|
41
|
+
// The session expires at the boundary, matching cold-start record cleanup.
|
|
46
42
|
const inactivityPeriodValid = now - session.lastActivity < inactivityTimeout;
|
|
47
43
|
return inactivityPeriodValid;
|
|
48
44
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
45
|
+
function notifySessionChange(previousSession, newSession) {
|
|
46
|
+
var _a, _b, _c, _d, _e;
|
|
47
|
+
const newSessionMeta = newSession.sessionMeta;
|
|
48
|
+
if (newSessionMeta == null) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
(_b = (_a = faro.config.sessionTracking) === null || _a === void 0 ? void 0 : _a.onSessionChange) === null || _b === void 0 ? void 0 : _b.call(_a, (_c = previousSession === null || previousSession === void 0 ? void 0 : previousSession.sessionMeta) !== null && _c !== void 0 ? _c : null, newSessionMeta);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
(_e = (_d = faro.unpatchedConsole) === null || _d === void 0 ? void 0 : _d.warn) === null || _e === void 0 ? void 0 : _e.call(_d, 'The session change callback failed:', error);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function createNextUserSession(previousSession) {
|
|
59
|
+
var _a, _b;
|
|
60
|
+
const nextSession = createUserSessionObject({ isSampled: isSampled() });
|
|
61
|
+
if (previousSession != null && nextSession.sessionId === previousSession.sessionId) {
|
|
62
|
+
(_b = (_a = faro.unpatchedConsole) === null || _a === void 0 ? void 0 : _a.warn) === null || _b === void 0 ? void 0 : _b.call(_a, 'The session ID generator returned the current session ID; using a generated fallback for the new session.');
|
|
63
|
+
nextSession.sessionId = genShortID();
|
|
64
|
+
}
|
|
65
|
+
return addSessionMetadataToNextSession(nextSession, previousSession);
|
|
66
|
+
}
|
|
67
|
+
function startNextUserSession(previousSession, storeUserSession) {
|
|
68
|
+
var _a;
|
|
69
|
+
const nextSession = createNextUserSession(previousSession);
|
|
70
|
+
storeUserSession(nextSession);
|
|
71
|
+
// setSession synchronously emits session_start through the meta listener.
|
|
72
|
+
// The transport hook then resumes and attributes the triggering item to
|
|
73
|
+
// the newly stored session.
|
|
74
|
+
(_a = faro.api) === null || _a === void 0 ? void 0 : _a.setSession(nextSession.sessionMeta);
|
|
75
|
+
notifySessionChange(previousSession, nextSession);
|
|
76
|
+
return nextSession;
|
|
77
|
+
}
|
|
78
|
+
export function getUserSessionResetter({ fetchUserSession, storeUserSession, }) {
|
|
79
|
+
return function resetSession() {
|
|
80
|
+
return startNextUserSession(fetchUserSession(), storeUserSession);
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export function getUserSessionUpdater({ fetchUserSession, recordUserSessionActivity, storeUserSession, }) {
|
|
84
|
+
const persistActivity = recordUserSessionActivity !== null && recordUserSessionActivity !== void 0 ? recordUserSessionActivity : storeUserSession;
|
|
85
|
+
return function updateSession(activity, currentSession) {
|
|
86
|
+
const sessionFromStorage = currentSession === undefined ? fetchUserSession() : currentSession;
|
|
87
|
+
if (sessionFromStorage != null && isUserSessionValid(sessionFromStorage)) {
|
|
88
|
+
if (activity === SessionActivityKind.Meaningful) {
|
|
89
|
+
const lastActivity = dateNow();
|
|
90
|
+
if (lastActivity === sessionFromStorage.lastActivity) {
|
|
91
|
+
return sessionFromStorage;
|
|
92
|
+
}
|
|
93
|
+
const refreshedSession = Object.assign(Object.assign({}, sessionFromStorage), { lastActivity });
|
|
94
|
+
persistActivity(refreshedSession);
|
|
95
|
+
return refreshedSession;
|
|
65
96
|
}
|
|
66
|
-
|
|
97
|
+
return sessionFromStorage;
|
|
98
|
+
}
|
|
99
|
+
return startNextUserSession(sessionFromStorage, storeUserSession);
|
|
67
100
|
};
|
|
68
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Persistent storage serializes sessions with `stringifyExternalJson`, which
|
|
104
|
+
* drops keys whose value is `undefined`. A session meta carrying such a key
|
|
105
|
+
* never compares `deepEqual` to its own stored copy, so the sync handler would
|
|
106
|
+
* rewrite the session on every meta notification. Applying the same round-trip
|
|
107
|
+
* in memory keeps the two sides comparable, for attributes and overrides alike.
|
|
108
|
+
*/
|
|
109
|
+
export function toStorableSessionMeta(sessionMeta) {
|
|
110
|
+
return JSON.parse(stringifyExternalJson(sessionMeta));
|
|
111
|
+
}
|
|
69
112
|
export function addSessionMetadataToNextSession(newSession, previousSession) {
|
|
70
113
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
71
114
|
const sessionWithMeta = Object.assign(Object.assign({}, newSession), { sessionMeta: {
|
|
@@ -77,31 +120,64 @@ export function addSessionMetadataToNextSession(newSession, previousSession) {
|
|
|
77
120
|
sessionWithMeta.sessionMeta.overrides = overrides;
|
|
78
121
|
}
|
|
79
122
|
const previousSessionId = previousSession === null || previousSession === void 0 ? void 0 : previousSession.sessionId;
|
|
80
|
-
if (previousSessionId != null) {
|
|
123
|
+
if (previousSessionId != null && previousSessionId !== newSession.sessionId) {
|
|
81
124
|
sessionWithMeta.sessionMeta.attributes['previousSession'] = previousSessionId;
|
|
82
125
|
}
|
|
126
|
+
// Normalize to what storage can hold, so the meta this session propagates
|
|
127
|
+
// stays comparable to its own stored copy.
|
|
128
|
+
sessionWithMeta.sessionMeta = toStorableSessionMeta(sessionWithMeta.sessionMeta);
|
|
83
129
|
return sessionWithMeta;
|
|
84
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Set only while a handler applies its own session update.
|
|
133
|
+
*
|
|
134
|
+
* `setSession()` notifies meta listeners synchronously, so a handler is
|
|
135
|
+
* re-entered by its own write. This flag rejects that re-entry, and bounds any
|
|
136
|
+
* future divergence between the in-memory and the stored session to a single
|
|
137
|
+
* redundant write instead of an unbounded loop.
|
|
138
|
+
*
|
|
139
|
+
* Module scoped rather than per handler: more than one handler can be
|
|
140
|
+
* registered over the same storage, and per-handler flags would let them
|
|
141
|
+
* re-trigger one another through the echo notifications of their own writes.
|
|
142
|
+
*/
|
|
143
|
+
let isApplyingOwnUpdate = false;
|
|
85
144
|
export function getSessionMetaUpdateHandler({ fetchUserSession, storeUserSession, }) {
|
|
86
145
|
return function syncSessionIfChangedExternally(meta) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
146
|
+
var _a, _b, _c;
|
|
147
|
+
// Checked before work begins so the synchronous re-entry triggered by
|
|
148
|
+
// `setSession()` below is rejected while the flag is still set.
|
|
149
|
+
if (isApplyingOwnUpdate) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
// Compare in storable form, so keys that storage cannot hold do not read
|
|
153
|
+
// as a perpetual external change.
|
|
154
|
+
const session = meta.session && toStorableSessionMeta(meta.session);
|
|
155
|
+
const sessionFromSessionStorage = fetchUserSession();
|
|
156
|
+
let sessionId = session === null || session === void 0 ? void 0 : session.id;
|
|
157
|
+
const sessionAttributes = session === null || session === void 0 ? void 0 : session.attributes;
|
|
158
|
+
const sessionOverrides = session === null || session === void 0 ? void 0 : session.overrides;
|
|
159
|
+
const storedSessionMeta = sessionFromSessionStorage === null || sessionFromSessionStorage === void 0 ? void 0 : sessionFromSessionStorage.sessionMeta;
|
|
160
|
+
const storedSessionMetaOverrides = storedSessionMeta === null || storedSessionMeta === void 0 ? void 0 : storedSessionMeta.overrides;
|
|
161
|
+
const hasSessionOverridesChanged = sessionOverrides != null && !deepEqual(sessionOverrides, storedSessionMetaOverrides);
|
|
162
|
+
const hasSessionMetaChanged = session != null &&
|
|
163
|
+
(!deepEqual(sessionAttributes, storedSessionMeta === null || storedSessionMeta === void 0 ? void 0 : storedSessionMeta.attributes) ||
|
|
164
|
+
!deepEqual(sessionOverrides, storedSessionMetaOverrides));
|
|
165
|
+
const hasSessionIdChanged = !!session && sessionId !== (sessionFromSessionStorage === null || sessionFromSessionStorage === void 0 ? void 0 : sessionFromSessionStorage.sessionId);
|
|
166
|
+
if (hasSessionIdChanged || hasSessionMetaChanged) {
|
|
167
|
+
const storedPreviousSessionId = (_a = storedSessionMeta === null || storedSessionMeta === void 0 ? void 0 : storedSessionMeta.attributes) === null || _a === void 0 ? void 0 : _a['previousSession'];
|
|
168
|
+
const effectiveOverrides = sessionOverrides !== null && sessionOverrides !== void 0 ? sessionOverrides : storedSessionMetaOverrides;
|
|
169
|
+
const userSession = sessionFromSessionStorage != null && !hasSessionIdChanged
|
|
170
|
+
? Object.assign(Object.assign({}, sessionFromSessionStorage), { sessionMeta: toStorableSessionMeta(Object.assign({ id: sessionFromSessionStorage.sessionId, attributes: Object.assign(Object.assign(Object.assign(Object.assign({}, (_c = (_b = faro.config.sessionTracking) === null || _b === void 0 ? void 0 : _b.session) === null || _c === void 0 ? void 0 : _c.attributes), (sessionAttributes !== null && sessionAttributes !== void 0 ? sessionAttributes : storedSessionMeta === null || storedSessionMeta === void 0 ? void 0 : storedSessionMeta.attributes)), (storedPreviousSessionId == null ? {} : { previousSession: storedPreviousSessionId })), { isSampled: sessionFromSessionStorage.isSampled.toString() }) }, (isEmpty(effectiveOverrides) ? {} : { overrides: effectiveOverrides }))) }) : addSessionMetadataToNextSession(createUserSessionObject({ sessionId, isSampled: isSampled() }), sessionFromSessionStorage);
|
|
171
|
+
storeUserSession(userSession);
|
|
172
|
+
sendOverrideEvent(hasSessionOverridesChanged, sessionOverrides, storedSessionMetaOverrides);
|
|
173
|
+
isApplyingOwnUpdate = true;
|
|
174
|
+
try {
|
|
102
175
|
faro.api.setSession(userSession.sessionMeta);
|
|
103
176
|
}
|
|
104
|
-
|
|
177
|
+
finally {
|
|
178
|
+
isApplyingOwnUpdate = false;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
105
181
|
};
|
|
106
182
|
}
|
|
107
183
|
function sendOverrideEvent(hasSessionOverridesChanged, sessionOverrides = {}, storedSessionOverrides = {}) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionManagerUtils.js","sourceRoot":"","sources":["../../../../../src/instrumentations/session/sessionManager/sessionManagerUtils.ts"],"names":[],"mappings":"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","sourcesContent":["import { dateNow, deepEqual, EVENT_OVERRIDES_SERVICE_NAME, faro, genShortID, isEmpty } from '@grafana/faro-core';\nimport type { Meta, MetaOverrides } from '@grafana/faro-core';\n\nimport { isSampled } from './sampling';\nimport { MAX_SESSION_PERSISTENCE_TIME } from './sessionConstants';\nimport type { FaroUserSession } from './types';\n\nconst DEFAULT_SESSION_EXPIRATION_MS = 4 * 60 * 60 * 1000; // 4 hours (not in faro-core)\n\nfunction getSessionTimeouts(): {\n sessionExpirationTime: number;\n inactivityTimeout: number;\n} {\n const inactivityTimeout = faro.config?.sessionTracking?.maxSessionPersistenceTime ?? MAX_SESSION_PERSISTENCE_TIME;\n return {\n sessionExpirationTime: DEFAULT_SESSION_EXPIRATION_MS,\n inactivityTimeout,\n };\n}\n\ntype CreateUserSessionObjectParams = {\n sessionId?: string;\n started?: number;\n lastActivity?: number;\n isSampled?: boolean;\n};\n\nexport function createUserSessionObject({\n sessionId,\n started,\n lastActivity,\n isSampled: sampledValue = true,\n}: CreateUserSessionObjectParams = {}): FaroUserSession {\n const now = dateNow();\n\n const generateSessionId = faro.config?.sessionTracking?.generateSessionId;\n\n if (sessionId == null) {\n sessionId = typeof generateSessionId === 'function' ? generateSessionId() : genShortID();\n }\n\n return {\n sessionId,\n lastActivity: lastActivity ?? now,\n started: started ?? now,\n isSampled: sampledValue,\n };\n}\n\nexport function isUserSessionValid(session: FaroUserSession | null): boolean {\n if (session == null) {\n return false;\n }\n\n const { sessionExpirationTime, inactivityTimeout } = getSessionTimeouts();\n const now = dateNow();\n const lifetimeValid = now - session.started < sessionExpirationTime;\n\n if (!lifetimeValid) {\n return false;\n }\n\n const inactivityPeriodValid = now - session.lastActivity < inactivityTimeout;\n return inactivityPeriodValid;\n}\n\ntype GetUserSessionUpdaterParams = {\n storeUserSession: (session: FaroUserSession) => void | Promise<void>;\n fetchUserSession: () => FaroUserSession | null | Promise<FaroUserSession | null>;\n};\n\nexport function getUserSessionUpdater({\n fetchUserSession,\n storeUserSession,\n}: GetUserSessionUpdaterParams): () => Promise<void> {\n return async function updateSession(): Promise<void> {\n if (!fetchUserSession || !storeUserSession) {\n return;\n }\n\n const sessionFromStorage = await fetchUserSession();\n\n if (isUserSessionValid(sessionFromStorage)) {\n await storeUserSession({ ...sessionFromStorage!, lastActivity: dateNow() });\n } else {\n let newSession = addSessionMetadataToNextSession(\n createUserSessionObject({ isSampled: isSampled() }),\n sessionFromStorage\n );\n\n await storeUserSession(newSession);\n\n faro.api?.setSession(newSession.sessionMeta);\n faro.config.sessionTracking?.onSessionChange?.(sessionFromStorage?.sessionMeta ?? null, newSession.sessionMeta!);\n }\n };\n}\n\nexport function addSessionMetadataToNextSession(newSession: FaroUserSession, previousSession: FaroUserSession | null) {\n const sessionWithMeta: Required<FaroUserSession> = {\n ...newSession,\n sessionMeta: {\n id: newSession.sessionId,\n attributes: {\n ...faro.config.sessionTracking?.session?.attributes,\n ...(faro.metas.value.session?.attributes ?? {}),\n isSampled: newSession.isSampled.toString(),\n },\n },\n };\n\n const overrides = faro.metas.value.session?.overrides ?? previousSession?.sessionMeta?.overrides;\n if (!isEmpty(overrides)) {\n sessionWithMeta.sessionMeta.overrides = overrides;\n }\n\n const previousSessionId = previousSession?.sessionId;\n if (previousSessionId != null) {\n sessionWithMeta.sessionMeta.attributes!['previousSession'] = previousSessionId;\n }\n\n return sessionWithMeta;\n}\n\ntype GetUserSessionMetaUpdateHandlerParams = {\n storeUserSession: (session: FaroUserSession) => void | Promise<void>;\n fetchUserSession: () => FaroUserSession | null | Promise<FaroUserSession | null>;\n};\n\nexport function getSessionMetaUpdateHandler({\n fetchUserSession,\n storeUserSession,\n}: GetUserSessionMetaUpdateHandlerParams) {\n return async function syncSessionIfChangedExternally(meta: Meta) {\n const session = meta.session;\n const sessionFromSessionStorage = await fetchUserSession();\n\n let sessionId = session?.id;\n const sessionAttributes = session?.attributes;\n const sessionOverrides = session?.overrides;\n\n const storedSessionMeta = sessionFromSessionStorage?.sessionMeta;\n const storedSessionMetaOverrides = storedSessionMeta?.overrides;\n\n const hasSessionOverridesChanged = !!sessionOverrides && !deepEqual(sessionOverrides, storedSessionMetaOverrides);\n const hasAttributesChanged = !!sessionAttributes && !deepEqual(sessionAttributes, storedSessionMeta?.attributes);\n const hasSessionIdChanged = !!session && sessionId !== sessionFromSessionStorage?.sessionId;\n\n if (hasSessionIdChanged || hasAttributesChanged || hasSessionOverridesChanged) {\n const userSession = addSessionMetadataToNextSession(\n createUserSessionObject({ sessionId, isSampled: isSampled() }),\n sessionFromSessionStorage\n );\n\n await storeUserSession(userSession);\n sendOverrideEvent(hasSessionOverridesChanged, sessionOverrides, storedSessionMetaOverrides);\n faro.api.setSession(userSession.sessionMeta);\n }\n };\n}\n\nfunction sendOverrideEvent(\n hasSessionOverridesChanged: boolean,\n sessionOverrides: MetaOverrides = {},\n storedSessionOverrides: MetaOverrides = {}\n) {\n if (!hasSessionOverridesChanged) {\n return;\n }\n\n const serviceName = sessionOverrides.serviceName;\n const previousServiceName = storedSessionOverrides.serviceName ?? faro.metas.value.app?.name ?? '';\n\n if (serviceName && serviceName !== previousServiceName) {\n faro.api.pushEvent(EVENT_OVERRIDES_SERVICE_NAME, {\n serviceName,\n previousServiceName,\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sessionManagerUtils.js","sourceRoot":"","sources":["../../../../../src/instrumentations/session/sessionManager/sessionManagerUtils.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n dateNow,\n deepEqual,\n EVENT_OVERRIDES_SERVICE_NAME,\n faro,\n genShortID,\n isEmpty,\n stringifyExternalJson,\n} from '@grafana/faro-core';\nimport type { Meta, MetaOverrides, MetaSession } from '@grafana/faro-core';\n\nimport { SessionActivityKind } from '../sessionActivity';\n\nimport { isSampled } from './sampling';\nimport { MAX_SESSION_PERSISTENCE_TIME } from './sessionConstants';\nimport type { FaroUserSession } from './types';\n\nconst DEFAULT_SESSION_EXPIRATION_MS = 4 * 60 * 60 * 1000; // 4 hours (not in faro-core)\n\nfunction getSessionTimeouts(): {\n sessionExpirationTime: number;\n inactivityTimeout: number;\n} {\n const inactivityTimeout = faro.config?.sessionTracking?.maxSessionPersistenceTime ?? MAX_SESSION_PERSISTENCE_TIME;\n return {\n sessionExpirationTime: DEFAULT_SESSION_EXPIRATION_MS,\n inactivityTimeout,\n };\n}\n\ntype CreateUserSessionObjectParams = {\n sessionId?: string;\n started?: number;\n lastActivity?: number;\n isSampled?: boolean;\n};\n\nexport function createUserSessionObject({\n sessionId,\n started,\n lastActivity,\n isSampled: sampledValue = true,\n}: CreateUserSessionObjectParams = {}): FaroUserSession {\n const now = dateNow();\n\n const generateSessionId = faro.config?.sessionTracking?.generateSessionId;\n\n if (sessionId == null) {\n sessionId = typeof generateSessionId === 'function' ? generateSessionId() : genShortID();\n }\n\n return {\n sessionId,\n lastActivity: lastActivity ?? now,\n started: started ?? now,\n isSampled: sampledValue,\n };\n}\n\nexport function isUserSessionValid(session: FaroUserSession | null): boolean {\n if (session == null) {\n return false;\n }\n\n const { sessionExpirationTime, inactivityTimeout } = getSessionTimeouts();\n const now = dateNow();\n if (session.started > now || session.lastActivity > now) {\n return false;\n }\n\n const lifetimeValid = now - session.started < sessionExpirationTime;\n\n if (!lifetimeValid) {\n return false;\n }\n\n // The session expires at the boundary, matching cold-start record cleanup.\n const inactivityPeriodValid = now - session.lastActivity < inactivityTimeout;\n return inactivityPeriodValid;\n}\n\ntype GetUserSessionUpdaterParams = {\n storeUserSession: (session: FaroUserSession) => void;\n fetchUserSession: () => FaroUserSession | null;\n recordUserSessionActivity?: (session: FaroUserSession) => void;\n};\n\ntype GetUserSessionResetterParams = Pick<GetUserSessionUpdaterParams, 'fetchUserSession' | 'storeUserSession'>;\n\nfunction notifySessionChange(previousSession: FaroUserSession | null, newSession: FaroUserSession): void {\n const newSessionMeta = newSession.sessionMeta;\n if (newSessionMeta == null) {\n return;\n }\n\n try {\n faro.config.sessionTracking?.onSessionChange?.(previousSession?.sessionMeta ?? null, newSessionMeta);\n } catch (error) {\n faro.unpatchedConsole?.warn?.('The session change callback failed:', error);\n }\n}\n\nfunction createNextUserSession(previousSession: FaroUserSession | null): FaroUserSession {\n const nextSession = createUserSessionObject({ isSampled: isSampled() });\n\n if (previousSession != null && nextSession.sessionId === previousSession.sessionId) {\n faro.unpatchedConsole?.warn?.(\n 'The session ID generator returned the current session ID; using a generated fallback for the new session.'\n );\n nextSession.sessionId = genShortID();\n }\n\n return addSessionMetadataToNextSession(nextSession, previousSession);\n}\n\nfunction startNextUserSession(\n previousSession: FaroUserSession | null,\n storeUserSession: (session: FaroUserSession) => void\n): FaroUserSession {\n const nextSession = createNextUserSession(previousSession);\n\n storeUserSession(nextSession);\n // setSession synchronously emits session_start through the meta listener.\n // The transport hook then resumes and attributes the triggering item to\n // the newly stored session.\n faro.api?.setSession(nextSession.sessionMeta);\n notifySessionChange(previousSession, nextSession);\n\n return nextSession;\n}\n\nexport function getUserSessionResetter({\n fetchUserSession,\n storeUserSession,\n}: GetUserSessionResetterParams): () => FaroUserSession {\n return function resetSession(): FaroUserSession {\n return startNextUserSession(fetchUserSession(), storeUserSession);\n };\n}\n\nexport function getUserSessionUpdater({\n fetchUserSession,\n recordUserSessionActivity,\n storeUserSession,\n}: GetUserSessionUpdaterParams): (\n activity: SessionActivityKind,\n currentSession?: FaroUserSession | null\n) => FaroUserSession {\n const persistActivity = recordUserSessionActivity ?? storeUserSession;\n\n return function updateSession(\n activity: SessionActivityKind,\n currentSession?: FaroUserSession | null\n ): FaroUserSession {\n const sessionFromStorage = currentSession === undefined ? fetchUserSession() : currentSession;\n\n if (sessionFromStorage != null && isUserSessionValid(sessionFromStorage)) {\n if (activity === SessionActivityKind.Meaningful) {\n const lastActivity = dateNow();\n if (lastActivity === sessionFromStorage.lastActivity) {\n return sessionFromStorage;\n }\n\n const refreshedSession = { ...sessionFromStorage, lastActivity };\n persistActivity(refreshedSession);\n return refreshedSession;\n }\n\n return sessionFromStorage;\n }\n\n return startNextUserSession(sessionFromStorage, storeUserSession);\n };\n}\n\n/**\n * Persistent storage serializes sessions with `stringifyExternalJson`, which\n * drops keys whose value is `undefined`. A session meta carrying such a key\n * never compares `deepEqual` to its own stored copy, so the sync handler would\n * rewrite the session on every meta notification. Applying the same round-trip\n * in memory keeps the two sides comparable, for attributes and overrides alike.\n */\nexport function toStorableSessionMeta(sessionMeta: MetaSession): MetaSession {\n return JSON.parse(stringifyExternalJson(sessionMeta)) as MetaSession;\n}\n\nexport function addSessionMetadataToNextSession(newSession: FaroUserSession, previousSession: FaroUserSession | null) {\n const sessionWithMeta: Required<FaroUserSession> = {\n ...newSession,\n sessionMeta: {\n id: newSession.sessionId,\n attributes: {\n ...faro.config.sessionTracking?.session?.attributes,\n ...(faro.metas.value.session?.attributes ?? {}),\n isSampled: newSession.isSampled.toString(),\n },\n },\n };\n\n const overrides = faro.metas.value.session?.overrides ?? previousSession?.sessionMeta?.overrides;\n if (!isEmpty(overrides)) {\n sessionWithMeta.sessionMeta.overrides = overrides;\n }\n\n const previousSessionId = previousSession?.sessionId;\n if (previousSessionId != null && previousSessionId !== newSession.sessionId) {\n sessionWithMeta.sessionMeta.attributes!['previousSession'] = previousSessionId;\n }\n\n // Normalize to what storage can hold, so the meta this session propagates\n // stays comparable to its own stored copy.\n sessionWithMeta.sessionMeta = toStorableSessionMeta(sessionWithMeta.sessionMeta);\n\n return sessionWithMeta;\n}\n\ntype GetUserSessionMetaUpdateHandlerParams = {\n storeUserSession: (session: FaroUserSession) => void;\n fetchUserSession: () => FaroUserSession | null;\n};\n\n/**\n * Set only while a handler applies its own session update.\n *\n * `setSession()` notifies meta listeners synchronously, so a handler is\n * re-entered by its own write. This flag rejects that re-entry, and bounds any\n * future divergence between the in-memory and the stored session to a single\n * redundant write instead of an unbounded loop.\n *\n * Module scoped rather than per handler: more than one handler can be\n * registered over the same storage, and per-handler flags would let them\n * re-trigger one another through the echo notifications of their own writes.\n */\nlet isApplyingOwnUpdate = false;\n\nexport function getSessionMetaUpdateHandler({\n fetchUserSession,\n storeUserSession,\n}: GetUserSessionMetaUpdateHandlerParams) {\n return function syncSessionIfChangedExternally(meta: Meta): void {\n // Checked before work begins so the synchronous re-entry triggered by\n // `setSession()` below is rejected while the flag is still set.\n if (isApplyingOwnUpdate) {\n return;\n }\n\n // Compare in storable form, so keys that storage cannot hold do not read\n // as a perpetual external change.\n const session = meta.session && toStorableSessionMeta(meta.session);\n const sessionFromSessionStorage = fetchUserSession();\n\n let sessionId = session?.id;\n const sessionAttributes = session?.attributes;\n const sessionOverrides = session?.overrides;\n\n const storedSessionMeta = sessionFromSessionStorage?.sessionMeta;\n const storedSessionMetaOverrides = storedSessionMeta?.overrides;\n\n const hasSessionOverridesChanged =\n sessionOverrides != null && !deepEqual(sessionOverrides, storedSessionMetaOverrides);\n const hasSessionMetaChanged =\n session != null &&\n (!deepEqual(sessionAttributes, storedSessionMeta?.attributes) ||\n !deepEqual(sessionOverrides, storedSessionMetaOverrides));\n const hasSessionIdChanged = !!session && sessionId !== sessionFromSessionStorage?.sessionId;\n\n if (hasSessionIdChanged || hasSessionMetaChanged) {\n const storedPreviousSessionId = storedSessionMeta?.attributes?.['previousSession'];\n const effectiveOverrides = sessionOverrides ?? storedSessionMetaOverrides;\n const userSession =\n sessionFromSessionStorage != null && !hasSessionIdChanged\n ? {\n ...sessionFromSessionStorage,\n sessionMeta: toStorableSessionMeta({\n id: sessionFromSessionStorage.sessionId,\n attributes: {\n ...faro.config.sessionTracking?.session?.attributes,\n ...(sessionAttributes ?? storedSessionMeta?.attributes),\n ...(storedPreviousSessionId == null ? {} : { previousSession: storedPreviousSessionId }),\n isSampled: sessionFromSessionStorage.isSampled.toString(),\n },\n ...(isEmpty(effectiveOverrides) ? {} : { overrides: effectiveOverrides }),\n }),\n }\n : addSessionMetadataToNextSession(\n createUserSessionObject({ sessionId, isSampled: isSampled() }),\n sessionFromSessionStorage\n );\n\n storeUserSession(userSession);\n sendOverrideEvent(hasSessionOverridesChanged, sessionOverrides, storedSessionMetaOverrides);\n\n isApplyingOwnUpdate = true;\n try {\n faro.api.setSession(userSession.sessionMeta);\n } finally {\n isApplyingOwnUpdate = false;\n }\n }\n };\n}\n\nfunction sendOverrideEvent(\n hasSessionOverridesChanged: boolean,\n sessionOverrides: MetaOverrides = {},\n storedSessionOverrides: MetaOverrides = {}\n) {\n if (!hasSessionOverridesChanged) {\n return;\n }\n\n const serviceName = sessionOverrides.serviceName;\n const previousServiceName = storedSessionOverrides.serviceName ?? faro.metas.value.app?.name ?? '';\n\n if (serviceName && serviceName !== previousServiceName) {\n faro.api.pushEvent(EVENT_OVERRIDES_SERVICE_NAME, {\n serviceName,\n previousServiceName,\n });\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../src/instrumentations/session/sessionManager/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { MetaSession } from '@grafana/faro-core';\n\nimport type { MmkvPersistentSessionsManager } from './MmkvPersistentSessionsManager';\nimport type { VolatileSessionsManager } from './VolatileSessionManager';\n\nexport interface FaroUserSession {\n sessionId: string;\n lastActivity: number;\n started: number;\n isSampled: boolean;\n sessionMeta?: MetaSession;\n}\n\nexport type SessionManager = typeof VolatileSessionsManager | typeof MmkvPersistentSessionsManager;\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../src/instrumentations/session/sessionManager/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { MetaSession } from '@grafana/faro-core';\n\nimport type { SessionActivityKind } from '../sessionActivity';\n\nimport type { MmkvPersistentSessionsManager } from './MmkvPersistentSessionsManager';\nimport type { VolatileSessionsManager } from './VolatileSessionManager';\n\nexport interface FaroUserSession {\n sessionId: string;\n lastActivity: number;\n started: number;\n isSampled: boolean;\n sessionMeta?: MetaSession;\n}\n\nexport type SessionManager = typeof VolatileSessionsManager | typeof MmkvPersistentSessionsManager;\n\nexport interface SessionManagerInstance {\n checkSession(activity: SessionActivityKind, currentSession?: FaroUserSession | null): FaroUserSession;\n resetSession(): FaroUserSession;\n unpatch(): void;\n}\n"]}
|