Add super properties to posthog (plateformCode)
This commit is contained in:
parent
4acbe4e582
commit
08c124e13b
|
@ -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
|
||||
|
||||
|
|
|
@ -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<Session?> = 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() {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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<String, Any>.withSuperProperties(): Map<String, Any> {
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<String, Any?>?.clearNulls(): Map<String, Any>? {
|
||||
if (this == null) return null
|
||||
|
||||
|
|
Loading…
Reference in New Issue