Bump posthog version to 3.2.0

This commit is contained in:
Valere 2024-05-06 09:28:53 +02:00
parent 305372cafc
commit 443db6ce8e
5 changed files with 43 additions and 49 deletions

View file

@ -120,7 +120,7 @@ ext.groups = [
'com.parse.bolts',
'com.pinterest',
'com.pinterest.ktlint',
'com.posthog.android',
'com.posthog',
'com.squareup',
'com.squareup.curtains',
'com.squareup.duktape',

View file

@ -231,9 +231,7 @@ dependencies {
kapt libs.dagger.hiltCompiler
// Analytics
implementation('com.posthog.android:posthog:2.0.3') {
exclude group: 'com.android.support', module: 'support-annotations'
}
implementation 'com.posthog:posthog-android:3.2.0'
implementation libs.sentry.sentryAndroid
// UnifiedPush

View file

@ -16,9 +16,7 @@
package im.vector.app.features.analytics.impl
import com.posthog.android.Options
import com.posthog.android.PostHog
import com.posthog.android.Properties
import com.posthog.PostHogInterface
import im.vector.app.core.di.NamedGlobalScope
import im.vector.app.features.analytics.AnalyticsConfig
import im.vector.app.features.analytics.VectorAnalytics
@ -36,9 +34,6 @@ import timber.log.Timber
import javax.inject.Inject
import javax.inject.Singleton
private val REUSE_EXISTING_ID: String? = null
private val IGNORED_OPTIONS: Options? = null
@Singleton
class DefaultVectorAnalytics @Inject constructor(
private val postHogFactory: PostHogFactory,
@ -49,9 +44,9 @@ class DefaultVectorAnalytics @Inject constructor(
@NamedGlobalScope private val globalScope: CoroutineScope
) : VectorAnalytics {
private var posthog: PostHog? = null
private var posthog: PostHogInterface? = null
private fun createPosthog(): PostHog? {
private fun createPosthog(): PostHogInterface? {
return when {
analyticsConfig.isEnabled -> postHogFactory.createPosthog()
else -> {
@ -126,7 +121,7 @@ class DefaultVectorAnalytics @Inject constructor(
posthog?.reset()
} else {
Timber.tag(analyticsTag.value).d("identify")
posthog?.identify(id, lateInitUserPropertiesFactory.createUserProperties()?.getProperties()?.toPostHogUserProperties(), IGNORED_OPTIONS)
posthog?.identify(id, lateInitUserPropertiesFactory.createUserProperties()?.getProperties()?.toPostHogUserProperties())
}
}
@ -155,7 +150,7 @@ class DefaultVectorAnalytics @Inject constructor(
when (_userConsent) {
true -> {
posthog = createPosthog()
posthog?.optOut(false)
posthog?.optIn()
identifyPostHog()
pendingUserProperties?.let { doUpdateUserProperties(it) }
pendingUserProperties = null
@ -163,8 +158,8 @@ class DefaultVectorAnalytics @Inject constructor(
false -> {
// When opting out, ensure that the queue is flushed first, or it will be flushed later (after user has revoked consent)
posthog?.flush()
posthog?.optOut(true)
posthog?.shutdown()
posthog?.optOut()
posthog?.close()
posthog = null
}
}
@ -177,6 +172,7 @@ class DefaultVectorAnalytics @Inject constructor(
?.takeIf { userConsent == true }
?.capture(
event.getName(),
analyticsId,
event.getProperties()?.toPostHogProperties()
)
}
@ -197,28 +193,38 @@ 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(REUSE_EXISTING_ID, userProperties.getProperties()?.toPostHogUserProperties(), IGNORED_OPTIONS)
?.identify(distinctId, userProperties.getProperties())
}
private fun Map<String, Any?>?.toPostHogProperties(): Properties? {
private fun Map<String, Any?>?.toPostHogProperties(): Map<String, Any>? {
if (this == null) return null
return Properties().apply {
putAll(this@toPostHogProperties)
val nonNulls = HashMap<String, Any>()
this.forEach { (key, value) ->
if (value != null) {
nonNulls[key] = value
}
}
return nonNulls
}
/**
* We avoid sending nulls as part of the UserProperties as this will reset the values across all devices.
* The UserProperties event has nullable properties to allow for clients to opt in.
*/
private fun Map<String, Any?>.toPostHogUserProperties(): Properties {
return Properties().apply {
putAll(this@toPostHogUserProperties.filter { it.value != null })
private fun Map<String, Any?>.toPostHogUserProperties(): Map<String, Any> {
val nonNulls = HashMap<String, Any>()
this.forEach { (key, value) ->
if (value != null) {
nonNulls[key] = value
}
}
return nonNulls
}
override fun trackError(throwable: Throwable) {
sentryAnalytics

View file

@ -17,7 +17,9 @@
package im.vector.app.features.analytics.impl
import android.content.Context
import com.posthog.android.PostHog
import com.posthog.PostHogInterface
import com.posthog.android.PostHogAndroid
import com.posthog.android.PostHogAndroidConfig
import im.vector.app.core.resources.BuildMeta
import im.vector.app.features.analytics.AnalyticsConfig
import javax.inject.Inject
@ -28,29 +30,17 @@ class PostHogFactory @Inject constructor(
private val buildMeta: BuildMeta,
) {
fun createPosthog(): PostHog {
return PostHog.Builder(context, analyticsConfig.postHogApiKey, analyticsConfig.postHogHost)
// Record certain application events automatically! (off/false by default)
// .captureApplicationLifecycleEvents()
// Record screen views automatically! (off/false by default)
// .recordScreenViews()
// Capture deep links as part of the screen call. (off by default)
// .captureDeepLinks()
// Maximum number of events to keep in queue before flushing (default 20)
// .flushQueueSize(20)
// Max delay before flushing the queue (30 seconds)
// .flushInterval(30, TimeUnit.SECONDS)
// Enable or disable collection of ANDROID_ID (true)
.collectDeviceId(false)
.logLevel(getLogLevel())
.build()
}
private fun getLogLevel(): PostHog.LogLevel {
return if (buildMeta.isDebug) {
PostHog.LogLevel.DEBUG
} else {
PostHog.LogLevel.INFO
fun createPosthog(): PostHogInterface {
val config = PostHogAndroidConfig(
apiKey = analyticsConfig.postHogApiKey,
host = analyticsConfig.postHogHost,
// we do that manually
captureScreenViews = false,
).also {
if (buildMeta.isDebug) {
it.debug = true
}
}
return PostHogAndroid.with(context, config)
}
}

View file

@ -16,12 +16,12 @@
package im.vector.app.test.fakes
import com.posthog.android.PostHog
import com.posthog.PostHogInterface
import im.vector.app.features.analytics.impl.PostHogFactory
import io.mockk.every
import io.mockk.mockk
class FakePostHogFactory(postHog: PostHog) {
class FakePostHogFactory(postHog: PostHogInterface) {
val instance = mockk<PostHogFactory>().also {
every { it.createPosthog() } returns postHog
}