-
Notifications
You must be signed in to change notification settings - Fork 48
fix(replay): honor PostHogConfig.sessionReplay writes after setup #757
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
posthog
wants to merge
3
commits into
main
Choose a base branch
from
posthog-self-driving/fixreplay-stop-android-replay-when-its-fea916
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+246
β2
Draft
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
5b078c8
fix(replay): honor PostHogConfig.sessionReplay writes after setup
posthog[bot] 1dd0520
docs(replay): clarify sessionReplay=false is not an unconditional kilβ¦
posthog[bot] 407f725
fix(replay): re-check recording permission before running a queued reβ¦
posthog[bot] File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| --- | ||
| "posthog": patch | ||
| "posthog-android": patch | ||
| --- | ||
|
|
||
| Fix: writing `PostHogConfig.sessionReplay` after setup now takes effect right away. It used to be honored only at setup, and then again at the next session rotation or remote config delivery, so an app that read its own feature flag and assigned the result kept recording a user the flag excluded. Setting it to false stops recording; setting it to true resumes it when the project settings, the linked flag, the event triggers, and sampling also allow it. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An event trigger can restart replay after the master switch turns off
Why we think it's a valid issue
onEventbody at posthog-android/src/main/java/com/posthog/android/replay/PostHogReplayIntegration.kt:2311-2341,start()at 2254-2280,shouldWaitForEventTriggers()at 2411-2426,install()at 525-556, every read and write ofstartedWithAutomaticDisabled, and the dispatch site in the core.PostHog.kt:875dispatchessessionReplayHandler?.onEvent(...)unconditionally.install()(line 525) has noconfig.sessionReplaycheck, so the integration is live even when the switch is off.onEventreads only the session id, the trigger list, andtriggerActivatedSessionIdbefore it callsstart(resumeCurrent = true)at line 2339.start()is already satisfied by the time it runs.onEventassignstriggerActivatedSessionId = currentSessionIdat line 2335, andshouldWaitForEventTriggers()returnsactivatedSession != currentSessionId(line 2425), so it returns false andstart()proceeds.start()setsstartedWithAutomaticDisabled = !config.sessionReplayat line 2267, which istruehere. The guard(!config.sessionReplay && !startedWithAutomaticDisabled)then evaluates to false inreevaluateRecordingState(line 2638), inisRecordingPermittedForCurrentSession(line 2613), and on session rotation (line 2387). Onlystop()(line 2292) oruninstall()(line 582) clears the flag, so nothing short of an explicitstopSessionReplay()call recovers.sessionReplay = true. Recording waits for a trigger, so it is inactive. The app writesfalse, andstopIfActiveat line 2640 finds nothing to stop. A matching event then arrives and starts recording with the switch off.falseand recording stops, the session rotates, and the next matching event in session B starts recording again through the same path.onEventitself is untouched by this PR, so the hole predates it. What is new is the documented contract at posthog/src/main/java/com/posthog/PostHogConfig.kt:409-411, "Set it to false to stop recording, for example when your own feature flag turns off for this user", which this path defeats within the same session.Issue description
Even when no manual start exists, a matching event can reactivate replay after a false write.
onEvent()does not checkconfig.sessionReplay. It callsstart(), which marks the recording as manually started. This records a user whom the app excluded.Suggested fix
Track explicit manual intent separately from an event trigger. In
onEvent(), return whenconfig.sessionReplayis false unless a manual start is pending. Add a true-to-false-to-trigger regression test.Prompt to fix with AI (copy-paste)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Confirmed and escalating for a human design decision rather than fixing unattended β this one needs a policy call I shouldn't make on my own. The bug is real:
onEventstarts recording on a matching trigger without checkingconfig.sessionReplay, andstart()stamps the recording asstartedWithAutomaticDisabled, so once a trigger fires with the switch off the recording is immune to the switch, to remote-config deliveries, and to session rotation β only an explicitstopSessionReplay()clears it. That defeats thefalse-stops-recording contract this PR documents.Why not a quick fix: the safe-looking change β
returnfromonEventwhenconfig.sessionReplayis false β would break a supported flow.startSessionReplay()does not setconfig.sessionReplay, and when event triggers are configured it defers (start() early-returns until a trigger matches), soonEventis the only path that ever begins recording under triggers β for automatic and manual replay. Gating it on the master switch would silently disable manualstartSessionReplay()for any project that also uses event triggers with the switch off, which is exactly the manual carve-out this PR is preserving.Doing it right means introducing explicit manual-intent state (there is none today) and deciding the intended semantics: should an automatic event trigger respect the master switch while an explicit manual start survives it, and how should manual intent be carried through the trigger-deferral path? That plus the fact that
onEventpredates this PR (is this in scope here or a follow-up?) is the decision I'd like a maintainer to make before I implement.