From 08c124e13bfa1bbf55e6b636a62a60664c93ae3f Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 28 May 2024 09:25:24 +0200 Subject: [PATCH 1/6] Add super properties to posthog (plateformCode) --- vector/build.gradle | 2 +- .../vector/app/core/di/ActiveSessionHolder.kt | 12 +- .../features/analytics/AnalyticsTracker.kt | 7 ++ .../analytics/impl/DefaultVectorAnalytics.kt | 36 +++++- .../impl/DefaultVectorAnalyticsTest.kt | 112 ++++++++++++++++++ 5 files changed, 164 insertions(+), 5 deletions(-) diff --git a/vector/build.gradle b/vector/build.gradle index 368fa217db..2518e89e32 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -160,7 +160,7 @@ dependencies { api 'com.facebook.stetho:stetho:1.6.0' // Analytics - api 'com.github.matrix-org:matrix-analytics-events:0.15.0' + api 'com.github.matrix-org:matrix-analytics-events:0.22.0' api libs.google.phonenumber diff --git a/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt b/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt index 5523c84994..1f4e4261f8 100644 --- a/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt +++ b/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt @@ -22,7 +22,8 @@ import im.vector.app.core.dispatchers.CoroutineDispatchers import im.vector.app.core.pushers.UnregisterUnifiedPushUseCase import im.vector.app.core.services.GuardServiceStarter import im.vector.app.core.session.ConfigureAndStartSessionUseCase -import im.vector.app.features.analytics.DecryptionFailureTracker +import im.vector.app.features.analytics.VectorAnalytics +import im.vector.app.features.analytics.plan.SuperProperties import im.vector.app.features.call.webrtc.WebRtcCallManager import im.vector.app.features.crypto.keysrequest.KeyRequestHandler import im.vector.app.features.crypto.verification.IncomingVerificationRequestHandler @@ -57,7 +58,7 @@ class ActiveSessionHolder @Inject constructor( private val unregisterUnifiedPushUseCase: UnregisterUnifiedPushUseCase, private val applicationCoroutineScope: CoroutineScope, private val coroutineDispatchers: CoroutineDispatchers, - private val decryptionFailureTracker: DecryptionFailureTracker, + private val vectorAnalytics: VectorAnalytics, ) { private var activeSessionReference: AtomicReference = AtomicReference() @@ -74,6 +75,13 @@ class ActiveSessionHolder @Inject constructor( session.callSignalingService().addCallListener(callManager) imageManager.onSessionStarted(session) guardServiceStarter.start() + vectorAnalytics.updateSuperProperties( + SuperProperties( + platformCodeName = SuperProperties.PlatformCodeName.EA, + cryptoSDK = SuperProperties.CryptoSDK.Rust, + cryptoSDKVersion = session.cryptoService().getCryptoVersion(applicationContext, false) + ) + ) } suspend fun clearActiveSession() { diff --git a/vector/src/main/java/im/vector/app/features/analytics/AnalyticsTracker.kt b/vector/src/main/java/im/vector/app/features/analytics/AnalyticsTracker.kt index 871782e473..d233900d2c 100644 --- a/vector/src/main/java/im/vector/app/features/analytics/AnalyticsTracker.kt +++ b/vector/src/main/java/im/vector/app/features/analytics/AnalyticsTracker.kt @@ -18,6 +18,7 @@ package im.vector.app.features.analytics import im.vector.app.features.analytics.itf.VectorAnalyticsEvent import im.vector.app.features.analytics.itf.VectorAnalyticsScreen +import im.vector.app.features.analytics.plan.SuperProperties import im.vector.app.features.analytics.plan.UserProperties interface AnalyticsTracker { @@ -35,4 +36,10 @@ interface AnalyticsTracker { * Update user specific properties. */ fun updateUserProperties(userProperties: UserProperties) + + /** + * Update the super properties. + * Super properties are added to any tracked event automatically. + */ + fun updateSuperProperties(updatedProperties: SuperProperties) } diff --git a/vector/src/main/java/im/vector/app/features/analytics/impl/DefaultVectorAnalytics.kt b/vector/src/main/java/im/vector/app/features/analytics/impl/DefaultVectorAnalytics.kt index 8520a40ca2..552af1b524 100644 --- a/vector/src/main/java/im/vector/app/features/analytics/impl/DefaultVectorAnalytics.kt +++ b/vector/src/main/java/im/vector/app/features/analytics/impl/DefaultVectorAnalytics.kt @@ -23,6 +23,7 @@ import im.vector.app.features.analytics.VectorAnalytics import im.vector.app.features.analytics.itf.VectorAnalyticsEvent import im.vector.app.features.analytics.itf.VectorAnalyticsScreen import im.vector.app.features.analytics.log.analyticsTag +import im.vector.app.features.analytics.plan.SuperProperties import im.vector.app.features.analytics.plan.UserProperties import im.vector.app.features.analytics.store.AnalyticsStore import kotlinx.coroutines.CoroutineScope @@ -63,6 +64,8 @@ class DefaultVectorAnalytics @Inject constructor( // Cache for the properties to send private var pendingUserProperties: UserProperties? = null + private var superProperties: SuperProperties? = null + override fun init() { observeUserConsent() observeAnalyticsId() @@ -173,7 +176,7 @@ class DefaultVectorAnalytics @Inject constructor( ?.capture( event.getName(), analyticsId, - event.getProperties()?.toPostHogProperties() + event.getProperties()?.toPostHogProperties().orEmpty().withSuperProperties() ) } @@ -181,7 +184,7 @@ class DefaultVectorAnalytics @Inject constructor( Timber.tag(analyticsTag.value).d("screen($screen)") posthog ?.takeIf { userConsent == true } - ?.screen(screen.getName(), screen.getProperties()?.toPostHogProperties()) + ?.screen(screen.getName(), screen.getProperties()?.toPostHogProperties().orEmpty().withSuperProperties()) } override fun updateUserProperties(userProperties: UserProperties) { @@ -226,9 +229,38 @@ class DefaultVectorAnalytics @Inject constructor( return nonNulls } + /** + * Adds super properties to the actual property set. + * If a property of the same name is already on the reported event it will not be overwritten. + */ + private fun Map.withSuperProperties(): Map { + val withSuperProperties = this.toMutableMap() + val superProperties = this@DefaultVectorAnalytics.superProperties?.getProperties() + superProperties?.forEach { + if (!withSuperProperties.containsKey(it.key)) { + withSuperProperties[it.key] = it.value + } + } + return withSuperProperties + } + override fun trackError(throwable: Throwable) { sentryAnalytics .takeIf { userConsent == true } ?.trackError(throwable) } + + override fun updateSuperProperties(updatedProperties: SuperProperties) { + if (this.superProperties == null) { + this.superProperties = updatedProperties + return + } + + this.superProperties = SuperProperties( + platformCodeName = updatedProperties.platformCodeName ?: this.superProperties?.platformCodeName, + cryptoSDK = updatedProperties.cryptoSDK ?: this.superProperties?.cryptoSDK, + appPlatform = updatedProperties.appPlatform ?: this.superProperties?.appPlatform, + cryptoSDKVersion = updatedProperties.cryptoSDKVersion ?: superProperties?.cryptoSDKVersion + ) + } } diff --git a/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt b/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt index ea8beaa86c..ebf1d21ce2 100644 --- a/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt +++ b/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt @@ -16,6 +16,7 @@ package im.vector.app.features.analytics.impl +import im.vector.app.features.analytics.plan.SuperProperties import im.vector.app.test.fakes.FakeAnalyticsStore import im.vector.app.test.fakes.FakeLateInitUserPropertiesFactory import im.vector.app.test.fakes.FakePostHog @@ -174,6 +175,117 @@ class DefaultVectorAnalyticsTest { fakeSentryAnalytics.verifyNoErrorTracking() } + @Test + fun `Super properties should be added to all captured events`() = runTest { + fakeAnalyticsStore.givenUserContent(consent = true) + + val updatedProperties = SuperProperties( + platformCodeName = SuperProperties.PlatformCodeName.EA, + cryptoSDKVersion = "0.0", + cryptoSDK = SuperProperties.CryptoSDK.Rust + ) + + defaultVectorAnalytics.updateSuperProperties(updatedProperties) + + val fakeEvent = aVectorAnalyticsEvent("THE_NAME", mutableMapOf("foo" to "bar")) + defaultVectorAnalytics.capture(fakeEvent) + + fakePostHog.verifyEventTracked( + "THE_NAME", + fakeEvent.getProperties().clearNulls()?.toMutableMap()?.apply { + updatedProperties.getProperties()?.let { putAll(it) } + } + ) + + // Check with a screen event + val fakeScreen = aVectorAnalyticsScreen("Screen", mutableMapOf("foo" to "bar")) + defaultVectorAnalytics.screen(fakeScreen) + + fakePostHog.verifyScreenTracked( + "Screen", + fakeScreen.getProperties().clearNulls()?.toMutableMap()?.apply { + updatedProperties.getProperties()?.let { putAll(it) } + } + ) + } + + @Test + fun `Super properties can be updated`() = runTest { + fakeAnalyticsStore.givenUserContent(consent = true) + + val superProperties = SuperProperties( + platformCodeName = SuperProperties.PlatformCodeName.EA, + cryptoSDKVersion = "0.0", + cryptoSDK = SuperProperties.CryptoSDK.Rust + ) + + defaultVectorAnalytics.updateSuperProperties(superProperties) + + val fakeEvent = aVectorAnalyticsEvent("THE_NAME", mutableMapOf("foo" to "bar")) + defaultVectorAnalytics.capture(fakeEvent) + + fakePostHog.verifyEventTracked( + "THE_NAME", + fakeEvent.getProperties().clearNulls()?.toMutableMap()?.apply { + superProperties.getProperties()?.let { putAll(it) } + } + ) + + val superPropertiesUpdate = superProperties.copy(cryptoSDKVersion = "1.0") + defaultVectorAnalytics.updateSuperProperties(superPropertiesUpdate) + + defaultVectorAnalytics.capture(fakeEvent) + + fakePostHog.verifyEventTracked( + "THE_NAME", + fakeEvent.getProperties().clearNulls()?.toMutableMap()?.apply { + superPropertiesUpdate.getProperties()?.let { putAll(it) } + } + ) + } + + @Test + fun `Super properties should not override event property`() = runTest { + fakeAnalyticsStore.givenUserContent(consent = true) + + val superProperties = SuperProperties( + cryptoSDKVersion = "0.0", + ) + + defaultVectorAnalytics.updateSuperProperties(superProperties) + + val fakeEvent = aVectorAnalyticsEvent("THE_NAME", mutableMapOf("cryptoSDKVersion" to "XXX")) + defaultVectorAnalytics.capture(fakeEvent) + + fakePostHog.verifyEventTracked( + "THE_NAME", + mapOf( + "cryptoSDKVersion" to "XXX" + ) + ) + } + + @Test + fun `Super properties should be added to event with no properties`() = runTest { + fakeAnalyticsStore.givenUserContent(consent = true) + + val superProperties = SuperProperties( + cryptoSDKVersion = "0.0", + ) + + defaultVectorAnalytics.updateSuperProperties(superProperties) + + val fakeEvent = aVectorAnalyticsEvent("THE_NAME", null) + defaultVectorAnalytics.capture(fakeEvent) + + fakePostHog.verifyEventTracked( + "THE_NAME", + mapOf( + "cryptoSDKVersion" to "0.0" + ) + ) + } + private fun Map?.clearNulls(): Map? { if (this == null) return null From ccd6eed45abd6388ea86d9ef24e64d880aa7f1cc Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 28 May 2024 09:27:43 +0200 Subject: [PATCH 2/6] Add changelog --- changelog.d/8839.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/8839.misc diff --git a/changelog.d/8839.misc b/changelog.d/8839.misc new file mode 100644 index 0000000000..00650ede9a --- /dev/null +++ b/changelog.d/8839.misc @@ -0,0 +1 @@ +Posthog | report platform code for EA From 09c68f34214626a737edf756b2def5ab501aeb5b Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 29 May 2024 17:38:36 +0200 Subject: [PATCH 3/6] Remove unused context in crypto service getCryptoVersion --- .../org/matrix/android/sdk/api/session/crypto/CryptoService.kt | 3 +-- .../matrix/android/sdk/internal/crypto/RustCryptoService.kt | 3 +-- .../main/java/im/vector/app/features/rageshake/BugReporter.kt | 2 +- .../app/features/settings/VectorSettingsHelpAboutFragment.kt | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt index 3ed6dd1450..ba6b1f23b1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt @@ -16,7 +16,6 @@ package org.matrix.android.sdk.api.session.crypto -import android.content.Context import androidx.annotation.Size import androidx.lifecycle.LiveData import androidx.paging.PagedList @@ -61,7 +60,7 @@ interface CryptoService { suspend fun deleteDevices(@Size(min = 1) deviceIds: List, userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor) - fun getCryptoVersion(context: Context, longFormat: Boolean): String + fun getCryptoVersion(longFormat: Boolean): String fun isCryptoEnabled(): Boolean diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt index 5ba74f705b..ada434ddca 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt @@ -16,7 +16,6 @@ package org.matrix.android.sdk.internal.crypto -import android.content.Context import androidx.lifecycle.LiveData import androidx.lifecycle.map import androidx.paging.PagedList @@ -184,7 +183,7 @@ internal class RustCryptoService @Inject constructor( deleteDevices(listOf(deviceId), userInteractiveAuthInterceptor) } - override fun getCryptoVersion(context: Context, longFormat: Boolean): String { + override fun getCryptoVersion(longFormat: Boolean): String { val version = org.matrix.rustcomponents.sdk.crypto.version() val gitHash = org.matrix.rustcomponents.sdk.crypto.versionInfo().gitSha val vodozemac = org.matrix.rustcomponents.sdk.crypto.vodozemacVersion() diff --git a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt index f1b01b2909..f89b6749a3 100755 --- a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt @@ -265,7 +265,7 @@ class BugReporter @Inject constructor( activeSessionHolder.getSafeActiveSession()?.let { session -> userId = session.myUserId deviceId = session.sessionParams.deviceId - olmVersion = session.cryptoService().getCryptoVersion(context, true) + olmVersion = session.cryptoService().getCryptoVersion(true) } if (!mIsCancelled) { diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt index 7777602166..47db90466e 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt @@ -96,7 +96,7 @@ class VectorSettingsHelpAboutFragment : // olm version findPreference(VectorPreferences.SETTINGS_CRYPTO_VERSION_PREFERENCE_KEY)!! - .summary = session.cryptoService().getCryptoVersion(requireContext(), true) + .summary = session.cryptoService().getCryptoVersion(true) } companion object { From a363e392b49a9e2fbb9b628696e4f6aebff01e02 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 29 May 2024 17:39:16 +0200 Subject: [PATCH 4/6] Update to analytics events 0.23.0 and refactor --- .../java/im/vector/app/VectorApplication.kt | 7 +++ vector/build.gradle | 2 +- .../vector/app/core/di/ActiveSessionHolder.kt | 10 ----- .../impl/AutoSuperPropertiesFlowProvider.kt | 43 +++++++++++++++++++ .../analytics/impl/DefaultVectorAnalytics.kt | 34 ++++++--------- .../impl/DefaultVectorAnalyticsTest.kt | 13 ++++-- 6 files changed, 75 insertions(+), 34 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/analytics/impl/AutoSuperPropertiesFlowProvider.kt diff --git a/vector-app/src/main/java/im/vector/app/VectorApplication.kt b/vector-app/src/main/java/im/vector/app/VectorApplication.kt index fe4cc3311b..0f83f57d01 100644 --- a/vector-app/src/main/java/im/vector/app/VectorApplication.kt +++ b/vector-app/src/main/java/im/vector/app/VectorApplication.kt @@ -53,6 +53,7 @@ import im.vector.app.core.pushers.FcmHelper import im.vector.app.core.resources.BuildMeta import im.vector.app.features.analytics.DecryptionFailureTracker import im.vector.app.features.analytics.VectorAnalytics +import im.vector.app.features.analytics.plan.SuperProperties import im.vector.app.features.call.webrtc.WebRtcCallManager import im.vector.app.features.configuration.VectorConfiguration import im.vector.app.features.invite.InvitesAcceptor @@ -130,6 +131,12 @@ class VectorApplication : appContext = this flipperProxy.init(matrix) vectorAnalytics.init() + vectorAnalytics.updateSuperProperties( + SuperProperties( + appPlatform = SuperProperties.AppPlatform.EA, + cryptoSDK = SuperProperties.CryptoSDK.Rust, + ) + ) invitesAcceptor.initialize() autoRageShaker.initialize() decryptionFailureTracker.start() diff --git a/vector/build.gradle b/vector/build.gradle index 2518e89e32..dc8eb0641e 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -160,7 +160,7 @@ dependencies { api 'com.facebook.stetho:stetho:1.6.0' // Analytics - api 'com.github.matrix-org:matrix-analytics-events:0.22.0' + api 'com.github.matrix-org:matrix-analytics-events:0.23.0' api libs.google.phonenumber diff --git a/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt b/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt index 1f4e4261f8..f3d775b39f 100644 --- a/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt +++ b/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt @@ -22,8 +22,6 @@ import im.vector.app.core.dispatchers.CoroutineDispatchers import im.vector.app.core.pushers.UnregisterUnifiedPushUseCase import im.vector.app.core.services.GuardServiceStarter import im.vector.app.core.session.ConfigureAndStartSessionUseCase -import im.vector.app.features.analytics.VectorAnalytics -import im.vector.app.features.analytics.plan.SuperProperties import im.vector.app.features.call.webrtc.WebRtcCallManager import im.vector.app.features.crypto.keysrequest.KeyRequestHandler import im.vector.app.features.crypto.verification.IncomingVerificationRequestHandler @@ -58,7 +56,6 @@ class ActiveSessionHolder @Inject constructor( private val unregisterUnifiedPushUseCase: UnregisterUnifiedPushUseCase, private val applicationCoroutineScope: CoroutineScope, private val coroutineDispatchers: CoroutineDispatchers, - private val vectorAnalytics: VectorAnalytics, ) { private var activeSessionReference: AtomicReference = AtomicReference() @@ -75,13 +72,6 @@ class ActiveSessionHolder @Inject constructor( session.callSignalingService().addCallListener(callManager) imageManager.onSessionStarted(session) guardServiceStarter.start() - vectorAnalytics.updateSuperProperties( - SuperProperties( - platformCodeName = SuperProperties.PlatformCodeName.EA, - cryptoSDK = SuperProperties.CryptoSDK.Rust, - cryptoSDKVersion = session.cryptoService().getCryptoVersion(applicationContext, false) - ) - ) } suspend fun clearActiveSession() { diff --git a/vector/src/main/java/im/vector/app/features/analytics/impl/AutoSuperPropertiesFlowProvider.kt b/vector/src/main/java/im/vector/app/features/analytics/impl/AutoSuperPropertiesFlowProvider.kt new file mode 100644 index 0000000000..76763e3bab --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/analytics/impl/AutoSuperPropertiesFlowProvider.kt @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.analytics.impl + +import im.vector.app.ActiveSessionDataSource +import im.vector.app.features.analytics.plan.SuperProperties +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.map +import javax.inject.Inject + +/** + * Gathers the super properties that are static to this platform or + * that can be automatically resolved from the current session. + */ +class AutoSuperPropertiesFlowProvider @Inject constructor( + activeSessionDataSource: ActiveSessionDataSource, +) { + + val superPropertiesFlow: Flow = activeSessionDataSource.stream() + .map { session -> + SuperProperties( + appPlatform = SuperProperties.AppPlatform.EA, + cryptoSDK = SuperProperties.CryptoSDK.Rust, + cryptoSDKVersion = session.getOrNull()?.cryptoService()?.getCryptoVersion(false) + ) + } + .distinctUntilChanged() +} diff --git a/vector/src/main/java/im/vector/app/features/analytics/impl/DefaultVectorAnalytics.kt b/vector/src/main/java/im/vector/app/features/analytics/impl/DefaultVectorAnalytics.kt index 552af1b524..baefe18cf5 100644 --- a/vector/src/main/java/im/vector/app/features/analytics/impl/DefaultVectorAnalytics.kt +++ b/vector/src/main/java/im/vector/app/features/analytics/impl/DefaultVectorAnalytics.kt @@ -42,6 +42,7 @@ class DefaultVectorAnalytics @Inject constructor( private val analyticsConfig: AnalyticsConfig, private val analyticsStore: AnalyticsStore, private val lateInitUserPropertiesFactory: LateInitUserPropertiesFactory, + private val autoSuperPropertiesFlowProvider: AutoSuperPropertiesFlowProvider, @NamedGlobalScope private val globalScope: CoroutineScope ) : VectorAnalytics { @@ -69,6 +70,7 @@ class DefaultVectorAnalytics @Inject constructor( override fun init() { observeUserConsent() observeAnalyticsId() + observeAutoSuperProperties() } override fun getUserConsent(): Flow { @@ -116,6 +118,12 @@ class DefaultVectorAnalytics @Inject constructor( .launchIn(globalScope) } + private fun observeAutoSuperProperties() { + autoSuperPropertiesFlowProvider.superPropertiesFlow.onEach { + updateSuperProperties(it) + }.launchIn(globalScope) + } + private suspend fun identifyPostHog() { val id = analyticsId ?: return if (!userConsent.orFalse()) return @@ -171,20 +179,14 @@ class DefaultVectorAnalytics @Inject constructor( override fun capture(event: VectorAnalyticsEvent) { Timber.tag(analyticsTag.value).d("capture($event)") - posthog - ?.takeIf { userConsent == true } - ?.capture( - event.getName(), - analyticsId, - event.getProperties()?.toPostHogProperties().orEmpty().withSuperProperties() + posthog?.takeIf { userConsent == true }?.capture( + event.getName(), analyticsId, event.getProperties()?.toPostHogProperties().orEmpty().withSuperProperties() ) } override fun screen(screen: VectorAnalyticsScreen) { Timber.tag(analyticsTag.value).d("screen($screen)") - posthog - ?.takeIf { userConsent == true } - ?.screen(screen.getName(), screen.getProperties()?.toPostHogProperties().orEmpty().withSuperProperties()) + posthog?.takeIf { userConsent == true }?.screen(screen.getName(), screen.getProperties()?.toPostHogProperties().orEmpty().withSuperProperties()) } override fun updateUserProperties(userProperties: UserProperties) { @@ -198,9 +200,7 @@ class DefaultVectorAnalytics @Inject constructor( private fun doUpdateUserProperties(userProperties: UserProperties) { // we need a distinct id to set user properties val distinctId = analyticsId ?: return - posthog - ?.takeIf { userConsent == true } - ?.identify(distinctId, userProperties.getProperties()) + posthog?.takeIf { userConsent == true }?.identify(distinctId, userProperties.getProperties()) } private fun Map?.toPostHogProperties(): Map? { @@ -233,7 +233,7 @@ class DefaultVectorAnalytics @Inject constructor( * Adds super properties to the actual property set. * If a property of the same name is already on the reported event it will not be overwritten. */ - private fun Map.withSuperProperties(): Map { + private fun Map.withSuperProperties(): Map? { val withSuperProperties = this.toMutableMap() val superProperties = this@DefaultVectorAnalytics.superProperties?.getProperties() superProperties?.forEach { @@ -241,7 +241,7 @@ class DefaultVectorAnalytics @Inject constructor( withSuperProperties[it.key] = it.value } } - return withSuperProperties + return withSuperProperties.takeIf { it.isEmpty().not() } } override fun trackError(throwable: Throwable) { @@ -251,13 +251,7 @@ class DefaultVectorAnalytics @Inject constructor( } override fun updateSuperProperties(updatedProperties: SuperProperties) { - if (this.superProperties == null) { - this.superProperties = updatedProperties - return - } - this.superProperties = SuperProperties( - platformCodeName = updatedProperties.platformCodeName ?: this.superProperties?.platformCodeName, cryptoSDK = updatedProperties.cryptoSDK ?: this.superProperties?.cryptoSDK, appPlatform = updatedProperties.appPlatform ?: this.superProperties?.appPlatform, cryptoSDKVersion = updatedProperties.cryptoSDKVersion ?: superProperties?.cryptoSDKVersion diff --git a/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt b/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt index ebf1d21ce2..70c97c234f 100644 --- a/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt +++ b/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt @@ -26,9 +26,12 @@ import im.vector.app.test.fixtures.AnalyticsConfigFixture.anAnalyticsConfig import im.vector.app.test.fixtures.aUserProperties import im.vector.app.test.fixtures.aVectorAnalyticsEvent import im.vector.app.test.fixtures.aVectorAnalyticsScreen +import io.mockk.every +import io.mockk.mockk import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test @@ -45,6 +48,9 @@ class DefaultVectorAnalyticsTest { private val fakeAnalyticsStore = FakeAnalyticsStore() private val fakeLateInitUserPropertiesFactory = FakeLateInitUserPropertiesFactory() private val fakeSentryAnalytics = FakeSentryAnalytics() + private val mockAutoSuperPropertiesFlowProvider = mockk().also { + every { it.superPropertiesFlow } returns flowOf(SuperProperties()) + } private val defaultVectorAnalytics = DefaultVectorAnalytics( postHogFactory = FakePostHogFactory(fakePostHog.instance).instance, @@ -52,7 +58,8 @@ class DefaultVectorAnalyticsTest { analyticsStore = fakeAnalyticsStore.instance, globalScope = CoroutineScope(Dispatchers.Unconfined), analyticsConfig = anAnalyticsConfig(isEnabled = true), - lateInitUserPropertiesFactory = fakeLateInitUserPropertiesFactory.instance + lateInitUserPropertiesFactory = fakeLateInitUserPropertiesFactory.instance, + autoSuperPropertiesFlowProvider = mockAutoSuperPropertiesFlowProvider, ) @Before @@ -180,7 +187,7 @@ class DefaultVectorAnalyticsTest { fakeAnalyticsStore.givenUserContent(consent = true) val updatedProperties = SuperProperties( - platformCodeName = SuperProperties.PlatformCodeName.EA, + appPlatform = SuperProperties.AppPlatform.EA, cryptoSDKVersion = "0.0", cryptoSDK = SuperProperties.CryptoSDK.Rust ) @@ -214,7 +221,7 @@ class DefaultVectorAnalyticsTest { fakeAnalyticsStore.givenUserContent(consent = true) val superProperties = SuperProperties( - platformCodeName = SuperProperties.PlatformCodeName.EA, + appPlatform = SuperProperties.AppPlatform.EA, cryptoSDKVersion = "0.0", cryptoSDK = SuperProperties.CryptoSDK.Rust ) From 28fa4ab784e63bb2ef18ab08527baf9244e783ac Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 29 May 2024 17:48:38 +0200 Subject: [PATCH 5/6] improve tests --- .../impl/DefaultVectorAnalyticsTest.kt | 44 ++++++++++++++++--- .../FakeAutoSuperPropertiesFlowProvider.kt | 36 +++++++++++++++ 2 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeAutoSuperPropertiesFlowProvider.kt diff --git a/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt b/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt index 70c97c234f..3b0d13c945 100644 --- a/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt +++ b/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt @@ -18,6 +18,7 @@ package im.vector.app.features.analytics.impl import im.vector.app.features.analytics.plan.SuperProperties import im.vector.app.test.fakes.FakeAnalyticsStore +import im.vector.app.test.fakes.FakeAutoSuperPropertiesFlowProvider import im.vector.app.test.fakes.FakeLateInitUserPropertiesFactory import im.vector.app.test.fakes.FakePostHog import im.vector.app.test.fakes.FakePostHogFactory @@ -26,12 +27,9 @@ import im.vector.app.test.fixtures.AnalyticsConfigFixture.anAnalyticsConfig import im.vector.app.test.fixtures.aUserProperties import im.vector.app.test.fixtures.aVectorAnalyticsEvent import im.vector.app.test.fixtures.aVectorAnalyticsScreen -import io.mockk.every -import io.mockk.mockk import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test @@ -48,9 +46,7 @@ class DefaultVectorAnalyticsTest { private val fakeAnalyticsStore = FakeAnalyticsStore() private val fakeLateInitUserPropertiesFactory = FakeLateInitUserPropertiesFactory() private val fakeSentryAnalytics = FakeSentryAnalytics() - private val mockAutoSuperPropertiesFlowProvider = mockk().also { - every { it.superPropertiesFlow } returns flowOf(SuperProperties()) - } + private val fakeAutoSuperPropertiesFlowProvider = FakeAutoSuperPropertiesFlowProvider() private val defaultVectorAnalytics = DefaultVectorAnalytics( postHogFactory = FakePostHogFactory(fakePostHog.instance).instance, @@ -59,7 +55,7 @@ class DefaultVectorAnalyticsTest { globalScope = CoroutineScope(Dispatchers.Unconfined), analyticsConfig = anAnalyticsConfig(isEnabled = true), lateInitUserPropertiesFactory = fakeLateInitUserPropertiesFactory.instance, - autoSuperPropertiesFlowProvider = mockAutoSuperPropertiesFlowProvider, + autoSuperPropertiesFlowProvider = fakeAutoSuperPropertiesFlowProvider.instance, ) @Before @@ -293,6 +289,40 @@ class DefaultVectorAnalyticsTest { ) } + @Test + fun `Update super properties from flow`() = runTest { + fakeAnalyticsStore.givenUserContent(consent = true) + + fakeAutoSuperPropertiesFlowProvider.postSuperProperty( + SuperProperties( + cryptoSDKVersion = "0" + ) + ) + + val fakeEvent = aVectorAnalyticsEvent("THE_NAME", null) + defaultVectorAnalytics.capture(fakeEvent) + + fakePostHog.verifyEventTracked( + "THE_NAME", + mapOf( + "cryptoSDKVersion" to "0" + ) + ) + + fakeAutoSuperPropertiesFlowProvider.postSuperProperty(SuperProperties( + cryptoSDKVersion = "1" + )) + + defaultVectorAnalytics.capture(fakeEvent) + + fakePostHog.verifyEventTracked( + "THE_NAME", + mapOf( + "cryptoSDKVersion" to "1" + ) + ) + } + private fun Map?.clearNulls(): Map? { if (this == null) return null diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeAutoSuperPropertiesFlowProvider.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeAutoSuperPropertiesFlowProvider.kt new file mode 100644 index 0000000000..eff184298e --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeAutoSuperPropertiesFlowProvider.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.test.fakes + +import im.vector.app.features.analytics.impl.AutoSuperPropertiesFlowProvider +import im.vector.app.features.analytics.plan.SuperProperties +import io.mockk.every +import io.mockk.mockk +import kotlinx.coroutines.flow.MutableSharedFlow + +class FakeAutoSuperPropertiesFlowProvider { + + val flow = MutableSharedFlow() + + val instance = mockk().also { + every { it.superPropertiesFlow } returns flow + } + + suspend fun postSuperProperty(properties: SuperProperties) { + flow.emit(properties) + } +} From 7e41d731f6949191fd9a00c794b7b18f5be293a5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 30 May 2024 13:10:36 +0200 Subject: [PATCH 6/6] Move getCryptoVersion from CryptoService to Matrix companion, it does not need a session to get the value. This simplify a lot accessing this data. --- .../java/org/matrix/android/sdk/api/Matrix.kt | 7 +++ .../sdk/api/session/crypto/CryptoService.kt | 2 - .../sdk/internal/crypto/RustCryptoService.kt | 7 --- .../java/im/vector/app/VectorApplication.kt | 1 + .../impl/AutoSuperPropertiesFlowProvider.kt | 43 ------------------- .../analytics/impl/DefaultVectorAnalytics.kt | 8 ---- .../app/features/rageshake/BugReporter.kt | 2 +- .../VectorSettingsHelpAboutFragment.kt | 2 +- .../impl/DefaultVectorAnalyticsTest.kt | 37 ---------------- .../FakeAutoSuperPropertiesFlowProvider.kt | 36 ---------------- 10 files changed, 10 insertions(+), 135 deletions(-) delete mode 100644 vector/src/main/java/im/vector/app/features/analytics/impl/AutoSuperPropertiesFlowProvider.kt delete mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeAutoSuperPropertiesFlowProvider.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt index 8893229a76..b9780b8021 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt @@ -147,5 +147,12 @@ class Matrix(context: Context, matrixConfiguration: MatrixConfiguration) { fun getSdkVersion(): String { return BuildConfig.SDK_VERSION + " (" + BuildConfig.GIT_SDK_REVISION + ")" } + + fun getCryptoVersion(longFormat: Boolean): String { + val version = org.matrix.rustcomponents.sdk.crypto.version() + val gitHash = org.matrix.rustcomponents.sdk.crypto.versionInfo().gitSha + val vodozemac = org.matrix.rustcomponents.sdk.crypto.vodozemacVersion() + return if (longFormat) "Rust SDK $version ($gitHash), Vodozemac $vodozemac" else version + } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt index ba6b1f23b1..fa1208059a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt @@ -60,8 +60,6 @@ interface CryptoService { suspend fun deleteDevices(@Size(min = 1) deviceIds: List, userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor) - fun getCryptoVersion(longFormat: Boolean): String - fun isCryptoEnabled(): Boolean fun isRoomBlacklistUnverifiedDevices(roomId: String?): Boolean diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt index ada434ddca..a6e4efd875 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt @@ -183,13 +183,6 @@ internal class RustCryptoService @Inject constructor( deleteDevices(listOf(deviceId), userInteractiveAuthInterceptor) } - override fun getCryptoVersion(longFormat: Boolean): String { - val version = org.matrix.rustcomponents.sdk.crypto.version() - val gitHash = org.matrix.rustcomponents.sdk.crypto.versionInfo().gitSha - val vodozemac = org.matrix.rustcomponents.sdk.crypto.vodozemacVersion() - return if (longFormat) "Rust SDK $version ($gitHash), Vodozemac $vodozemac" else version - } - override suspend fun getMyCryptoDevice(): CryptoDeviceInfo = withContext(coroutineDispatchers.io) { olmMachine.ownDevice() } diff --git a/vector-app/src/main/java/im/vector/app/VectorApplication.kt b/vector-app/src/main/java/im/vector/app/VectorApplication.kt index 0f83f57d01..df1c584b3a 100644 --- a/vector-app/src/main/java/im/vector/app/VectorApplication.kt +++ b/vector-app/src/main/java/im/vector/app/VectorApplication.kt @@ -135,6 +135,7 @@ class VectorApplication : SuperProperties( appPlatform = SuperProperties.AppPlatform.EA, cryptoSDK = SuperProperties.CryptoSDK.Rust, + cryptoSDKVersion = Matrix.getCryptoVersion(longFormat = false) ) ) invitesAcceptor.initialize() diff --git a/vector/src/main/java/im/vector/app/features/analytics/impl/AutoSuperPropertiesFlowProvider.kt b/vector/src/main/java/im/vector/app/features/analytics/impl/AutoSuperPropertiesFlowProvider.kt deleted file mode 100644 index 76763e3bab..0000000000 --- a/vector/src/main/java/im/vector/app/features/analytics/impl/AutoSuperPropertiesFlowProvider.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2024 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.vector.app.features.analytics.impl - -import im.vector.app.ActiveSessionDataSource -import im.vector.app.features.analytics.plan.SuperProperties -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.map -import javax.inject.Inject - -/** - * Gathers the super properties that are static to this platform or - * that can be automatically resolved from the current session. - */ -class AutoSuperPropertiesFlowProvider @Inject constructor( - activeSessionDataSource: ActiveSessionDataSource, -) { - - val superPropertiesFlow: Flow = activeSessionDataSource.stream() - .map { session -> - SuperProperties( - appPlatform = SuperProperties.AppPlatform.EA, - cryptoSDK = SuperProperties.CryptoSDK.Rust, - cryptoSDKVersion = session.getOrNull()?.cryptoService()?.getCryptoVersion(false) - ) - } - .distinctUntilChanged() -} diff --git a/vector/src/main/java/im/vector/app/features/analytics/impl/DefaultVectorAnalytics.kt b/vector/src/main/java/im/vector/app/features/analytics/impl/DefaultVectorAnalytics.kt index baefe18cf5..a7df8c54a8 100644 --- a/vector/src/main/java/im/vector/app/features/analytics/impl/DefaultVectorAnalytics.kt +++ b/vector/src/main/java/im/vector/app/features/analytics/impl/DefaultVectorAnalytics.kt @@ -42,7 +42,6 @@ class DefaultVectorAnalytics @Inject constructor( private val analyticsConfig: AnalyticsConfig, private val analyticsStore: AnalyticsStore, private val lateInitUserPropertiesFactory: LateInitUserPropertiesFactory, - private val autoSuperPropertiesFlowProvider: AutoSuperPropertiesFlowProvider, @NamedGlobalScope private val globalScope: CoroutineScope ) : VectorAnalytics { @@ -70,7 +69,6 @@ class DefaultVectorAnalytics @Inject constructor( override fun init() { observeUserConsent() observeAnalyticsId() - observeAutoSuperProperties() } override fun getUserConsent(): Flow { @@ -118,12 +116,6 @@ class DefaultVectorAnalytics @Inject constructor( .launchIn(globalScope) } - private fun observeAutoSuperProperties() { - autoSuperPropertiesFlowProvider.superPropertiesFlow.onEach { - updateSuperProperties(it) - }.launchIn(globalScope) - } - private suspend fun identifyPostHog() { val id = analyticsId ?: return if (!userConsent.orFalse()) return diff --git a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt index f89b6749a3..611c210f39 100755 --- a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt @@ -265,7 +265,7 @@ class BugReporter @Inject constructor( activeSessionHolder.getSafeActiveSession()?.let { session -> userId = session.myUserId deviceId = session.sessionParams.deviceId - olmVersion = session.cryptoService().getCryptoVersion(true) + olmVersion = Matrix.getCryptoVersion(true) } if (!mIsCancelled) { diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt index 47db90466e..359cc041f8 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt @@ -96,7 +96,7 @@ class VectorSettingsHelpAboutFragment : // olm version findPreference(VectorPreferences.SETTINGS_CRYPTO_VERSION_PREFERENCE_KEY)!! - .summary = session.cryptoService().getCryptoVersion(true) + .summary = Matrix.getCryptoVersion(true) } companion object { diff --git a/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt b/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt index 3b0d13c945..72ff56bc27 100644 --- a/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt +++ b/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt @@ -18,7 +18,6 @@ package im.vector.app.features.analytics.impl import im.vector.app.features.analytics.plan.SuperProperties import im.vector.app.test.fakes.FakeAnalyticsStore -import im.vector.app.test.fakes.FakeAutoSuperPropertiesFlowProvider import im.vector.app.test.fakes.FakeLateInitUserPropertiesFactory import im.vector.app.test.fakes.FakePostHog import im.vector.app.test.fakes.FakePostHogFactory @@ -46,7 +45,6 @@ class DefaultVectorAnalyticsTest { private val fakeAnalyticsStore = FakeAnalyticsStore() private val fakeLateInitUserPropertiesFactory = FakeLateInitUserPropertiesFactory() private val fakeSentryAnalytics = FakeSentryAnalytics() - private val fakeAutoSuperPropertiesFlowProvider = FakeAutoSuperPropertiesFlowProvider() private val defaultVectorAnalytics = DefaultVectorAnalytics( postHogFactory = FakePostHogFactory(fakePostHog.instance).instance, @@ -55,7 +53,6 @@ class DefaultVectorAnalyticsTest { globalScope = CoroutineScope(Dispatchers.Unconfined), analyticsConfig = anAnalyticsConfig(isEnabled = true), lateInitUserPropertiesFactory = fakeLateInitUserPropertiesFactory.instance, - autoSuperPropertiesFlowProvider = fakeAutoSuperPropertiesFlowProvider.instance, ) @Before @@ -289,40 +286,6 @@ class DefaultVectorAnalyticsTest { ) } - @Test - fun `Update super properties from flow`() = runTest { - fakeAnalyticsStore.givenUserContent(consent = true) - - fakeAutoSuperPropertiesFlowProvider.postSuperProperty( - SuperProperties( - cryptoSDKVersion = "0" - ) - ) - - val fakeEvent = aVectorAnalyticsEvent("THE_NAME", null) - defaultVectorAnalytics.capture(fakeEvent) - - fakePostHog.verifyEventTracked( - "THE_NAME", - mapOf( - "cryptoSDKVersion" to "0" - ) - ) - - fakeAutoSuperPropertiesFlowProvider.postSuperProperty(SuperProperties( - cryptoSDKVersion = "1" - )) - - defaultVectorAnalytics.capture(fakeEvent) - - fakePostHog.verifyEventTracked( - "THE_NAME", - mapOf( - "cryptoSDKVersion" to "1" - ) - ) - } - private fun Map?.clearNulls(): Map? { if (this == null) return null diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeAutoSuperPropertiesFlowProvider.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeAutoSuperPropertiesFlowProvider.kt deleted file mode 100644 index eff184298e..0000000000 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeAutoSuperPropertiesFlowProvider.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2024 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.vector.app.test.fakes - -import im.vector.app.features.analytics.impl.AutoSuperPropertiesFlowProvider -import im.vector.app.features.analytics.plan.SuperProperties -import io.mockk.every -import io.mockk.mockk -import kotlinx.coroutines.flow.MutableSharedFlow - -class FakeAutoSuperPropertiesFlowProvider { - - val flow = MutableSharedFlow() - - val instance = mockk().also { - every { it.superPropertiesFlow } returns flow - } - - suspend fun postSuperProperty(properties: SuperProperties) { - flow.emit(properties) - } -}