Skip to content

Commit

Permalink
Merge pull request #974 from DataDog/mconstantin/rumm-2267/session-re…
Browse files Browse the repository at this point in the history
…play-public-api

RUMM-2267 Add Session Replay public API
  • Loading branch information
mariusc83 authored Jul 11, 2022
2 parents 244001a + 97761af commit ef40e6c
Show file tree
Hide file tree
Showing 19 changed files with 245 additions and 49 deletions.
33 changes: 17 additions & 16 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ tasks.register("assembleAll") {
":dd-sdk-android-ktx:assemble",
":dd-sdk-android-ndk:assemble",
":dd-sdk-android-rx:assemble",
":dd-sdk-android-session-replay:assemble",
":dd-sdk-android-sqldelight:assemble",
":dd-sdk-android-timber:assemble",
":dd-sdk-android-tv:assemble"
":dd-sdk-android-tv:assemble",
":library:dd-sdk-android-session-replay:assemble"
)
}

Expand All @@ -93,10 +93,10 @@ tasks.register("unitTestRelease") {
":dd-sdk-android-ktx:testReleaseUnitTest",
":dd-sdk-android-ndk:testReleaseUnitTest",
":dd-sdk-android-rx:testReleaseUnitTest",
":dd-sdk-android-session-replay:testReleaseUnitTest",
":dd-sdk-android-sqldelight:testReleaseUnitTest",
":dd-sdk-android-timber:testReleaseUnitTest",
":dd-sdk-android-tv:testReleaseUnitTest"
":dd-sdk-android-tv:testReleaseUnitTest",
":library:dd-sdk-android-session-replay:testReleaseUnitTest"
)
}

Expand All @@ -110,10 +110,10 @@ tasks.register("unitTestDebug") {
":dd-sdk-android-ktx:testDebugUnitTest",
":dd-sdk-android-ndk:testDebugUnitTest",
":dd-sdk-android-rx:testDebugUnitTest",
":dd-sdk-android-session-replay:testDebugUnitTest",
":dd-sdk-android-sqldelight:testDebugUnitTest",
":dd-sdk-android-timber:testDebugUnitTest",
":dd-sdk-android-tv:testDebugUnitTest"
":dd-sdk-android-tv:testDebugUnitTest",
":library:dd-sdk-android-session-replay:testDebugUnitTest"
)
}

Expand Down Expand Up @@ -143,12 +143,12 @@ tasks.register("ktlintCheckAll") {
":dd-sdk-android-ktx:ktlintCheck",
":dd-sdk-android-ndk:ktlintCheck",
":dd-sdk-android-rx:ktlintCheck",
":dd-sdk-android-session-replay:ktlintCheck",
":dd-sdk-android-sqldelight:ktlintCheck",
":dd-sdk-android-timber:ktlintCheck",
":dd-sdk-android-tv:ktlintCheck",
":instrumented:integration:ktlintCheck",
":instrumented:nightly-tests:ktlintCheck",
":library:dd-sdk-android-session-replay:ktlintCheck",
":tools:detekt:ktlintCheck",
":tools:unit:ktlintCheck"
)
Expand All @@ -164,10 +164,10 @@ tasks.register("lintCheckAll") {
":dd-sdk-android-ktx:lintRelease",
":dd-sdk-android-ndk:lintRelease",
":dd-sdk-android-rx:lintRelease",
":dd-sdk-android-session-replay:lintRelease",
":dd-sdk-android-sqldelight:lintRelease",
":dd-sdk-android-timber:lintRelease",
":dd-sdk-android-tv:lintRelease"
":dd-sdk-android-tv:lintRelease",
":library:dd-sdk-android-session-replay:lintRelease"
)
}

Expand All @@ -181,10 +181,10 @@ tasks.register("checkThirdPartyLicensesAll") {
":dd-sdk-android-ktx:checkThirdPartyLicences",
":dd-sdk-android-ndk:checkThirdPartyLicences",
":dd-sdk-android-rx:checkThirdPartyLicences",
":dd-sdk-android-session-replay:checkThirdPartyLicences",
":dd-sdk-android-sqldelight:checkThirdPartyLicences",
":dd-sdk-android-timber:checkThirdPartyLicences",
":dd-sdk-android-tv:checkThirdPartyLicences"
":dd-sdk-android-tv:checkThirdPartyLicences",
":library:dd-sdk-android-session-replay:checkThirdPartyLicences"
)
}

Expand All @@ -198,10 +198,10 @@ tasks.register("checkApiSurfaceChangesAll") {
":dd-sdk-android-ktx:checkApiSurfaceChanges",
":dd-sdk-android-ndk:checkApiSurfaceChanges",
":dd-sdk-android-rx:checkApiSurfaceChanges",
":dd-sdk-android-session-replay:checkApiSurfaceChanges",
":dd-sdk-android-sqldelight:checkApiSurfaceChanges",
":dd-sdk-android-timber:checkApiSurfaceChanges",
":dd-sdk-android-tv:checkApiSurfaceChanges"
":dd-sdk-android-tv:checkApiSurfaceChanges",
":library:dd-sdk-android-session-replay:checkApiSurfaceChanges"
)
}

Expand All @@ -216,11 +216,11 @@ tasks.register("detektAll") {
":dd-sdk-android-ndk:detektMain",
":dd-sdk-android-rx:detektMain",
":dd-sdk-android-sqldelight:detektMain",
":dd-sdk-android-session-replay:detektMain",
":dd-sdk-android-timber:detektMain",
":dd-sdk-android-tv:detektMain",
":instrumented:integration:detekt",
":instrumented:nightly-tests:detekt",
":library:dd-sdk-android-session-replay:detektMain",
":tools:unit:detekt"
)
}
Expand All @@ -238,8 +238,9 @@ tasks.register("koverReportAll") {
":dd-sdk-android-session-replay:koverXmlReport",
":dd-sdk-android-sqldelight:koverXmlReport",
":dd-sdk-android-timber:koverXmlReport",
":dd-sdk-android-tv:koverXmlReport"
)
":dd-sdk-android-tv:koverXmlReport",
":library:dd-sdk-android-session-replay:koverXmlReport",
)
}

tasks.register("instrumentTestAll") {
Expand Down
7 changes: 6 additions & 1 deletion dd-sdk-android/apiSurface
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ object com.datadog.android.DatadogEndpoint
const val NTP_1: String
const val NTP_2: String
const val NTP_3: String
const val SESSION_REPLAY_US1: String
const val SESSION_REPLAY_US3: String
const val SESSION_REPLAY_US5: String
const val SESSION_REPLAY_EU1: String
class com.datadog.android.DatadogEventListener : okhttp3.EventListener
override fun callStart(okhttp3.Call)
override fun dnsStart(okhttp3.Call, String)
Expand Down Expand Up @@ -74,7 +78,7 @@ enum com.datadog.android.core.configuration.BatchSize
- LARGE
data class com.datadog.android.core.configuration.Configuration
class Builder
constructor(Boolean, Boolean, Boolean, Boolean)
constructor(Boolean, Boolean, Boolean, Boolean, Boolean)
fun build(): Configuration
fun setUseDeveloperModeWhenDebuggable(Boolean): Builder
fun setFirstPartyHosts(List<String>): Builder
Expand Down Expand Up @@ -295,6 +299,7 @@ enum com.datadog.android.plugin.Feature
- CRASH
- TRACE
- RUM
- SESSION_REPLAY
enum com.datadog.android.privacy.TrackingConsent
- GRANTED
- NOT_GRANTED
Expand Down
2 changes: 2 additions & 0 deletions dd-sdk-android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ android {
}

dependencies {
// TODO Invert the Dependency Once SDKCore is ready. RUMM-2338
api(project(":library:dd-sdk-android-session-replay"))
implementation(libs.kotlin)

// Network
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,40 @@ 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 want to point to
* [app.datadoghq.com](https://app.datadoghq.com)
* @see [Configuration]
*/
const val SESSION_REPLAY_US1: String = "https://session-replay.browser-intake-datadoghq.com"

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

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

/**
* The EU1 endpoint for Session Replay (EU based servers).
* Use this in your [Configuration] if you want to point to
* [app.datadoghq.eu](https://app.datadoghq.eu)
* @see [Configuration]
*/
const val SESSION_REPLAY_EU1: String = "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 @@ -117,18 +123,21 @@ internal constructor(
* @param tracesEnabled whether Spans are tracked and sent to Datadog
* @param crashReportsEnabled whether crashes are tracked and sent to Datadog
* @param rumEnabled whether RUM events are tracked and sent to Datadog
* @param sessionReplayEnabled whether RUM Session Replay is enabled or not
*/
@Suppress("TooManyFunctions")
class Builder(
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 +154,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 +441,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 +697,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 +754,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("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,17 @@
/*
* 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: This will be switched to a Serializer<Record> once the models
// will be in place. RUMM-2330"
return null
}
}
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)
)
Loading

0 comments on commit ef40e6c

Please sign in to comment.