Skip to content
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
2 changes: 1 addition & 1 deletion example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ SPEC CHECKSUMS:
DatadogInternal: b9217da25018284c087a2ed4b9bb3b0f26c767c0
DatadogLogs: 3b4132eefa67f196bb3ab2d603c1a2acd1292615
DatadogRUM: 8845815ba89f5ab8ceee765ee268f7de36f3e35d
DatadogSDKReactNative: df8874f04262606461d8db6b48d6be145d3bf483
DatadogSDKReactNative: 12490ebd711f2133bd7e12eaaab9bdc8075aca24
DatadogSDKReactNativeSessionReplay: ad782e91dce3671c22bbd33f681db62d214a8e68
DatadogSessionReplay: f189054bd2fc2d14c487fd614f04b2b8041dd81f
DatadogTrace: a63da746c609bd4c683bca61a94429889e33b11e
Expand Down
3 changes: 2 additions & 1 deletion packages/core/DatadogSDKReactNative.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ Pod::Spec.new do |s|
s.dependency 'DatadogWebViewTracking', '~> 2.7.1'

s.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'ios/Tests/*.swift'
test_spec.source_files = 'ios/Tests/**/*.{swift,json}'
test_spec.resources = 'ios/Tests/Fixtures'
end


Expand Down
1 change: 1 addition & 0 deletions packages/core/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ dependencies {
implementation "com.datadoghq:dd-sdk-android-logs:2.6.2"
implementation "com.datadoghq:dd-sdk-android-trace:2.6.2"
implementation "com.datadoghq:dd-sdk-android-webview:2.6.2"
implementation "com.google.code.gson:gson:2.10.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
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,48 @@ data class DdSdkConfiguration(
val firstPartyHosts: Map<String, Set<TracingHeaderType>>? = null
)

internal data class JSONConfigurationFile(
Comment thread
louiszawadzki marked this conversation as resolved.
val configuration: JSONDdSdkConfiguration
)

internal data class JSONDdSdkConfiguration(
val clientToken: String,
val env: String,
val applicationId: String,
val nativeCrashReportEnabled: Boolean? = null,
val nativeLongTaskThresholdMs: Double? = null,
val longTaskThresholdMs: Double? = null,
val sessionSamplingRate: Double? = null,
val site: String? = null,
val trackingConsent: String? = null,
val telemetrySampleRate: Double? = null,
val vitalsUpdateFrequency: String? = null,
val trackFrustrations: Boolean? = null,
val uploadFrequency: String? = null,
val batchSize: String? = null,
val trackBackgroundEvents: Boolean? = null,
val customEndpoints: CustomEndpoints? = null,
val nativeViewTracking: Boolean? = null,
val nativeInteractionTracking: Boolean? = null,
val verbosity: String? = null,
val proxy: JSONProxyConfiguration? = null,
val serviceName: String? = null,
val firstPartyHosts: List<JSONFirstPartyHost>? = null
)

internal data class JSONProxyConfiguration(
val type: String,
val address: String,
val port: Int,
val username: String? = null,
val password: String? = null
)

internal data class JSONFirstPartyHost(
val match: String,
val propagatorTypes: List<String>
)

/**
* Additional configuration data for Datadog telemetry.
* @param initializationType Type of initialization used.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Copyright 2016-Present Datadog, Inc.
*/

@file:Suppress("TooManyFunctions")
package com.datadog.reactnative

import android.util.Log
Expand Down Expand Up @@ -75,42 +76,87 @@ internal fun ReadableMap.asProxyConfig(): Pair<Proxy, ProxyAuthenticator?>? {
port = getInt("port")
}

val type =
getString("type")?.let {
when (it.lowercase(Locale.US)) {
"http", "https" -> Proxy.Type.HTTP
"socks" -> Proxy.Type.SOCKS
else -> {
Log.w(
DdSdk::class.java.canonicalName,
"Unknown proxy type given: $it, skipping proxy configuration."
)
null
}
}
}
val type = getString("type")

val proxy =
if (address != null && port != null && type != null) {
Proxy(type, InetSocketAddress(address, port))
} else {
return null
}
return if (address != null && port != null && type != null) {
buildProxyConfig(
type,
address,
port,
getString("username"),
getString("password")
)
} else {
null
}
}

val username = getString("username")
val password = getString("password")
internal fun ReadableArray.asFirstPartyHosts(): Map<String, Set<TracingHeaderType>> {
val firstPartyHosts = this.toArrayList() as List<ReadableMap>
return firstPartyHosts.mapNotNull<ReadableMap, JSONFirstPartyHost> {
val match = it.getString("match")
val propagatorTypes = it.getArray("propagatorTypes")
if (match != null && propagatorTypes != null) {
JSONFirstPartyHost(match, propagatorTypes.toArrayList() as List<String>)
} else null
}.asFirstPartyHosts()
}

val authenticator =
if (username != null && password != null) {
ProxyAuthenticator(username, password)
} else {
null
}
internal object DefaultConfiguration {
const val nativeCrashReportEnabled = false
const val sessionSamplingRate = 100.0
const val site = "US1"
const val longTaskThresholdMs = 0.0
const val nativeLongTaskThresholdMs = 200.0
const val nativeViewTracking = false
const val nativeInteractionTracking = false
const val trackingConsent = "GRANTED"
const val telemetrySampleRate = 20.0
const val vitalsUpdateFrequency = "AVERAGE"
const val trackFrustrations = true
const val uploadFrequency = "AVERAGE"
const val batchSize = "MEDIUM"
const val trackBackgroundEvents = false
}

return Pair(proxy, authenticator)
@Suppress("ComplexMethod")
internal fun JSONDdSdkConfiguration.asDdSdkConfiguration(): DdSdkConfiguration {
return DdSdkConfiguration(
this.clientToken,
this.env,
this.applicationId,
this.nativeCrashReportEnabled ?: DefaultConfiguration.nativeCrashReportEnabled,
this.nativeLongTaskThresholdMs ?: DefaultConfiguration.nativeLongTaskThresholdMs,
this.longTaskThresholdMs ?: DefaultConfiguration.longTaskThresholdMs,
this.sessionSamplingRate ?: DefaultConfiguration.sessionSamplingRate,
this.site ?: DefaultConfiguration.site,
this.trackingConsent ?: DefaultConfiguration.trackingConsent,
this.telemetrySampleRate ?: DefaultConfiguration.telemetrySampleRate,
this.vitalsUpdateFrequency ?: DefaultConfiguration.vitalsUpdateFrequency,
this.trackFrustrations ?: DefaultConfiguration.trackFrustrations,
this.uploadFrequency ?: DefaultConfiguration.uploadFrequency,
this.batchSize ?: DefaultConfiguration.batchSize,
this.trackBackgroundEvents ?: DefaultConfiguration.trackBackgroundEvents,
this.customEndpoints,
mapOf(
"_dd.source" to "react-native",
"_dd.sdk_version" to SDK_VERSION
),
null,
this.nativeViewTracking ?: DefaultConfiguration.nativeViewTracking,
this.nativeInteractionTracking ?: DefaultConfiguration.nativeInteractionTracking,
this.verbosity,
this.proxy?.asProxyConfig(),
this.serviceName,
this.firstPartyHosts?.asFirstPartyHosts()
)
}

internal fun ReadableArray.asFirstPartyHosts(): Map<String, Set<TracingHeaderType>> {
internal fun JSONProxyConfiguration.asProxyConfig(): Pair<Proxy, ProxyAuthenticator?>? {
return buildProxyConfig(type, address, port, username, password)
}

internal fun List<JSONFirstPartyHost>.asFirstPartyHosts(): Map<String, Set<TracingHeaderType>> {
/**
* Adapts the data format from the React Native SDK configuration to match with the Android
* SDK configuration. For example:
Expand All @@ -120,26 +166,23 @@ internal fun ReadableArray.asFirstPartyHosts(): Map<String, Set<TracingHeaderTyp
*/
val firstPartyHostsWithHeaderTypes = mutableMapOf<String, MutableSet<TracingHeaderType>>()

val firstPartyHosts = this.toArrayList() as List<ReadableMap>
for (it in firstPartyHosts) {
val match = it.getString("match")
val propagatorTypes = it.getArray("propagatorTypes")?.asTracingHeaderTypes()
if (match != null && propagatorTypes != null && propagatorTypes.isNotEmpty()) {
val hostMatch = firstPartyHostsWithHeaderTypes[match]
for (host in this) {
if (host.propagatorTypes.isNotEmpty()) {
val hostMatch = firstPartyHostsWithHeaderTypes[host.match]
if (hostMatch != null) {
hostMatch.addAll(propagatorTypes)
hostMatch.addAll(host.propagatorTypes.asTracingHeaderTypes())
} else {
firstPartyHostsWithHeaderTypes[match] = propagatorTypes.toMutableSet()
firstPartyHostsWithHeaderTypes[host.match] = host.propagatorTypes.asTracingHeaderTypes().toMutableSet()
}
}
}

return firstPartyHostsWithHeaderTypes
}

internal fun ReadableArray.asTracingHeaderTypes(): Set<TracingHeaderType> {
return this.toArrayList().mapNotNull {
when (it) {
internal fun List<String>.asTracingHeaderTypes(): Set<TracingHeaderType> {
return this.mapNotNull {
when (it.lowercase()) {
"datadog" -> TracingHeaderType.DATADOG
"b3" -> TracingHeaderType.B3
"b3multi" -> TracingHeaderType.B3MULTI
Expand Down Expand Up @@ -189,3 +232,32 @@ internal fun CustomEndpoints.toReadableMap(): ReadableMap {
trace?.let { map.putString("trace", it) }
return map
}

private fun buildProxyConfig(type: String, address: String, port: Int, username: String?, password: String?): Pair<Proxy, ProxyAuthenticator?>? {
val proxyType = when (type.lowercase(Locale.US)) {
"http", "https" -> Proxy.Type.HTTP
"socks" -> Proxy.Type.SOCKS
else -> {
Log.w(
DdSdk::class.java.canonicalName,
"Unknown proxy type given: $type, skipping proxy configuration."
)
null
}
}

if (proxyType == null) {
return null
}

val proxy = Proxy(proxyType, InetSocketAddress(address, port))

val authenticator =
if (username != null && password != null) {
ProxyAuthenticator(username, password)
} else {
null
}

return Pair(proxy, authenticator)
}
Loading