Skip to content

Commit

Permalink
Add the Session Replay Public API
Browse files Browse the repository at this point in the history
  • Loading branch information
mariusc83 committed Jul 7, 2022
1 parent 0e57e76 commit 1dfdc06
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,36 @@ object DatadogEndpoint {
const val NTP_3: String = "3.datadog.pool.ntp.org"

// endregion

// region Session Replay

/**
* The US1 endpoint for Session Replay (US based servers).
* Use this in your [Configuration] if you log on [app.datadoghq.com](https://app.datadoghq.com)
* @see [Configuration]
*/
const val SESSION_REPLAY_US1 = "https://session-replay.browser-intake-datadoghq.com"

/**
* The US3 endpoint for Session Replay (US based servers).
* Use this in your [Configuration] if you log on [us3.datadoghq.com](https://us3.datadoghq.com)
* @see [Configuration]
*/
const val SESSION_REPLAY_US3 = "https://session-replay.browser-intake-us3-datadoghq.com"

/**
* The US5 endpoint for Session replay (US based servers).
* Use this in your [Configuration] if you log on [us5.datadoghq.com](https://us5.datadoghq.com)
* @see [Configuration]
*/
const val SESSION_REPLAY_US5 = "https://session-replay.browser-intake-us5-datadoghq.com"

/**
* The EU1 endpoint for Session Replay (EU based servers).
* Use this in your [Configuration] if you log on [app.datadoghq.eu](https://app.datadoghq.eu)
* @see [Configuration]
*/
const val SESSION_REPLAY_EU1 = "https://session-replay.browser-intake-datadoghq.eu"

// endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ internal constructor(
internal val tracesConfig: Feature.Tracing?,
internal val crashReportConfig: Feature.CrashReport?,
internal val rumConfig: Feature.RUM?,
internal val sessionReplayConfig: Feature.SessionReplay?,
internal val additionalConfig: Map<String, Any>
) {

Expand Down Expand Up @@ -107,6 +108,11 @@ internal constructor(
val rumEventMapper: EventMapper<Any>,
val backgroundEventTracking: Boolean
) : Feature()

internal data class SessionReplay(
override val endpointUrl: String,
override val plugins: List<DatadogPlugin>
) : Feature()
}

// region Builder
Expand All @@ -123,12 +129,14 @@ internal constructor(
val logsEnabled: Boolean,
val tracesEnabled: Boolean,
val crashReportsEnabled: Boolean,
val rumEnabled: Boolean
val rumEnabled: Boolean,
val sessionReplayEnabled: Boolean
) {
private var logsConfig: Feature.Logs = DEFAULT_LOGS_CONFIG
private var tracesConfig: Feature.Tracing = DEFAULT_TRACING_CONFIG
private var crashReportConfig: Feature.CrashReport = DEFAULT_CRASH_CONFIG
private var rumConfig: Feature.RUM = DEFAULT_RUM_CONFIG
private var sessionReplayConfig: Feature.SessionReplay = DEFAULT_SESSION_REPLAY_CONFIG
private var additionalConfig: Map<String, Any> = emptyMap()

private var coreConfig = DEFAULT_CORE_CONFIG
Expand All @@ -145,6 +153,7 @@ internal constructor(
tracesConfig = if (tracesEnabled) tracesConfig else null,
crashReportConfig = if (crashReportsEnabled) crashReportConfig else null,
rumConfig = if (rumEnabled) rumConfig else null,
sessionReplayConfig = if (sessionReplayEnabled) sessionReplayConfig else null,
additionalConfig = additionalConfig
)
}
Expand Down Expand Up @@ -431,6 +440,9 @@ internal constructor(
PluginFeature.CRASH -> crashReportConfig = crashReportConfig.copy(
plugins = crashReportConfig.plugins + plugin
)
PluginFeature.SESSION_REPLAY ->
sessionReplayConfig =
sessionReplayConfig.copy(plugins = sessionReplayConfig.plugins + plugin)
}
}
return this
Expand Down Expand Up @@ -684,6 +696,7 @@ internal constructor(
PluginFeature.TRACE -> tracesEnabled
PluginFeature.CRASH -> crashReportsEnabled
PluginFeature.RUM -> rumEnabled
PluginFeature.SESSION_REPLAY -> sessionReplayEnabled
}
if (featureEnabled) {
@Suppress("UnsafeThirdPartyFunctionCall") // internal safe call
Expand Down Expand Up @@ -740,6 +753,10 @@ internal constructor(
rumEventMapper = NoOpEventMapper(),
backgroundEventTracking = false
)
internal val DEFAULT_SESSION_REPLAY_CONFIG = Feature.SessionReplay(
endpointUrl = DatadogEndpoint.SESSION_REPLAY_US1,
plugins = emptyList()
)

internal const val ERROR_FEATURE_DISABLED = "The %s feature has been disabled in your " +
"Configuration.Builder, but you're trying to edit the RUM configuration with the " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ enum class Feature(internal val featureName: String) {
LOG("Logging"),
CRASH("Crash Reporting"),
TRACE("Tracing"),
RUM("RUM")
RUM("RUM"),
SESSION_REPLAY(featureName = "Session Replay")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* 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

import android.content.Context
import com.datadog.android.core.configuration.Configuration
import com.datadog.android.core.internal.CoreFeature
import com.datadog.android.core.internal.SdkFeature
import com.datadog.android.core.internal.net.DataUploader
import com.datadog.android.core.internal.net.NoOpDataUploader
import com.datadog.android.core.internal.persistence.PersistenceStrategy
import com.datadog.android.core.internal.utils.sdkLogger
import com.datadog.android.sessionreplay.internal.domain.SessionReplayRecordPersistenceStrategy

internal class SessionReplayFeature(coreFeature: CoreFeature) :
SdkFeature<Any, Configuration.Feature.SessionReplay>(coreFeature) {

override fun createPersistenceStrategy(
context: Context,
configuration: Configuration.Feature.SessionReplay
): PersistenceStrategy<Any> {
return SessionReplayRecordPersistenceStrategy(
coreFeature.trackingConsentProvider,
context,
coreFeature.persistenceExecutorService,
sdkLogger,
coreFeature.localDataEncryption
)
}

override fun createUploader(configuration: Configuration.Feature.SessionReplay): DataUploader {
// TODO: This will be added later in RUMM-2273
return NoOpDataUploader()
}

companion object {
const val SESSION_REPLAY_FEATURE_NAME = "session-replay"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* 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.domain

import com.datadog.android.core.internal.persistence.Serializer

internal class RecordSerializer : Serializer<Any> {
override fun serialize(model: Any): String? {
TODO(
"Not yet implemented. This will be switched to a Serializer<Record> once the" +
"models will be in place."
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* 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.domain

import android.content.Context
import com.datadog.android.core.internal.persistence.PayloadDecoration
import com.datadog.android.core.internal.persistence.file.FileMover
import com.datadog.android.core.internal.persistence.file.advanced.FeatureFileOrchestrator
import com.datadog.android.core.internal.persistence.file.batch.BatchFilePersistenceStrategy
import com.datadog.android.core.internal.persistence.file.batch.BatchFileReaderWriter
import com.datadog.android.core.internal.privacy.ConsentProvider
import com.datadog.android.log.Logger
import com.datadog.android.security.Encryption
import com.datadog.android.sessionreplay.internal.SessionReplayFeature
import java.util.concurrent.ExecutorService

internal class SessionReplayRecordPersistenceStrategy(
consentProvider: ConsentProvider,
context: Context,
executorService: ExecutorService,
internalLogger: Logger,
localDataEncryption: Encryption?
) : BatchFilePersistenceStrategy<Any>(
FeatureFileOrchestrator(
consentProvider,
context,
SessionReplayFeature.SESSION_REPLAY_FEATURE_NAME,
executorService,
internalLogger
),
executorService,
RecordSerializer(),
PayloadDecoration.NEW_LINE_DECORATION,
internalLogger,
BatchFileReaderWriter.create(internalLogger, localDataEncryption),
FileMover(internalLogger)
)
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import com.datadog.android.log.internal.LogsFeature
import com.datadog.android.log.model.LogEvent
import com.datadog.android.privacy.TrackingConsent
import com.datadog.android.rum.internal.RumFeature
import com.datadog.android.sessionreplay.internal.SessionReplayFeature
import com.datadog.android.tracing.internal.TracingFeature
import com.datadog.android.v2.api.FeatureScope
import com.datadog.android.v2.api.FeatureStorageConfiguration
Expand Down Expand Up @@ -60,6 +61,7 @@ class DatadogCore(
null
internal var webViewLogsFeature: SdkFeature<JsonObject, Configuration.Feature.Logs>? = null
internal var webViewRumFeature: SdkFeature<Any, Configuration.Feature.RUM>? = null
internal var sessionReplayFeature: SdkFeature<Any, Configuration.Feature.SessionReplay>? = null

init {
val isDebug = isAppDebuggable(context)
Expand Down Expand Up @@ -176,6 +178,7 @@ class DatadogCore(
initializeTracingFeature(mutableConfig.tracesConfig, appContext)
initializeRumFeature(mutableConfig.rumConfig, appContext)
initializeCrashReportFeature(mutableConfig.crashReportConfig, appContext)
initializeSessionReplayFeature(mutableConfig.sessionReplayConfig, appContext)

coreFeature.ndkCrashHandler.handleNdkCrash(
logsFeature?.persistenceStrategy?.getWriter() ?: NoOpDataWriter(),
Expand Down Expand Up @@ -252,6 +255,16 @@ class DatadogCore(
}
}

private fun initializeSessionReplayFeature(
configuration: Configuration.Feature.SessionReplay?,
appContext: Context
) {
if (configuration != null) {
sessionReplayFeature = SessionReplayFeature(coreFeature)
sessionReplayFeature?.initialize(appContext, configuration)
}
}

@Suppress("FunctionMaxLength")
private fun modifyConfigurationForDeveloperDebug(configuration: Configuration): Configuration {
return configuration.copy(
Expand Down
Loading

0 comments on commit 1dfdc06

Please sign in to comment.