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

Migrate Android SDK to v2 #522

Closed
wants to merge 12 commits into from
3 changes: 1 addition & 2 deletions example/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

buildscript {
ext {
RNNKotlinVersion = "1.5.31"
buildToolsVersion = "33.0.0"
minSdkVersion = 21
compileSdkVersion = 33
Expand All @@ -16,7 +15,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.21"
classpath("com.android.tools.build:gradle:7.3.1")
classpath("com.facebook.react:react-native-gradle-plugin")
}
Expand Down
8 changes: 5 additions & 3 deletions packages/core/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ buildscript {
classpath 'com.android.tools.build:gradle:7.2.2'
// noinspection DifferentKotlinGradleVersion
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jlleitschuh.gradle:ktlint-gradle:10.2.1"
classpath "org.jlleitschuh.gradle:ktlint-gradle:11.5.1"
classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.18.0"
classpath 'com.github.bjoernq:unmockplugin:0.7.9'
}
Expand Down Expand Up @@ -159,7 +159,10 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compileOnly "com.squareup.okhttp3:okhttp:3.12.13"

implementation "com.datadoghq:dd-sdk-android:1.19.2"
implementation "com.datadoghq:dd-sdk-android-rum:2.0.0"
implementation "com.datadoghq:dd-sdk-android-logs:2.0.0"
implementation "com.datadoghq:dd-sdk-android-trace:2.0.0"
implementation "com.datadoghq:dd-sdk-android-webview:2.0.0"
testImplementation "org.junit.platform:junit-platform-launcher:1.6.2"
testImplementation "org.junit.jupiter:junit-jupiter-api:5.6.2"
testImplementation "org.junit.jupiter:junit-jupiter-engine:5.6.2"
Expand Down Expand Up @@ -204,7 +207,6 @@ ktlint {
outputToConsole.set(true)
ignoreFailures.set(false)
enableExperimentalRules.set(false)
additionalEditorconfigFile.set(file("${project.rootDir}/script/config/.editorconfig"))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this option does not exist anymore and the file did not exist

filter {
exclude("**/generated/**")
include("**/kotlin/**")
Expand Down
2 changes: 1 addition & 1 deletion packages/core/android/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
DdSdkReactNative_kotlinVersion=1.6.21
DdSdkReactNative_kotlinVersion=1.7.21
DdSdkReactNative_compileSdkVersion=31
DdSdkReactNative_buildToolsVersion=31.0.0
DdSdkReactNative_targetSdkVersion=31
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,51 @@ package com.datadog.reactnative
import android.content.Context
import com.datadog.android.Datadog
import com.datadog.android.core.configuration.Configuration
import com.datadog.android.core.configuration.Credentials
import com.datadog.android.log.Logs
import com.datadog.android.log.LogsConfiguration
import com.datadog.android.privacy.TrackingConsent
import com.datadog.android.rum.GlobalRum
import com.datadog.android.rum.GlobalRumMonitor
import com.datadog.android.rum.Rum
import com.datadog.android.rum.RumConfiguration
import com.datadog.android.rum.RumMonitor
import com.datadog.android.trace.Trace
import com.datadog.android.trace.TraceConfiguration
import com.datadog.android.webview.WebViewTracking

internal class DatadogSDKWrapper : DatadogWrapper {

// lazy here is on purpose. The thing is that this class will be instantiated even before
// Sdk.initialize is called, but telemetry proxy can be created only after SDK is initialized.
private val telemetryProxy by lazy { Datadog._internalProxy() }

// lazy here is on purpose. The thing is that this class will be instantiated even before
// Sdk.initialize is called, but webview proxy can be created only after SDK is initialized.
private val webViewProxy by lazy {
WebViewTracking._InternalWebViewProxy(Datadog.getInstance())
}

override fun setVerbosity(level: Int) {
Datadog.setVerbosity(level)
}

override fun initialize(
context: Context,
credentials: Credentials,
configuration: Configuration,
consent: TrackingConsent
) {
Datadog.initialize(context, credentials, configuration, consent)
Datadog.initialize(context, configuration, consent)
}

override fun enableRum(configuration: RumConfiguration) {
Rum.enable(configuration)
}

override fun enableLogs(configuration: LogsConfiguration) {
Logs.enable(configuration)
}

override fun enableTrace(configuration: TraceConfiguration) {
Trace.enable(configuration)
}

override fun setUserInfo(
Expand All @@ -38,13 +65,10 @@ internal class DatadogSDKWrapper : DatadogWrapper {
Datadog.setUserInfo(id, name, email, extraInfo)
}

override fun registerRumMonitor(rumMonitor: RumMonitor) {
GlobalRum.registerIfAbsent(rumMonitor)
}

override fun addRumGlobalAttributes(attributes: Map<String, Any?>) {
val rumMonitor = this.getRumMonitor()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
val rumMonitor = this.getRumMonitor()
val rumMonitor = getRumMonitor()

attributes.forEach {
GlobalRum.addAttribute(it.key, it.value)
rumMonitor.addAttribute(it.key, it.value)
}
}

Expand All @@ -53,22 +77,38 @@ internal class DatadogSDKWrapper : DatadogWrapper {
}

override fun telemetryDebug(message: String) {
Datadog._internal._telemetry.debug(message)
// Do not initialize the telemetry proxy before SDK is initialized
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not find an easy way to test this.
It can be a bit dangerous, as if the telemetry (or webview) proxy is initialized before the SDK, then telemetry (or webview) proxy will never work.

I don't know what's the impact of re-creating a proxy on every telemetry and webview event, let me know if you think this logic is worth it or not.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

proxy won't be recreated on every telemetry event, because lazy does initialization only once and then memoized value is returned each time.

However, maybe we can optimize isInitialized call? Datadog.isInitialized is thread-safe call, but if this safety overhead is not needed and this wrapper is called only from the single thread always, maybe we can store initialization flag directly here?

if (isInitialized()) {
telemetryProxy._telemetry.debug(message)
}
}

override fun telemetryError(message: String, stack: String?, kind: String?) {
Datadog._internal._telemetry.error(message, stack, kind)
// Do not initialize the telemetry proxy before SDK is initialized
if (isInitialized()) {
telemetryProxy._telemetry.error(message, stack, kind)
}
}

override fun telemetryError(message: String, throwable: Throwable?) {
Datadog._internal._telemetry.error(message, throwable)
// Do not initialize the telemetry proxy before SDK is initialized
if (isInitialized()) {
telemetryProxy._telemetry.error(message, throwable)
}
}

override fun consumeWebviewEvent(message: String) {
Datadog._internal.consumeWebviewEvent(message)
// Do not initialize the webview proxy before SDK is initialized
if (isInitialized()) {
webViewProxy.consumeWebviewEvent(message)
}
}

override fun isInitialized(): Boolean {
return Datadog.isInitialized()
}

override fun getRumMonitor(): RumMonitor {
return GlobalRumMonitor.get()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ package com.datadog.reactnative

import android.content.Context
import com.datadog.android.core.configuration.Configuration
import com.datadog.android.core.configuration.Credentials
import com.datadog.android.log.LogsConfiguration
import com.datadog.android.privacy.TrackingConsent
import com.datadog.android.rum.GlobalRumMonitor
import com.datadog.android.rum.RumConfiguration
import com.datadog.android.rum.RumMonitor
import com.datadog.android.trace.TraceConfiguration
import java.lang.IllegalArgumentException

/**
Expand Down Expand Up @@ -45,11 +48,37 @@ interface DatadogWrapper {
*/
fun initialize(
context: Context,
credentials: Credentials,
configuration: Configuration,
consent: TrackingConsent
)

/**
* Enables the RUM feature of the SDK.
*
* @param configuration the configuration for the RUM feature
*/
fun enableRum(
configuration: RumConfiguration
)

/**
* Enables the Logs feature of the SDK.
*
* @param configuration the configuration for the Logs feature
*/
fun enableLogs(
configuration: LogsConfiguration
)

/**
* Enables the Trace feature of the SDK.
*
* @param configuration the configuration for the Trace feature
*/
fun enableTrace(
configuration: TraceConfiguration
)

/**
* Sets the user information.
*
Expand All @@ -66,13 +95,6 @@ interface DatadogWrapper {
extraInfo: Map<String, Any?>
)

/**
* Registers a given monitor in [GlobalRum].
*
* @param rumMonitor to register
*/
fun registerRumMonitor(rumMonitor: RumMonitor)

/**
* Adds global attributes.
*
Expand Down Expand Up @@ -109,4 +131,9 @@ interface DatadogWrapper {
* Returns whether the SDK is initialized.
*/
fun isInitialized(): Boolean

/**
* Returns the RUM Monitor for the default SDK core.
*/
fun getRumMonitor(): RumMonitor
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ class DdLogsImplementation(
) {
private val reactNativeLogger: Logger by lazy {
logger ?: Logger.Builder()
.setDatadogLogsEnabled(true)
.setLogcatLogsEnabled(true)
.setLoggerName("DdLogs")
.setName("DdLogs")
.build()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

package com.datadog.reactnative

import com.datadog.android.rum.GlobalRum
import com.datadog.android.rum.RumActionType
import com.datadog.android.rum.RumAttributes
import com.datadog.android.rum.RumErrorSource
Expand All @@ -19,7 +18,7 @@ import java.util.Locale
* The entry point to use Datadog's RUM feature.
*/
@Suppress("TooManyFunctions")
class DdRumImplementation {
class DdRumImplementation(private val datadog: DatadogWrapper = DatadogSDKWrapper()) {
/**
* Start tracking a RUM View.
* @param key The view unique key identifier.
Expand All @@ -37,7 +36,7 @@ class DdRumImplementation {
val attributes = context.toHashMap().toMutableMap().apply {
put(RumAttributes.INTERNAL_TIMESTAMP, timestampMs.toLong())
}
GlobalRum.get().startView(
datadog.getRumMonitor().startView(
key = key,
name = name,
attributes = attributes
Expand All @@ -55,7 +54,7 @@ class DdRumImplementation {
val attributes = context.toHashMap().toMutableMap().apply {
put(RumAttributes.INTERNAL_TIMESTAMP, timestampMs.toLong())
}
GlobalRum.get().stopView(
datadog.getRumMonitor().stopView(
key = key,
attributes = attributes
)
Expand All @@ -79,7 +78,7 @@ class DdRumImplementation {
val attributes = context.toHashMap().toMutableMap().apply {
put(RumAttributes.INTERNAL_TIMESTAMP, timestampMs.toLong())
}
GlobalRum.get().startUserAction(
datadog.getRumMonitor().startAction(
type = type.asRumActionType(),
name = name,
attributes = attributes
Expand All @@ -104,7 +103,7 @@ class DdRumImplementation {
val attributes = context.toHashMap().toMutableMap().apply {
put(RumAttributes.INTERNAL_TIMESTAMP, timestampMs.toLong())
}
GlobalRum.get().stopUserAction(
datadog.getRumMonitor().stopAction(
type = type.asRumActionType(),
name = name,
attributes = attributes
Expand All @@ -129,7 +128,7 @@ class DdRumImplementation {
val attributes = context.toHashMap().toMutableMap().apply {
put(RumAttributes.INTERNAL_TIMESTAMP, timestampMs.toLong())
}
GlobalRum.get().addUserAction(
datadog.getRumMonitor().addAction(
type = type.asRumActionType(),
name = name,
attributes = attributes
Expand Down Expand Up @@ -157,7 +156,7 @@ class DdRumImplementation {
val attributes = context.toHashMap().toMutableMap().apply {
put(RumAttributes.INTERNAL_TIMESTAMP, timestampMs.toLong())
}
GlobalRum.get().startResource(
datadog.getRumMonitor().startResource(
key = key,
method = method,
url = url,
Expand Down Expand Up @@ -193,7 +192,7 @@ class DdRumImplementation {
} else {
size.toLong()
}
GlobalRum.get().stopResource(
datadog.getRumMonitor().stopResource(
key = key,
statusCode = statusCode.toInt(),
kind = kind.asRumResourceKind(),
Expand Down Expand Up @@ -223,7 +222,7 @@ class DdRumImplementation {
val attributes = context.toHashMap().toMutableMap().apply {
put(RumAttributes.INTERNAL_TIMESTAMP, timestampMs.toLong())
}
GlobalRum.get().addErrorWithStacktrace(
datadog.getRumMonitor().addErrorWithStacktrace(
message = message,
source = source.asErrorSource(),
stacktrace = stacktrace,
Expand All @@ -237,28 +236,28 @@ class DdRumImplementation {
* @param name The name of the new custom timing attribute. Timings can be nested up to 8 levels deep. Names using more than 8 levels will be sanitized by SDK.
*/
fun addTiming(name: String, promise: Promise) {
GlobalRum.get().addTiming(name)
datadog.getRumMonitor().addTiming(name)
promise.resolve(null)
}

/**
* Stops the current RUM Session.
*/
fun stopSession(promise: Promise) {
GlobalRum.get().stopSession()
datadog.getRumMonitor().stopSession()
promise.resolve(null)
}

/**
* Adds result of evaluating a feature flag to the view.
* Feature flag evaluations are local to the active view and are cleared when the view is stopped.
* @param name The name of the feature flag
* @param value The value the feature flag evaluated to, encapsulated in a Map
* @param valueAsMap The value the feature flag evaluated to, encapsulated in a Map
*/
fun addFeatureFlagEvaluation(name: String, value: ReadableMap, promise: Promise) {
val value = value.toHashMap()["value"]
fun addFeatureFlagEvaluation(name: String, valueAsMap: ReadableMap, promise: Promise) {
val value = valueAsMap.toHashMap()["value"]
if (value != null) {
GlobalRum.get().addFeatureFlagEvaluation(name, value)
datadog.getRumMonitor().addFeatureFlagEvaluation(name, value)
}
promise.resolve(null)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ package com.datadog.reactnative
data class DdSdkConfiguration(
val clientToken: String,
val env: String,
val applicationId: String? = null,
val applicationId: String,
val nativeCrashReportEnabled: Boolean? = null,
val nativeLongTaskThresholdMs: Double? = null,
val longTaskThresholdMs: Double? = null,
Expand Down
Loading