Skip to content

Commit a5cbbbe

Browse files
turnipdabeetsclaude
andcommitted
fix: restore full session replay state on in-session re-arm
reevaluateSessionReplayFromCachedConfig() only restored sessionReplayFlagActive, leaving consoleLogRecordingEnabled (zeroed by reset()) off until an app restart. Reuse processSessionRecordingConfig on the cached map so the re-arm restores the full recording state (console logs, endpoint, sample rate, triggers, duration) the way /config did. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent f880cdb commit a5cbbbe

2 files changed

Lines changed: 36 additions & 5 deletions

File tree

posthog/src/main/java/com/posthog/internal/PostHogRemoteConfig.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -398,15 +398,15 @@ public class PostHogRemoteConfig(
398398
return milliseconds
399399
}
400400

401-
// Re-evaluates sessionReplayFlagActive from the cached config (survives reset) + current flags.
401+
// Restores the full recording config from cache (survives reset), re-evaluated against current flags.
402402
private fun reevaluateSessionReplayFromCachedConfig() {
403403
@Suppress("UNCHECKED_CAST")
404404
val recordingConfig = config.cachePreferences?.getValue(SESSION_REPLAY) as? Map<String, Any?>
405405
if (recordingConfig == null) {
406406
config.logger.log("No cached session replay config to re-evaluate; replay stays disabled.")
407407
return
408408
}
409-
sessionReplayFlagActive = isRecordingActive(this.featureFlags ?: mapOf(), recordingConfig)
409+
processSessionRecordingConfig(recordingConfig)
410410
}
411411

412412
private fun processSessionRecordingConfig(sessionRecording: Any?) {
@@ -648,8 +648,7 @@ public class PostHogRemoteConfig(
648648
this.featureFlagPayloads = normalizedPayloads
649649
}
650650

651-
// /flags omits sessionRecording (null) -> re-evaluate from the cached config instead of
652-
// clobbering it. An explicit value (e.g. Boolean false when remotely disabled) is still honored.
651+
// /flags usually omits sessionRecording; re-arm from cached config instead of clobbering it.
653652
val responseSessionRecording = it.sessionRecording
654653
if (responseSessionRecording != null) {
655654
processSessionRecordingConfig(responseSessionRecording)

posthog/src/test/java/com/posthog/internal/PostHogRemoteConfigTest.kt

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,14 +146,46 @@ internal class PostHogRemoteConfigTest {
146146
)
147147
assertTrue(secondLatch.await(5, TimeUnit.SECONDS), "second flags load should complete")
148148

149-
// Explicit false turns replay off and drops the cached config.
149+
// A response that explicitly carries false turns replay off and drops the cached config.
150150
assertFalse(sut.isSessionReplayFlagActive())
151151
assertNull(preferences.getValue(SESSION_REPLAY))
152152

153153
sut.clear()
154154
http.shutdown()
155155
}
156156

157+
@Test
158+
fun `re-arm on a flags reload restores consoleLogRecordingEnabled from the cached config`() {
159+
preferences.setValue(SESSION_REPLAY, mapOf("consoleLogRecordingEnabled" to true))
160+
161+
// /flags omits sessionRecording, so the reload must re-arm from the cached config.
162+
val withoutRecording = File("src/test/resources/json/basic-flags-no-session-recording.json").readText()
163+
val http = mockHttp(response = MockResponse().setBody(withoutRecording))
164+
val url = http.url("/")
165+
166+
val sut = getSut(host = url.toString())
167+
168+
assertTrue(sut.isConsoleLogRecordingEnabled())
169+
170+
sut.clear()
171+
assertFalse(sut.isConsoleLogRecordingEnabled())
172+
173+
val latch = CountDownLatch(1)
174+
sut.loadFeatureFlags(
175+
"my_identify",
176+
anonymousId = "anonId",
177+
emptyMap(),
178+
onFeatureFlags = PostHogOnFeatureFlags { latch.countDown() },
179+
)
180+
assertTrue(latch.await(5, TimeUnit.SECONDS), "flags load should complete")
181+
182+
// Restored from cache, not left clobbered to false.
183+
assertTrue(sut.isConsoleLogRecordingEnabled())
184+
185+
sut.clear()
186+
http.shutdown()
187+
}
188+
157189
@Test
158190
fun `flags reload without a cached recording config leaves replay inactive`() {
159191
val withoutRecording = File("src/test/resources/json/basic-flags-no-session-recording.json").readText()

0 commit comments

Comments
 (0)