From 5d911c5647bdba1d7fd924151b708ab9e6bd6dd4 Mon Sep 17 00:00:00 2001 From: Jamie Lynch Date: Wed, 13 Mar 2024 15:52:30 +0000 Subject: [PATCH] switch collator depending on config --- .../session/message/PayloadFactoryImpl.kt | 28 +++--- .../session/message/PayloadFactoryImplTest.kt | 96 +++++++++++++++++++ 2 files changed, 113 insertions(+), 11 deletions(-) create mode 100644 embrace-android-sdk/src/test/java/io/embrace/android/embracesdk/session/message/PayloadFactoryImplTest.kt diff --git a/embrace-android-sdk/src/main/java/io/embrace/android/embracesdk/session/message/PayloadFactoryImpl.kt b/embrace-android-sdk/src/main/java/io/embrace/android/embracesdk/session/message/PayloadFactoryImpl.kt index 9b668cbe03..ff0a93ec16 100644 --- a/embrace-android-sdk/src/main/java/io/embrace/android/embracesdk/session/message/PayloadFactoryImpl.kt +++ b/embrace-android-sdk/src/main/java/io/embrace/android/embracesdk/session/message/PayloadFactoryImpl.kt @@ -9,10 +9,16 @@ import io.embrace.android.embracesdk.session.orchestrator.SessionSnapshotType internal class PayloadFactoryImpl( private val v1payloadMessageCollator: V1PayloadMessageCollator, - @Suppress("UnusedPrivateProperty") private val v2payloadMessageCollator: V2PayloadMessageCollator, + private val v2payloadMessageCollator: V2PayloadMessageCollator, private val configService: ConfigService ) : PayloadFactory { + private val collator: PayloadMessageCollator + get() = when { + configService.sessionBehavior.useV2Payload() -> v2payloadMessageCollator + else -> v1payloadMessageCollator + } + override fun startPayloadWithState(state: ProcessState, timestamp: Long, coldStart: Boolean) = when (state) { ProcessState.FOREGROUND -> startSessionWithState(timestamp, coldStart) @@ -42,7 +48,7 @@ internal class PayloadFactoryImpl( } override fun startSessionWithManual(timestamp: Long): Session { - return v1payloadMessageCollator.buildInitialSession( + return collator.buildInitialSession( InitialEnvelopeParams.SessionParams( false, LifeEventType.MANUAL, @@ -52,7 +58,7 @@ internal class PayloadFactoryImpl( } override fun endSessionWithManual(timestamp: Long, initial: Session): SessionMessage { - return v1payloadMessageCollator.buildFinalSessionMessage( + return collator.buildFinalSessionMessage( FinalEnvelopeParams.SessionParams( initial = initial, endTime = timestamp, @@ -63,7 +69,7 @@ internal class PayloadFactoryImpl( } private fun startSessionWithState(timestamp: Long, coldStart: Boolean): Session { - return v1payloadMessageCollator.buildInitialSession( + return collator.buildInitialSession( InitialEnvelopeParams.SessionParams( coldStart, LifeEventType.STATE, @@ -83,7 +89,7 @@ internal class PayloadFactoryImpl( coldStart -> timestamp else -> timestamp + 1 } - return v1payloadMessageCollator.buildInitialSession( + return collator.buildInitialSession( InitialEnvelopeParams.BackgroundActivityParams( coldStart = coldStart, startType = LifeEventType.BKGND_STATE, @@ -93,7 +99,7 @@ internal class PayloadFactoryImpl( } private fun endSessionWithState(initial: Session, timestamp: Long): SessionMessage { - return v1payloadMessageCollator.buildFinalSessionMessage( + return collator.buildFinalSessionMessage( FinalEnvelopeParams.SessionParams( initial = initial, endTime = timestamp, @@ -110,7 +116,7 @@ internal class PayloadFactoryImpl( // kept for backwards compat. the backend expects the start time to be 1 ms greater // than the adjacent session, and manually adjusts. - return v1payloadMessageCollator.buildFinalBackgroundActivityMessage( + return collator.buildFinalBackgroundActivityMessage( FinalEnvelopeParams.BackgroundActivityParams( initial = initial, endTime = timestamp - 1, @@ -125,7 +131,7 @@ internal class PayloadFactoryImpl( timestamp: Long, crashId: String ): SessionMessage { - return v1payloadMessageCollator.buildFinalSessionMessage( + return collator.buildFinalSessionMessage( FinalEnvelopeParams.SessionParams( initial = initial, endTime = timestamp, @@ -144,7 +150,7 @@ internal class PayloadFactoryImpl( if (!configService.isBackgroundActivityCaptureEnabled()) { return null } - return v1payloadMessageCollator.buildFinalBackgroundActivityMessage( + return collator.buildFinalBackgroundActivityMessage( FinalEnvelopeParams.BackgroundActivityParams( initial = initial, endTime = timestamp, @@ -159,7 +165,7 @@ internal class PayloadFactoryImpl( * Called when the session is persisted every 2s to cache its state. */ private fun snapshotSession(initial: Session, timestamp: Long): SessionMessage { - return v1payloadMessageCollator.buildFinalSessionMessage( + return collator.buildFinalSessionMessage( FinalEnvelopeParams.SessionParams( initial = initial, endTime = timestamp, @@ -173,7 +179,7 @@ internal class PayloadFactoryImpl( if (!configService.isBackgroundActivityCaptureEnabled()) { return null } - return v1payloadMessageCollator.buildFinalBackgroundActivityMessage( + return collator.buildFinalBackgroundActivityMessage( FinalEnvelopeParams.BackgroundActivityParams( initial = initial, endTime = timestamp, diff --git a/embrace-android-sdk/src/test/java/io/embrace/android/embracesdk/session/message/PayloadFactoryImplTest.kt b/embrace-android-sdk/src/test/java/io/embrace/android/embracesdk/session/message/PayloadFactoryImplTest.kt new file mode 100644 index 0000000000..79088f0386 --- /dev/null +++ b/embrace-android-sdk/src/test/java/io/embrace/android/embracesdk/session/message/PayloadFactoryImplTest.kt @@ -0,0 +1,96 @@ +package io.embrace.android.embracesdk.session.message + +import io.embrace.android.embracesdk.FakeBreadcrumbService +import io.embrace.android.embracesdk.FakeSessionPropertiesService +import io.embrace.android.embracesdk.capture.envelope.SessionEnvelopeSource +import io.embrace.android.embracesdk.config.remote.RemoteConfig +import io.embrace.android.embracesdk.config.remote.SessionRemoteConfig +import io.embrace.android.embracesdk.fakes.FakeConfigService +import io.embrace.android.embracesdk.fakes.FakeEnvelopeMetadataSource +import io.embrace.android.embracesdk.fakes.FakeEnvelopeResourceSource +import io.embrace.android.embracesdk.fakes.FakeEventService +import io.embrace.android.embracesdk.fakes.FakeInternalErrorService +import io.embrace.android.embracesdk.fakes.FakeLogMessageService +import io.embrace.android.embracesdk.fakes.FakeMetadataService +import io.embrace.android.embracesdk.fakes.FakePerformanceInfoService +import io.embrace.android.embracesdk.fakes.FakePreferenceService +import io.embrace.android.embracesdk.fakes.FakeSessionPayloadSource +import io.embrace.android.embracesdk.fakes.FakeStartupService +import io.embrace.android.embracesdk.fakes.FakeThermalStatusService +import io.embrace.android.embracesdk.fakes.FakeUserService +import io.embrace.android.embracesdk.fakes.FakeWebViewService +import io.embrace.android.embracesdk.fakes.fakeSessionBehavior +import io.embrace.android.embracesdk.fakes.injection.FakeInitModule +import io.embrace.android.embracesdk.payload.LegacyExceptionError +import io.embrace.android.embracesdk.payload.isV2Payload +import io.embrace.android.embracesdk.session.lifecycle.ProcessState.FOREGROUND +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test + +internal class PayloadFactoryImplTest { + + private var sessionConfig = SessionRemoteConfig() + private lateinit var factory: PayloadFactoryImpl + + @Before + fun setUp() { + val configService = FakeConfigService( + sessionBehavior = fakeSessionBehavior( + remoteCfg = { + RemoteConfig(sessionConfig = sessionConfig) + } + ) + ) + val initModule = FakeInitModule() + val v1Collator = V1PayloadMessageCollator( + configService = FakeConfigService(), + nativeThreadSamplerService = null, + thermalStatusService = FakeThermalStatusService(), + webViewService = FakeWebViewService(), + userService = FakeUserService(), + preferencesService = FakePreferenceService(), + eventService = FakeEventService(), + logMessageService = FakeLogMessageService(), + internalErrorService = FakeInternalErrorService().apply { + currentExceptionError = LegacyExceptionError() + }, + breadcrumbService = FakeBreadcrumbService(), + metadataService = FakeMetadataService(), + performanceInfoService = FakePerformanceInfoService(), + spanSink = initModule.openTelemetryModule.spanSink, + currentSessionSpan = initModule.openTelemetryModule.currentSessionSpan, + sessionPropertiesService = FakeSessionPropertiesService(), + startupService = FakeStartupService() + ) + val v2Collator = V2PayloadMessageCollator( + v1Collator, + SessionEnvelopeSource( + FakeEnvelopeMetadataSource(), + FakeEnvelopeResourceSource(), + FakeSessionPayloadSource() + ) + ) + factory = PayloadFactoryImpl( + v1payloadMessageCollator = v1Collator, + v2payloadMessageCollator = v2Collator, + configService = configService + ) + } + + @Test + fun `legacy payload generated`() { + val session = checkNotNull(factory.startPayloadWithState(FOREGROUND, 0, false)) + val sessionMessage = checkNotNull(factory.endPayloadWithState(FOREGROUND, 0, session)) + assertFalse(sessionMessage.isV2Payload()) + } + + @Test + fun `v2 payload generated`() { + sessionConfig = SessionRemoteConfig(useV2Payload = true) + val session = checkNotNull(factory.startPayloadWithState(FOREGROUND, 0, false)) + val sessionMessage = checkNotNull(factory.endPayloadWithState(FOREGROUND, 0, session)) + assertTrue(sessionMessage.isV2Payload()) + } +}