From 4ea8d176393e54d1c086ee5df432fe46849f4b2b Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Tue, 27 Aug 2024 13:39:50 +0200 Subject: [PATCH 1/4] chore: expose session id for react native --- posthog/api/posthog.api | 9 ++++ posthog/src/main/java/com/posthog/PostHog.kt | 39 ++++---------- .../posthog/internal/PostHogSessionManager.kt | 54 +++++++++++++++++++ 3 files changed, 74 insertions(+), 28 deletions(-) create mode 100644 posthog/src/main/java/com/posthog/internal/PostHogSessionManager.kt diff --git a/posthog/api/posthog.api b/posthog/api/posthog.api index 5e003138..23b216e3 100644 --- a/posthog/api/posthog.api +++ b/posthog/api/posthog.api @@ -302,6 +302,15 @@ public final class com/posthog/internal/PostHogSerializer { public final fun serializeObject (Ljava/lang/Object;)Ljava/lang/String; } +public final class com/posthog/internal/PostHogSessionManager { + public static final field INSTANCE Lcom/posthog/internal/PostHogSessionManager; + public final fun endSession ()V + public final fun getActiveSessionId ()Ljava/util/UUID; + public final fun isSessionActive ()Z + public final fun setSessionId (Ljava/util/UUID;)V + public final fun startSession ()V +} + public final class com/posthog/internal/PostHogThreadFactory : java/util/concurrent/ThreadFactory { public fun (Ljava/lang/String;)V public fun newThread (Ljava/lang/Runnable;)Ljava/lang/Thread; diff --git a/posthog/src/main/java/com/posthog/PostHog.kt b/posthog/src/main/java/com/posthog/PostHog.kt index 58eaf193..fcbfaeab 100644 --- a/posthog/src/main/java/com/posthog/PostHog.kt +++ b/posthog/src/main/java/com/posthog/PostHog.kt @@ -17,9 +17,9 @@ import com.posthog.internal.PostHogPrintLogger import com.posthog.internal.PostHogQueue import com.posthog.internal.PostHogSendCachedEventsIntegration import com.posthog.internal.PostHogSerializer +import com.posthog.internal.PostHogSessionManager import com.posthog.internal.PostHogThreadFactory import com.posthog.vendor.uuid.TimeBasedEpochGenerator -import java.util.UUID import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -48,13 +48,8 @@ public class PostHog private constructor( private val setupLock = Any() private val optOutLock = Any() private val anonymousLock = Any() - private val sessionLock = Any() private val groupsLock = Any() - // do not move to companion object, otherwise sessionId will be null - private val sessionIdNone = UUID(0, 0) - - private var sessionId = sessionIdNone private val featureFlagsCalledLock = Any() private var config: PostHogConfig? = null @@ -272,15 +267,13 @@ public class PostHog private constructor( } } - synchronized(sessionLock) { - if (sessionId != sessionIdNone) { - val sessionId = sessionId.toString() - props["\$session_id"] = sessionId - if (config?.sessionReplay == true) { - // Session replay requires $window_id, so we set as the same as $session_id. - // the backend might fallback to $session_id if $window_id is not present next. - props["\$window_id"] = sessionId - } + PostHogSessionManager.getActiveSessionId()?.let { sessionId -> + val tempSessionId = sessionId.toString() + props["\$session_id"] = tempSessionId + if (config?.sessionReplay == true) { + // Session replay requires $window_id, so we set as the same as $session_id. + // the backend might fallback to $session_id if $window_id is not present next. + props["\$window_id"] = tempSessionId } } @@ -697,25 +690,15 @@ public class PostHog private constructor( } override fun startSession() { - synchronized(sessionLock) { - if (sessionId == sessionIdNone) { - sessionId = TimeBasedEpochGenerator.generate() - } - } + PostHogSessionManager.startSession() } override fun endSession() { - synchronized(sessionLock) { - sessionId = sessionIdNone - } + PostHogSessionManager.endSession() } override fun isSessionActive(): Boolean { - var active: Boolean - synchronized(sessionLock) { - active = sessionId != sessionIdNone - } - return active + return PostHogSessionManager.isSessionActive() } override fun getConfig(): T? { diff --git a/posthog/src/main/java/com/posthog/internal/PostHogSessionManager.kt b/posthog/src/main/java/com/posthog/internal/PostHogSessionManager.kt new file mode 100644 index 00000000..0f7b08eb --- /dev/null +++ b/posthog/src/main/java/com/posthog/internal/PostHogSessionManager.kt @@ -0,0 +1,54 @@ +package com.posthog.internal + +import com.posthog.PostHogInternal +import com.posthog.vendor.uuid.TimeBasedEpochGenerator +import java.util.UUID + +/** + * Class that manages the Session ID + */ +@PostHogInternal +public object PostHogSessionManager { + private val sessionLock = Any() + + // do not move to companion object, otherwise sessionId will be null + private val sessionIdNone = UUID(0, 0) + + private var sessionId = sessionIdNone + + public fun startSession() { + synchronized(sessionLock) { + if (sessionId == sessionIdNone) { + sessionId = TimeBasedEpochGenerator.generate() + } + } + } + + public fun endSession() { + synchronized(sessionLock) { + sessionId = sessionIdNone + } + } + + public fun getActiveSessionId(): UUID? { + var tempSessionId: UUID? + synchronized(sessionLock) { + tempSessionId = if (sessionId != sessionIdNone) sessionId else null + } + return tempSessionId + } + + public fun setSessionId(sessionId: UUID) { + synchronized(sessionLock) { + this.sessionId = sessionId + } + } + + public fun isSessionActive(): Boolean { + var active: Boolean + synchronized(sessionLock) { + active = sessionId != sessionIdNone + } + return active + } +} From aa3bfb66bd26397f885e5424e3381e61e64040aa Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Tue, 27 Aug 2024 13:44:54 +0200 Subject: [PATCH 2/4] add get session id --- .../src/test/java/com/posthog/android/PostHogFake.kt | 5 +++++ posthog/api/posthog.api | 3 +++ posthog/src/main/java/com/posthog/PostHog.kt | 9 +++++++++ posthog/src/main/java/com/posthog/PostHogInterface.kt | 7 +++++++ 4 files changed, 24 insertions(+) diff --git a/posthog-android/src/test/java/com/posthog/android/PostHogFake.kt b/posthog-android/src/test/java/com/posthog/android/PostHogFake.kt index d5c466c9..3e7a6d23 100644 --- a/posthog-android/src/test/java/com/posthog/android/PostHogFake.kt +++ b/posthog-android/src/test/java/com/posthog/android/PostHogFake.kt @@ -3,6 +3,7 @@ package com.posthog.android import com.posthog.PostHogConfig import com.posthog.PostHogInterface import com.posthog.PostHogOnFeatureFlags +import java.util.UUID public class PostHogFake : PostHogInterface { public var event: String? = null @@ -119,6 +120,10 @@ public class PostHogFake : PostHogInterface { return false } + override fun getSessionId(): UUID? { + return null + } + override fun getConfig(): T? { return null } diff --git a/posthog/api/posthog.api b/posthog/api/posthog.api index 23b216e3..e69973eb 100644 --- a/posthog/api/posthog.api +++ b/posthog/api/posthog.api @@ -11,6 +11,7 @@ public final class com/posthog/PostHog : com/posthog/PostHogInterface { public fun getConfig ()Lcom/posthog/PostHogConfig; public fun getFeatureFlag (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public fun getFeatureFlagPayload (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; + public fun getSessionId ()Ljava/util/UUID; public fun group (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)V public fun identify (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)V public fun isFeatureEnabled (Ljava/lang/String;Z)Z @@ -38,6 +39,7 @@ public final class com/posthog/PostHog$Companion : com/posthog/PostHogInterface public fun getConfig ()Lcom/posthog/PostHogConfig; public fun getFeatureFlag (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public fun getFeatureFlagPayload (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; + public fun getSessionId ()Ljava/util/UUID; public fun group (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)V public fun identify (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)V public fun isFeatureEnabled (Ljava/lang/String;Z)Z @@ -178,6 +180,7 @@ public abstract interface class com/posthog/PostHogInterface { public abstract fun getConfig ()Lcom/posthog/PostHogConfig; public abstract fun getFeatureFlag (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun getFeatureFlagPayload (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun getSessionId ()Ljava/util/UUID; public abstract fun group (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)V public abstract fun identify (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)V public abstract fun isFeatureEnabled (Ljava/lang/String;Z)Z diff --git a/posthog/src/main/java/com/posthog/PostHog.kt b/posthog/src/main/java/com/posthog/PostHog.kt index fcbfaeab..70965e1d 100644 --- a/posthog/src/main/java/com/posthog/PostHog.kt +++ b/posthog/src/main/java/com/posthog/PostHog.kt @@ -20,6 +20,7 @@ import com.posthog.internal.PostHogSerializer import com.posthog.internal.PostHogSessionManager import com.posthog.internal.PostHogThreadFactory import com.posthog.vendor.uuid.TimeBasedEpochGenerator +import java.util.UUID import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -701,6 +702,10 @@ public class PostHog private constructor( return PostHogSessionManager.isSessionActive() } + override fun getSessionId(): UUID? { + return PostHogSessionManager.getActiveSessionId() + } + override fun getConfig(): T? { @Suppress("UNCHECKED_CAST") return config as? T @@ -879,6 +884,10 @@ public class PostHog private constructor( return shared.isSessionActive() } + override fun getSessionId(): UUID? { + return shared.getSessionId() + } + override fun getConfig(): T? { return shared.getConfig() } diff --git a/posthog/src/main/java/com/posthog/PostHogInterface.kt b/posthog/src/main/java/com/posthog/PostHogInterface.kt index a6a49363..8b5c394b 100644 --- a/posthog/src/main/java/com/posthog/PostHogInterface.kt +++ b/posthog/src/main/java/com/posthog/PostHogInterface.kt @@ -1,5 +1,7 @@ package com.posthog +import java.util.UUID + /** * The PostHog SDK entry point */ @@ -189,6 +191,11 @@ public interface PostHogInterface { */ public fun isSessionActive(): Boolean + /** + * Returns the session Id if a session is active + */ + public fun getSessionId(): UUID? + @PostHogInternal public fun getConfig(): T? } From a35addf20389154c1a74437e96a2551bf76daa5f Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Tue, 27 Aug 2024 13:58:58 +0200 Subject: [PATCH 3/4] pr id --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f87cfbe..87737be3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## Next +- recording: expose session id ([#166](https://github.com/PostHog/posthog-android/pull/166)) + ## 3.5.1 - 2024-08-26 - recording: capture touch interaction off of main thread to avoid ANRs ([#165](https://github.com/PostHog/posthog-android/pull/165)) From 12144a9fb15f3a148b97a9849dde57d4129d37a0 Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Tue, 27 Aug 2024 14:17:30 +0200 Subject: [PATCH 4/4] add is enabled checks --- posthog/src/main/java/com/posthog/PostHog.kt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/posthog/src/main/java/com/posthog/PostHog.kt b/posthog/src/main/java/com/posthog/PostHog.kt index 70965e1d..97479581 100644 --- a/posthog/src/main/java/com/posthog/PostHog.kt +++ b/posthog/src/main/java/com/posthog/PostHog.kt @@ -166,6 +166,10 @@ public class PostHog private constructor( public override fun close() { synchronized(setupLock) { try { + if (!isEnabled()) { + return + } + enabled = false config?.let { config -> @@ -691,18 +695,34 @@ public class PostHog private constructor( } override fun startSession() { + if (!isEnabled()) { + return + } + PostHogSessionManager.startSession() } override fun endSession() { + if (!isEnabled()) { + return + } + PostHogSessionManager.endSession() } override fun isSessionActive(): Boolean { + if (!isEnabled()) { + return false + } + return PostHogSessionManager.isSessionActive() } override fun getSessionId(): UUID? { + if (!isEnabled()) { + return null + } + return PostHogSessionManager.getActiveSessionId() }