Skip to content

feat: auto-rotate session after 24 hours #247

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft

Conversation

pauldambra
Copy link
Member

see PostHog/posthog#30889

android doesn't rotate session ID after 24 hours

i think this PR adds that 🙈

@pauldambra pauldambra requested review from a team, sortafreel and veryayskiy and removed request for a team May 6, 2025 14:38
@@ -29,10 +29,10 @@ internal class FakePostHogDateProvider : PostHogDateProvider {
}

override fun currentTimeMillis(): Long {
return System.currentTimeMillis()
return currentDate?.time ?: System.currentTimeMillis()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this threw me 🤣

}

override fun nanoTime(): Long {
return System.nanoTime()
return currentDate?.time?.times(1000000) ?: System.nanoTime()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so I updated here too

synchronized(sessionLock) {
if (sessionId == sessionIdNone) {
sessionId = TimeBasedEpochGenerator.generate()
sessionId = TimeBasedEpochGenerator.generate(sessionStartTime ?: System.currentTimeMillis())
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I passed the time in here...
since we have a date provider really we should pass it around everywhere

but I guess it's only for tests so I suppose this is OK

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thats fine, another approach would be to make a TimeBasedEpochGenerator an interface, and the current TimeBasedEpochGenerator is the production implementation and we could have a test implementation and swap during SDK initialization just for testing, the prod code would be cleaner but we would pay the price of an extra interface

* we can convert a session id into the session start timestamp
* and then use that to enforce the maximum session length
*/
private fun enforceMaxSessionLength(buildProperties: Map<String, Any>): Map<String, Any> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

react native has its own session id rotation so we should not do this for RN I think
https://github.com/PostHog/posthog-js-lite/blob/b8372284df5489457d95b16b0e4b12a91dd66c26/posthog-core/src/index.ts#L1309-L1315
otherwise they will be out of sync (RN uses a different session id than Android)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so, needs to be configurable? and then RN would turn off the Android one?
or sync up a release and RN stops doing its own?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, we have something similar for flutter already
today the way how it works is react native manages the session id and update the session id on android when its rotated.
now we want to do the other way around, from android to call the react native but you cant do this because the bridge only works in one direction, so its better to let the react native manage the whole session id thing otherwise they will be out of sync

Comment on lines +490 to +491
PostHogSessionManager.endSession()
PostHogSessionManager.startSession(currentTimeMillis)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this changes the session id but the session replay would need to be notified to eg send a new full snapshot with metadata etc otherwise it'll assume its already sent and the replay will be broken (missing meta event and full snapshot for the new session id)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 in the JS SDK we have an event emitter that we pass around that can be used for this kind of "onBlah" behavior

I guess the sessionManager can have a onSessionStarted that accepts a callback?

Is there a more android-y way of doing it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah a callback would be one way, since PostHogSessionManager lives in the java-only lib and most of the replay code is Android-dependent, we will need to pass callbacks around, or implement a pub/sub approach for "app is in background, app is in foreground, etc" so the java bits only can do things

appendSharedProps = !snapshotEvent,
// only append groups if not a group identify event and not a snapshot
appendGroups = !groupIdentify,
enforceMaxSessionLength(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will only be executed if an event is captured instead of when 24 hours have passed. Is that intentional? should we also do this eg when the app is put on foreground/backgorund?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i guess the foreground change is righ there

was assuming that we didn't want to run a timer just for this - although ultimately that's where JS SDK ended up

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we already have a timer when the app is put in the background, see here

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe that timer should also call enforceMaxSessionLength when its back in the foreground so we don't rely on the next event but rather if the app is back visible to the user

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

me: "let's open a PR and see how much I don't know"
me: *regrets life choices

🤣

@@ -4,6 +4,8 @@ import com.posthog.PostHogInternal
import com.posthog.vendor.uuid.TimeBasedEpochGenerator
import java.util.UUID

public const val MAX_SESSION_AGE_MILLIS: Int = 24 * 60 * 60 * 60
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can it be private instead?
if needed you can put it inside a companion object

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants