Skip to content
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

RUMM-2682: Use event write context for Session Replay #1107

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,25 @@ import android.app.Application
import android.content.Context
import com.datadog.android.core.configuration.Configuration
import com.datadog.android.core.internal.CoreFeature
import com.datadog.android.core.internal.persistence.NoOpPersistenceStrategy
import com.datadog.android.core.internal.persistence.PersistenceStrategy
import com.datadog.android.core.internal.utils.sdkLogger
import com.datadog.android.sessionreplay.LifecycleCallback
import com.datadog.android.sessionreplay.RecordWriter
import com.datadog.android.sessionreplay.SessionReplayLifecycleCallback
import com.datadog.android.sessionreplay.internal.domain.SessionReplayRecordPersistenceStrategy
import com.datadog.android.sessionreplay.internal.domain.SessionReplaySerializedRecordWriter
import com.datadog.android.sessionreplay.internal.storage.NoOpRecordWriter
import com.datadog.android.sessionreplay.internal.storage.SessionReplayRecordWriter
import com.datadog.android.sessionreplay.internal.time.SessionReplayTimeProvider
import com.datadog.android.v2.api.SdkCore
import com.datadog.android.v2.core.internal.storage.Storage
import java.util.concurrent.atomic.AtomicBoolean

internal class SessionReplayFeature(
private val coreFeature: CoreFeature,
private val storage: Storage,
sdkCore: SdkCore,
private val sdkCore: SdkCore,
private val sessionReplayCallbackProvider:
(PersistenceStrategy<String>, Configuration.Feature.SessionReplay) ->
LifecycleCallback = { persistenceStrategy, configuration ->
(RecordWriter, Configuration.Feature.SessionReplay) ->
LifecycleCallback = { recordWriter, configuration ->
SessionReplayLifecycleCallback(
SessionReplayRumContextProvider(),
configuration.privacy,
SessionReplaySerializedRecordWriter(persistenceStrategy.getWriter()),
recordWriter,
SessionReplayTimeProvider(coreFeature.contextProvider),
SessionReplayRecordCallback(sdkCore)
)
Expand All @@ -43,7 +39,7 @@ internal class SessionReplayFeature(
private var isRecording = AtomicBoolean(false)
internal var sessionReplayCallback: LifecycleCallback = NoOpLifecycleCallback()

internal var persistenceStrategy: PersistenceStrategy<String> = NoOpPersistenceStrategy()
internal var dataWriter: RecordWriter = NoOpRecordWriter()
internal val initialized = AtomicBoolean(false)

// region SDKFeature
Expand All @@ -53,28 +49,21 @@ internal class SessionReplayFeature(
configuration: Configuration.Feature.SessionReplay
) {
appContext = context
persistenceStrategy = createPersistenceStrategy(storage)
sessionReplayCallback = sessionReplayCallbackProvider(persistenceStrategy, configuration)
dataWriter = createDataWriter()
sessionReplayCallback = sessionReplayCallbackProvider(dataWriter, configuration)
initialized.set(true)
startRecording()
}

internal fun stop() {
stopRecording()
persistenceStrategy = NoOpPersistenceStrategy()
dataWriter = NoOpRecordWriter()
sessionReplayCallback = NoOpLifecycleCallback()
initialized.set(false)
}

private fun createPersistenceStrategy(
storage: Storage
): PersistenceStrategy<String> {
return SessionReplayRecordPersistenceStrategy(
coreFeature.contextProvider,
coreFeature.persistenceExecutorService,
sdkLogger,
storage
)
private fun createDataWriter(): RecordWriter {
return SessionReplayRecordWriter(sdkCore)
}

// endregion
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@
* Copyright 2016-Present Datadog, Inc.
*/

package com.datadog.android.sessionreplay.writer
package com.datadog.android.sessionreplay.internal.storage

import com.datadog.android.sessionreplay.SerializedRecordWriter
import com.datadog.android.sessionreplay.RecordWriter
import com.datadog.android.sessionreplay.processor.EnrichedRecord

internal class RecordWriter(private val jsonStringWriter: SerializedRecordWriter) : Writer {

internal class NoOpRecordWriter : RecordWriter {
override fun write(record: EnrichedRecord) {
jsonStringWriter.write(record.toJson())
// no-op
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
* This product includes software developed at Datadog (https://www.datadoghq.com/).
* Copyright 2016-Present Datadog, Inc.
*/

package com.datadog.android.sessionreplay.internal.storage

import com.datadog.android.sessionreplay.RecordWriter
import com.datadog.android.sessionreplay.internal.SessionReplayFeature
import com.datadog.android.sessionreplay.processor.EnrichedRecord
import com.datadog.android.v2.api.SdkCore

internal class SessionReplayRecordWriter(private val sdkCore: SdkCore) : RecordWriter {
override fun write(record: EnrichedRecord) {
sdkCore.getFeature(SessionReplayFeature.SESSION_REPLAY_FEATURE_NAME)
?.withWriteContext { _, eventBatchWriter ->
val serializedRecord = record.toJson().toByteArray(Charsets.UTF_8)
synchronized(this) {
@Suppress("ThreadSafety") // called from the worker thread
eventBatchWriter.write(serializedRecord, null)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ internal class DatadogCore(
)
features[SessionReplayFeature.SESSION_REPLAY_FEATURE_NAME]?.let {
it.initialize(appContext, configuration.plugins)
sessionReplayFeature = SessionReplayFeature(coreFeature, it.storage, this).also {
sessionReplayFeature = SessionReplayFeature(coreFeature, this).also {
it.initialize(appContext, configuration)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ package com.datadog.android.sessionreplay.internal
import android.app.Application
import com.datadog.android.core.configuration.Configuration
import com.datadog.android.sessionreplay.SessionReplayLifecycleCallback
import com.datadog.android.sessionreplay.internal.domain.SessionReplayRecordPersistenceStrategy
import com.datadog.android.sessionreplay.internal.storage.SessionReplayRecordWriter
import com.datadog.android.utils.config.ApplicationContextTestConfiguration
import com.datadog.android.utils.config.CoreFeatureTestConfiguration
import com.datadog.android.utils.forge.Configurator
import com.datadog.android.v2.api.SdkCore
import com.datadog.android.v2.core.internal.storage.Storage
import com.datadog.tools.unit.annotations.TestConfigurationsProvider
import com.datadog.tools.unit.extensions.TestConfigurationExtension
import com.datadog.tools.unit.extensions.config.TestConfiguration
Expand Down Expand Up @@ -58,34 +57,29 @@ internal class SessionReplayFeatureTest {
@Mock
lateinit var mockSDKCore: SdkCore

@Mock
lateinit var mockStorage: Storage

@BeforeEach
fun `set up`() {
testedFeature = SessionReplayFeature(
coreFeature.mockInstance,
mockStorage,
mockSDKCore
) { _, _ -> mockSessionReplayLifecycleCallback }
}

@Test
fun `𝕄 initialize persistence strategy 𝕎 initialize()`() {
fun `𝕄 initialize writer 𝕎 initialize()`() {
// When
testedFeature.initialize(appContext.mockInstance, fakeConfigurationFeature)

// Then
assertThat(testedFeature.persistenceStrategy)
.isInstanceOf(SessionReplayRecordPersistenceStrategy::class.java)
assertThat(testedFeature.dataWriter)
.isInstanceOf(SessionReplayRecordWriter::class.java)
}

@Test
fun `𝕄 initialize session replay callback 𝕎 initialize()`() {
// Given
testedFeature = SessionReplayFeature(
coreFeature.mockInstance,
mockStorage,
mockSDKCore
)

Expand Down

This file was deleted.

6 changes: 3 additions & 3 deletions library/dd-sdk-android-session-replay/apiSurface
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ interface com.datadog.android.sessionreplay.LifecycleCallback : android.app.Appl
interface com.datadog.android.sessionreplay.RecordCallback
fun onStartRecording()
fun onStopRecording()
interface com.datadog.android.sessionreplay.SerializedRecordWriter
fun write(String)
interface com.datadog.android.sessionreplay.RecordWriter
fun write(com.datadog.android.sessionreplay.processor.EnrichedRecord)
class com.datadog.android.sessionreplay.SessionReplayLifecycleCallback : LifecycleCallback
constructor(com.datadog.android.sessionreplay.utils.RumContextProvider, SessionReplayPrivacy, SerializedRecordWriter, com.datadog.android.sessionreplay.utils.TimeProvider, RecordCallback = NoOpRecordCallback())
constructor(com.datadog.android.sessionreplay.utils.RumContextProvider, SessionReplayPrivacy, RecordWriter, com.datadog.android.sessionreplay.utils.TimeProvider, RecordCallback = NoOpRecordCallback())
override fun onActivityCreated(android.app.Activity, android.os.Bundle?)
override fun onActivityStarted(android.app.Activity)
override fun onActivityResumed(android.app.Activity)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@

package com.datadog.android.sessionreplay

import com.datadog.android.sessionreplay.processor.EnrichedRecord

/**
* Will persists the serialized EnrichedRecord in the allocated Session Replay caching location.
*/
interface SerializedRecordWriter {
interface RecordWriter {
/**
* Writes the serializedRecord to disk.
* @param serializedRecord
* Writes the record to disk.
* @param record to write
*/
fun write(serializedRecord: String)
fun write(record: EnrichedRecord)
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import com.datadog.android.sessionreplay.recorder.ScreenRecorder
import com.datadog.android.sessionreplay.recorder.SnapshotProducer
import com.datadog.android.sessionreplay.utils.RumContextProvider
import com.datadog.android.sessionreplay.utils.TimeProvider
import com.datadog.android.sessionreplay.writer.RecordWriter
import java.util.WeakHashMap
import java.util.concurrent.LinkedBlockingDeque
import java.util.concurrent.ThreadPoolExecutor
Expand All @@ -28,7 +27,7 @@ import java.util.concurrent.TimeUnit
class SessionReplayLifecycleCallback(
rumContextProvider: RumContextProvider,
privacy: SessionReplayPrivacy,
serializedRecordWriter: SerializedRecordWriter,
recordWriter: RecordWriter,
timeProvider: TimeProvider,
private val recordCallback: RecordCallback = NoOpRecordCallback()
) : LifecycleCallback {
Expand All @@ -46,7 +45,7 @@ class SessionReplayLifecycleCallback(
rumContextProvider,
timeProvider,
processorExecutorService,
RecordWriter(serializedRecordWriter)
recordWriter
),
SnapshotProducer(privacy.mapper()),
timeProvider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ package com.datadog.android.sessionreplay.processor

import androidx.annotation.MainThread
import androidx.annotation.WorkerThread
import com.datadog.android.sessionreplay.RecordWriter
import com.datadog.android.sessionreplay.model.MobileSegment
import com.datadog.android.sessionreplay.recorder.Node
import com.datadog.android.sessionreplay.recorder.OrientationChanged
import com.datadog.android.sessionreplay.utils.RumContextProvider
import com.datadog.android.sessionreplay.utils.SessionReplayRumContext
import com.datadog.android.sessionreplay.utils.TimeProvider
import com.datadog.android.sessionreplay.writer.Writer
import java.lang.NullPointerException
import java.util.LinkedList
import java.util.concurrent.ExecutorService
Expand All @@ -25,7 +25,7 @@ internal class SnapshotProcessor(
private val rumContextProvider: RumContextProvider,
private val timeProvider: TimeProvider,
private val executorService: ExecutorService,
private val writer: Writer,
private val writer: RecordWriter,
private val mutationResolver: MutationResolver = MutationResolver(),
private val nodeFlattener: NodeFlattener = NodeFlattener()
) : Processor {
Expand Down

This file was deleted.

Loading