Skip to content

Commit 4acbe4e

Browse files
authored
Merge pull request #8820 from element-hq/feature/bca/bump_posthog_version_3
Bump posthog version to 3.2.0
2 parents f9a8451 + d100b62 commit 4acbe4e

File tree

8 files changed

+65
-72
lines changed

8 files changed

+65
-72
lines changed

changelog.d/8820.misc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Update posthog sdk to 3.2.0

dependencies_groups.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ ext.groups = [
121121
'com.parse.bolts',
122122
'com.pinterest',
123123
'com.pinterest.ktlint',
124-
'com.posthog.android',
124+
'com.posthog',
125125
'com.squareup',
126126
'com.squareup.curtains',
127127
'com.squareup.duktape',

vector/build.gradle

+1-3
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,7 @@ dependencies {
234234
kapt libs.dagger.hiltCompiler
235235

236236
// Analytics
237-
implementation('com.posthog.android:posthog:2.0.3') {
238-
exclude group: 'com.android.support', module: 'support-annotations'
239-
}
237+
implementation 'com.posthog:posthog-android:3.2.0'
240238
implementation libs.sentry.sentryAndroid
241239

242240
// UnifiedPush

vector/src/main/java/im/vector/app/features/analytics/impl/DefaultVectorAnalytics.kt

+25-19
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@
1616

1717
package im.vector.app.features.analytics.impl
1818

19-
import com.posthog.android.Options
20-
import com.posthog.android.PostHog
21-
import com.posthog.android.Properties
19+
import com.posthog.PostHogInterface
2220
import im.vector.app.core.di.NamedGlobalScope
2321
import im.vector.app.features.analytics.AnalyticsConfig
2422
import im.vector.app.features.analytics.VectorAnalytics
@@ -36,9 +34,6 @@ import timber.log.Timber
3634
import javax.inject.Inject
3735
import javax.inject.Singleton
3836

39-
private val REUSE_EXISTING_ID: String? = null
40-
private val IGNORED_OPTIONS: Options? = null
41-
4237
@Singleton
4338
class DefaultVectorAnalytics @Inject constructor(
4439
private val postHogFactory: PostHogFactory,
@@ -49,9 +44,9 @@ class DefaultVectorAnalytics @Inject constructor(
4944
@NamedGlobalScope private val globalScope: CoroutineScope
5045
) : VectorAnalytics {
5146

52-
private var posthog: PostHog? = null
47+
private var posthog: PostHogInterface? = null
5348

54-
private fun createPosthog(): PostHog? {
49+
private fun createPosthog(): PostHogInterface? {
5550
return when {
5651
analyticsConfig.isEnabled -> postHogFactory.createPosthog()
5752
else -> {
@@ -126,7 +121,7 @@ class DefaultVectorAnalytics @Inject constructor(
126121
posthog?.reset()
127122
} else {
128123
Timber.tag(analyticsTag.value).d("identify")
129-
posthog?.identify(id, lateInitUserPropertiesFactory.createUserProperties()?.getProperties()?.toPostHogUserProperties(), IGNORED_OPTIONS)
124+
posthog?.identify(id, lateInitUserPropertiesFactory.createUserProperties()?.getProperties()?.toPostHogUserProperties())
130125
}
131126
}
132127

@@ -155,16 +150,16 @@ class DefaultVectorAnalytics @Inject constructor(
155150
when (_userConsent) {
156151
true -> {
157152
posthog = createPosthog()
158-
posthog?.optOut(false)
153+
posthog?.optIn()
159154
identifyPostHog()
160155
pendingUserProperties?.let { doUpdateUserProperties(it) }
161156
pendingUserProperties = null
162157
}
163158
false -> {
164159
// When opting out, ensure that the queue is flushed first, or it will be flushed later (after user has revoked consent)
165160
posthog?.flush()
166-
posthog?.optOut(true)
167-
posthog?.shutdown()
161+
posthog?.optOut()
162+
posthog?.close()
168163
posthog = null
169164
}
170165
}
@@ -177,6 +172,7 @@ class DefaultVectorAnalytics @Inject constructor(
177172
?.takeIf { userConsent == true }
178173
?.capture(
179174
event.getName(),
175+
analyticsId,
180176
event.getProperties()?.toPostHogProperties()
181177
)
182178
}
@@ -197,27 +193,37 @@ class DefaultVectorAnalytics @Inject constructor(
197193
}
198194

199195
private fun doUpdateUserProperties(userProperties: UserProperties) {
196+
// we need a distinct id to set user properties
197+
val distinctId = analyticsId ?: return
200198
posthog
201199
?.takeIf { userConsent == true }
202-
?.identify(REUSE_EXISTING_ID, userProperties.getProperties()?.toPostHogUserProperties(), IGNORED_OPTIONS)
200+
?.identify(distinctId, userProperties.getProperties())
203201
}
204202

205-
private fun Map<String, Any?>?.toPostHogProperties(): Properties? {
203+
private fun Map<String, Any?>?.toPostHogProperties(): Map<String, Any>? {
206204
if (this == null) return null
207205

208-
return Properties().apply {
209-
putAll(this@toPostHogProperties)
206+
val nonNulls = HashMap<String, Any>()
207+
this.forEach { (key, value) ->
208+
if (value != null) {
209+
nonNulls[key] = value
210+
}
210211
}
212+
return nonNulls
211213
}
212214

213215
/**
214216
* We avoid sending nulls as part of the UserProperties as this will reset the values across all devices.
215217
* The UserProperties event has nullable properties to allow for clients to opt in.
216218
*/
217-
private fun Map<String, Any?>.toPostHogUserProperties(): Properties {
218-
return Properties().apply {
219-
putAll(this@toPostHogUserProperties.filter { it.value != null })
219+
private fun Map<String, Any?>.toPostHogUserProperties(): Map<String, Any> {
220+
val nonNulls = HashMap<String, Any>()
221+
this.forEach { (key, value) ->
222+
if (value != null) {
223+
nonNulls[key] = value
224+
}
220225
}
226+
return nonNulls
221227
}
222228

223229
override fun trackError(throwable: Throwable) {

vector/src/main/java/im/vector/app/features/analytics/impl/PostHogFactory.kt

+14-24
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
package im.vector.app.features.analytics.impl
1818

1919
import android.content.Context
20-
import com.posthog.android.PostHog
20+
import com.posthog.PostHogInterface
21+
import com.posthog.android.PostHogAndroid
22+
import com.posthog.android.PostHogAndroidConfig
2123
import im.vector.app.core.resources.BuildMeta
2224
import im.vector.app.features.analytics.AnalyticsConfig
2325
import javax.inject.Inject
@@ -28,29 +30,17 @@ class PostHogFactory @Inject constructor(
2830
private val buildMeta: BuildMeta,
2931
) {
3032

31-
fun createPosthog(): PostHog {
32-
return PostHog.Builder(context, analyticsConfig.postHogApiKey, analyticsConfig.postHogHost)
33-
// Record certain application events automatically! (off/false by default)
34-
// .captureApplicationLifecycleEvents()
35-
// Record screen views automatically! (off/false by default)
36-
// .recordScreenViews()
37-
// Capture deep links as part of the screen call. (off by default)
38-
// .captureDeepLinks()
39-
// Maximum number of events to keep in queue before flushing (default 20)
40-
// .flushQueueSize(20)
41-
// Max delay before flushing the queue (30 seconds)
42-
// .flushInterval(30, TimeUnit.SECONDS)
43-
// Enable or disable collection of ANDROID_ID (true)
44-
.collectDeviceId(false)
45-
.logLevel(getLogLevel())
46-
.build()
47-
}
48-
49-
private fun getLogLevel(): PostHog.LogLevel {
50-
return if (buildMeta.isDebug) {
51-
PostHog.LogLevel.DEBUG
52-
} else {
53-
PostHog.LogLevel.INFO
33+
fun createPosthog(): PostHogInterface {
34+
val config = PostHogAndroidConfig(
35+
apiKey = analyticsConfig.postHogApiKey,
36+
host = analyticsConfig.postHogHost,
37+
// we do that manually
38+
captureScreenViews = false,
39+
).also {
40+
if (buildMeta.isDebug) {
41+
it.debug = true
42+
}
5443
}
44+
return PostHogAndroid.with(context, config)
5545
}
5646
}

vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt

+11-14
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616

1717
package im.vector.app.features.analytics.impl
1818

19-
import com.posthog.android.Properties
20-
import im.vector.app.features.analytics.itf.VectorAnalyticsEvent
21-
import im.vector.app.features.analytics.itf.VectorAnalyticsScreen
2219
import im.vector.app.test.fakes.FakeAnalyticsStore
2320
import im.vector.app.test.fakes.FakeLateInitUserPropertiesFactory
2421
import im.vector.app.test.fakes.FakePostHog
@@ -128,7 +125,7 @@ class DefaultVectorAnalyticsTest {
128125

129126
defaultVectorAnalytics.screen(A_SCREEN_EVENT)
130127

131-
fakePostHog.verifyScreenTracked(A_SCREEN_EVENT.getName(), A_SCREEN_EVENT.toPostHogProperties())
128+
fakePostHog.verifyScreenTracked(A_SCREEN_EVENT.getName(), A_SCREEN_EVENT.getProperties())
132129
}
133130

134131
@Test
@@ -146,7 +143,7 @@ class DefaultVectorAnalyticsTest {
146143

147144
defaultVectorAnalytics.capture(AN_EVENT)
148145

149-
fakePostHog.verifyEventTracked(AN_EVENT.getName(), AN_EVENT.toPostHogProperties())
146+
fakePostHog.verifyEventTracked(AN_EVENT.getName(), AN_EVENT.getProperties().clearNulls())
150147
}
151148

152149
@Test
@@ -176,16 +173,16 @@ class DefaultVectorAnalyticsTest {
176173

177174
fakeSentryAnalytics.verifyNoErrorTracking()
178175
}
179-
}
180176

181-
private fun VectorAnalyticsScreen.toPostHogProperties(): Properties? {
182-
return getProperties()?.let { properties ->
183-
Properties().also { it.putAll(properties) }
184-
}
185-
}
177+
private fun Map<String, Any?>?.clearNulls(): Map<String, Any>? {
178+
if (this == null) return null
186179

187-
private fun VectorAnalyticsEvent.toPostHogProperties(): Properties? {
188-
return getProperties()?.let { properties ->
189-
Properties().also { it.putAll(properties) }
180+
val nonNulls = HashMap<String, Any>()
181+
this.forEach { (key, value) ->
182+
if (value != null) {
183+
nonNulls[key] = value
184+
}
185+
}
186+
return nonNulls
190187
}
191188
}

vector/src/test/java/im/vector/app/test/fakes/FakePostHog.kt

+10-9
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@
1717
package im.vector.app.test.fakes
1818

1919
import android.os.Looper
20-
import com.posthog.android.PostHog
21-
import com.posthog.android.Properties
20+
import com.posthog.PostHogInterface
2221
import im.vector.app.features.analytics.plan.UserProperties
2322
import io.mockk.every
2423
import io.mockk.mockk
@@ -36,16 +35,19 @@ class FakePostHog {
3635
every { Looper.getMainLooper() } returns looper
3736
}
3837

39-
val instance = mockk<PostHog>(relaxed = true)
38+
val instance = mockk<PostHogInterface>(relaxed = true)
4039

4140
fun verifyOptOutStatus(optedOut: Boolean) {
42-
verify { instance.optOut(optedOut) }
41+
if (optedOut) {
42+
verify { instance.optOut() }
43+
} else {
44+
verify { instance.optIn() }
45+
}
4346
}
4447

4548
fun verifyIdentifies(analyticsId: String, userProperties: UserProperties?) {
4649
verify {
4750
val postHogProperties = userProperties?.getProperties()
48-
?.let { rawProperties -> Properties().also { it.putAll(rawProperties) } }
4951
?.takeIf { it.isNotEmpty() }
5052
instance.identify(analyticsId, postHogProperties, null)
5153
}
@@ -55,20 +57,19 @@ class FakePostHog {
5557
verify { instance.reset() }
5658
}
5759

58-
fun verifyScreenTracked(name: String, properties: Properties?) {
60+
fun verifyScreenTracked(name: String, properties: Map<String, Any>?) {
5961
verify { instance.screen(name, properties) }
6062
}
6163

6264
fun verifyNoScreenTracking() {
6365
verify(exactly = 0) {
6466
instance.screen(any())
6567
instance.screen(any(), any())
66-
instance.screen(any(), any(), any())
6768
}
6869
}
6970

70-
fun verifyEventTracked(name: String, properties: Properties?) {
71-
verify { instance.capture(name, properties) }
71+
fun verifyEventTracked(name: String, properties: Map<String, Any>?) {
72+
verify { instance.capture(name, null, properties) }
7273
}
7374

7475
fun verifyNoEventTracking() {

vector/src/test/java/im/vector/app/test/fakes/FakePostHogFactory.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@
1616

1717
package im.vector.app.test.fakes
1818

19-
import com.posthog.android.PostHog
19+
import com.posthog.PostHogInterface
2020
import im.vector.app.features.analytics.impl.PostHogFactory
2121
import io.mockk.every
2222
import io.mockk.mockk
2323

24-
class FakePostHogFactory(postHog: PostHog) {
24+
class FakePostHogFactory(postHog: PostHogInterface) {
2525
val instance = mockk<PostHogFactory>().also {
2626
every { it.createPosthog() } returns postHog
2727
}

0 commit comments

Comments
 (0)