Skip to content

Commit dcb1457

Browse files
authored
Merge pull request #2504 from DataDog/tvaleev/RUM-8375/optinal-telemetry-envent
[RUM-8375] View ended instrumentation type attribute support
2 parents 308b80b + b0f79d2 commit dcb1457

File tree

26 files changed

+814
-145
lines changed

26 files changed

+814
-145
lines changed

dd-sdk-android-core/api/apiSurface

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,25 @@ sealed class com.datadog.android.core.feature.event.JvmCrash
255255
constructor(Throwable, String, List<ThreadDump>)
256256
data class com.datadog.android.core.feature.event.ThreadDump
257257
constructor(String, String, String, Boolean)
258+
interface com.datadog.android.core.internal.attributes.LocalAttribute
259+
enum Key
260+
constructor(String)
261+
- CREATION_SAMPLING_RATE
262+
- REPORTING_SAMPLING_RATE
263+
- VIEW_SCOPE_INSTRUMENTATION_TYPE
264+
interface Constant
265+
val key: Key
266+
val value: Any
267+
fun MutableMap<String, Any?>.enrichWithConstantAttribute(LocalAttribute.Constant)
268+
fun MutableMap<String, Any?>.enrichWithNonNullAttribute(LocalAttribute.Key, Any?)
269+
fun MutableMap<String, Any?>.enrichWithLocalAttribute(LocalAttribute.Key, Any?)
270+
enum com.datadog.android.core.internal.attributes.ViewScopeInstrumentationType : LocalAttribute.Constant
271+
constructor(String)
272+
- MANUAL
273+
- COMPOSE
274+
- ACTIVITY
275+
- FRAGMENT
276+
override val key: LocalAttribute.Key
258277
class com.datadog.android.core.internal.net.DefaultFirstPartyHostHeaderTypeResolver : FirstPartyHostHeaderTypeResolver
259278
constructor(Map<String, Set<com.datadog.android.trace.TracingHeaderType>>)
260279
override fun isFirstPartyUrl(okhttp3.HttpUrl): Boolean

dd-sdk-android-core/api/dd-sdk-android-core.api

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,41 @@ public final class com/datadog/android/core/feature/event/ThreadDump {
716716
public fun toString ()Ljava/lang/String;
717717
}
718718

719+
public abstract interface class com/datadog/android/core/internal/attributes/LocalAttribute {
720+
}
721+
722+
public abstract interface class com/datadog/android/core/internal/attributes/LocalAttribute$Constant {
723+
public abstract fun getKey ()Lcom/datadog/android/core/internal/attributes/LocalAttribute$Key;
724+
public abstract fun getValue ()Ljava/lang/Object;
725+
}
726+
727+
public final class com/datadog/android/core/internal/attributes/LocalAttribute$Key : java/lang/Enum {
728+
public static final field CREATION_SAMPLING_RATE Lcom/datadog/android/core/internal/attributes/LocalAttribute$Key;
729+
public static final field REPORTING_SAMPLING_RATE Lcom/datadog/android/core/internal/attributes/LocalAttribute$Key;
730+
public static final field VIEW_SCOPE_INSTRUMENTATION_TYPE Lcom/datadog/android/core/internal/attributes/LocalAttribute$Key;
731+
public final fun getString ()Ljava/lang/String;
732+
public static fun valueOf (Ljava/lang/String;)Lcom/datadog/android/core/internal/attributes/LocalAttribute$Key;
733+
public static fun values ()[Lcom/datadog/android/core/internal/attributes/LocalAttribute$Key;
734+
}
735+
736+
public final class com/datadog/android/core/internal/attributes/LocalAttributeKt {
737+
public static final fun enrichWithConstantAttribute (Ljava/util/Map;Lcom/datadog/android/core/internal/attributes/LocalAttribute$Constant;)Ljava/util/Map;
738+
public static final fun enrichWithLocalAttribute (Ljava/util/Map;Lcom/datadog/android/core/internal/attributes/LocalAttribute$Key;Ljava/lang/Object;)Ljava/util/Map;
739+
public static final fun enrichWithNonNullAttribute (Ljava/util/Map;Lcom/datadog/android/core/internal/attributes/LocalAttribute$Key;Ljava/lang/Object;)Ljava/util/Map;
740+
}
741+
742+
public final class com/datadog/android/core/internal/attributes/ViewScopeInstrumentationType : java/lang/Enum, com/datadog/android/core/internal/attributes/LocalAttribute$Constant {
743+
public static final field ACTIVITY Lcom/datadog/android/core/internal/attributes/ViewScopeInstrumentationType;
744+
public static final field COMPOSE Lcom/datadog/android/core/internal/attributes/ViewScopeInstrumentationType;
745+
public static final field FRAGMENT Lcom/datadog/android/core/internal/attributes/ViewScopeInstrumentationType;
746+
public static final field MANUAL Lcom/datadog/android/core/internal/attributes/ViewScopeInstrumentationType;
747+
public fun getKey ()Lcom/datadog/android/core/internal/attributes/LocalAttribute$Key;
748+
public synthetic fun getValue ()Ljava/lang/Object;
749+
public fun getValue ()Ljava/lang/String;
750+
public static fun valueOf (Ljava/lang/String;)Lcom/datadog/android/core/internal/attributes/ViewScopeInstrumentationType;
751+
public static fun values ()[Lcom/datadog/android/core/internal/attributes/ViewScopeInstrumentationType;
752+
}
753+
719754
public final class com/datadog/android/core/internal/net/DefaultFirstPartyHostHeaderTypeResolver : com/datadog/android/core/internal/net/FirstPartyHostHeaderTypeResolver {
720755
public fun <init> (Ljava/util/Map;)V
721756
public fun getAllHeaderTypes ()Ljava/util/Set;
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
3+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
* Copyright 2016-Present Datadog, Inc.
5+
*/
6+
package com.datadog.android.core.internal.attributes
7+
8+
import com.datadog.android.lint.InternalApi
9+
10+
/**
11+
* Local attributes are used to pass additional metadata along with the event
12+
* and are never sent to the backend directly.
13+
*/
14+
@InternalApi
15+
interface LocalAttribute {
16+
17+
/**
18+
* Enumeration of all local attributes keys used in the application.
19+
* Made via **enum** to make sure that all such attributes will be removed before sending the event to the backend.
20+
*
21+
* @property string - Unique string value for a local attribute key.
22+
*/
23+
@InternalApi
24+
enum class Key(
25+
val string: String
26+
) {
27+
/* Some of the metrics like [PerformanceMetric] being sampled on the
28+
* metric creation place and then reported with 100% probability.
29+
* In such cases we need to use *creationSampleRate* to compute effectiveSampleRate correctlyThe sampling
30+
* rate is used when creating metrics.
31+
* Creation(head) sampling rate exist only for long-lived metrics like method performance.
32+
* Created metric still could not be sent it depends on [REPORTING_SAMPLING_RATE] sampling rate
33+
*/
34+
CREATION_SAMPLING_RATE("_dd.local.head_sampling_rate_key"),
35+
36+
/* Sampling rate that is used to decide to send or not to send the metric.
37+
* Each metric should have reporting(tail) sampling rate.
38+
* It's possible that metric has only reporting(tail) sampling rate.
39+
*/
40+
REPORTING_SAMPLING_RATE("_dd.local.tail_sampling_rate_key"),
41+
42+
/*
43+
* Indicates which instrumentation was used to track the view scope.
44+
* See [ViewScopeInstrumentationType] for possible values.
45+
*/
46+
VIEW_SCOPE_INSTRUMENTATION_TYPE("_dd.local.view_instrumentation_type_key")
47+
}
48+
49+
/**
50+
* Used for attributes that have a finite set of possible values (such as enumerations, see [ViewScopeInstrumentationType]).
51+
* This interface makes it possible to use only the value (see [enrichWithConstantAttribute]) when setting
52+
* an attribute and reduces the possibility of inconsistent use of api (when an unsupported value is passed
53+
* for a particular attribute key).
54+
*/
55+
@InternalApi
56+
interface Constant {
57+
/** Constant attribute key. For enum constants will be same for all values. */
58+
val key: Key
59+
60+
/** Constant attribute value. One item from set of possible finite values for a given constant attribute.*/
61+
val value: Any
62+
}
63+
}
64+
65+
/**
66+
* Adds local attribute to the mutable map.
67+
*
68+
* @param attribute - Constant attribute value that should be added.
69+
* Key for the attribute will be resolved automatically.
70+
*/
71+
@InternalApi
72+
fun MutableMap<String, Any?>.enrichWithConstantAttribute(
73+
attribute: LocalAttribute.Constant
74+
) = enrichWithLocalAttribute(
75+
attribute.key,
76+
attribute
77+
)
78+
79+
/**
80+
* Adds value to the map for specified key if value is not null.
81+
*
82+
* @param key - local attribute key.
83+
* @param value - attribute value.
84+
*/
85+
@InternalApi
86+
fun MutableMap<String, Any?>.enrichWithNonNullAttribute(
87+
key: LocalAttribute.Key,
88+
value: Any?
89+
) = value?.let { enrichWithLocalAttribute(key, it) } ?: this
90+
91+
/**
92+
* Adds value to the map for specified key.
93+
*
94+
* @param key - local attribute key.
95+
* @param value - attribute value.
96+
*/
97+
@InternalApi
98+
fun MutableMap<String, Any?>.enrichWithLocalAttribute(
99+
key: LocalAttribute.Key,
100+
value: Any?
101+
) = apply {
102+
this[key.string] = value
103+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
3+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
* Copyright 2016-Present Datadog, Inc.
5+
*/
6+
package com.datadog.android.core.internal.attributes
7+
8+
import com.datadog.android.lint.InternalApi
9+
10+
/**
11+
* A set of constants describing the instrumentation that were used to define the view scope.
12+
*/
13+
@InternalApi
14+
enum class ViewScopeInstrumentationType(
15+
override val value: String
16+
) : LocalAttribute.Constant {
17+
/** Tracked manually through the RUMMonitor API. */
18+
MANUAL("manual"),
19+
20+
/** Tracked through ComposeNavigationObserver instrumentation. */
21+
COMPOSE("compose"),
22+
23+
/** Tracked through ActivityViewTrackingStrategy instrumentation. */
24+
ACTIVITY("activity"),
25+
26+
/** Tracked through FragmentViewTrackingStrategy instrumentation. */
27+
FRAGMENT("fragment");
28+
29+
/** @inheritdoc */
30+
override val key: LocalAttribute.Key = LocalAttribute.Key.VIEW_SCOPE_INSTRUMENTATION_TYPE
31+
}

dd-sdk-android-core/src/main/kotlin/com/datadog/android/core/internal/logger/SdkInternalLogger.kt

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import com.datadog.android.Datadog
1212
import com.datadog.android.api.InternalLogger
1313
import com.datadog.android.api.feature.Feature
1414
import com.datadog.android.api.feature.FeatureSdkCore
15+
import com.datadog.android.core.internal.attributes.LocalAttribute
16+
import com.datadog.android.core.internal.attributes.enrichWithNonNullAttribute
1517
import com.datadog.android.core.internal.metrics.MethodCalledTelemetry
1618
import com.datadog.android.core.metrics.PerformanceMetric
1719
import com.datadog.android.core.metrics.TelemetryMetricType
@@ -102,18 +104,14 @@ internal class SdkInternalLogger(
102104
if (!sample(samplingRate)) return
103105
val rumFeature = sdkCore?.getFeature(Feature.RUM_FEATURE_NAME) ?: return
104106
val additionalPropertiesMutable = additionalProperties.toMutableMap()
105-
106-
enrichWithNonNullValue(
107-
additionalPropertiesMutable,
108-
InternalTelemetryEvent.CREATION_SAMPLING_RATE_KEY,
109-
creationSampleRate
110-
)
111-
112-
enrichWithNonNullValue(
113-
additionalPropertiesMutable,
114-
InternalTelemetryEvent.REPORTING_SAMPLING_RATE_KEY,
115-
samplingRate
116-
)
107+
.enrichWithNonNullAttribute(
108+
LocalAttribute.Key.CREATION_SAMPLING_RATE,
109+
creationSampleRate
110+
)
111+
.enrichWithNonNullAttribute(
112+
LocalAttribute.Key.REPORTING_SAMPLING_RATE,
113+
samplingRate
114+
)
117115

118116
val metricEvent = InternalTelemetryEvent.Metric(
119117
message = messageBuilder(),
@@ -150,10 +148,8 @@ internal class SdkInternalLogger(
150148
val rumFeature = sdkCore?.getFeature(Feature.RUM_FEATURE_NAME) ?: return
151149

152150
val event = apiUsageEventBuilder()
153-
154-
enrichWithNonNullValue(
155-
event.additionalProperties,
156-
InternalTelemetryEvent.REPORTING_SAMPLING_RATE_KEY,
151+
event.additionalProperties.enrichWithNonNullAttribute(
152+
LocalAttribute.Key.REPORTING_SAMPLING_RATE,
157153
samplingRate
158154
)
159155

@@ -278,18 +274,6 @@ internal class SdkInternalLogger(
278274
}
279275
}
280276

281-
private fun enrichWithNonNullValue(
282-
map: MutableMap<String, Any?>,
283-
key: String,
284-
value: Float?
285-
) {
286-
if (value == null) return
287-
288-
if (!map.containsKey(key)) {
289-
map[key] = value
290-
}
291-
}
292-
293277
companion object {
294278
internal const val SDK_LOG_TAG = "DD_LOG"
295279
internal const val DEV_LOG_TAG = "Datadog"

dd-sdk-android-core/src/test/kotlin/com/datadog/android/core/internal/logger/SdkInternalLoggerTest.kt

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.datadog.android.api.InternalLogger
1212
import com.datadog.android.api.feature.Feature
1313
import com.datadog.android.api.feature.FeatureScope
1414
import com.datadog.android.api.feature.FeatureSdkCore
15+
import com.datadog.android.core.internal.attributes.LocalAttribute
1516
import com.datadog.android.core.internal.metrics.MethodCalledTelemetry
1617
import com.datadog.android.core.metrics.TelemetryMetricType
1718
import com.datadog.android.internal.telemetry.InternalTelemetryEvent
@@ -452,7 +453,7 @@ internal class SdkInternalLoggerTest {
452453
// Given
453454
val samplingRate = 100.0f
454455
val fakeAdditionalProperties = forge.exhaustiveAttributes().also {
455-
it[InternalTelemetryEvent.REPORTING_SAMPLING_RATE_KEY] = samplingRate
456+
it[LocalAttribute.Key.REPORTING_SAMPLING_RATE.string] = samplingRate
456457
}
457458
val mockLambda: () -> String = mock()
458459
whenever(mockLambda.invoke()) doReturn fakeMessage
@@ -504,13 +505,13 @@ internal class SdkInternalLoggerTest {
504505
val metricEvent = firstValue as InternalTelemetryEvent.Metric
505506

506507
assertThat(
507-
metricEvent.additionalProperties?.get(InternalTelemetryEvent.CREATION_SAMPLING_RATE_KEY)
508+
metricEvent.additionalProperties?.get(LocalAttribute.Key.CREATION_SAMPLING_RATE.string)
508509
).isEqualTo(
509510
expectedCreationSampleRate
510511
)
511512

512513
assertThat(
513-
metricEvent.additionalProperties?.get(InternalTelemetryEvent.REPORTING_SAMPLING_RATE_KEY)
514+
metricEvent.additionalProperties?.get(LocalAttribute.Key.REPORTING_SAMPLING_RATE.string)
514515
).isEqualTo(
515516
samplingRate
516517
)
@@ -543,11 +544,11 @@ internal class SdkInternalLoggerTest {
543544
assertThat(
544545
apiUsageEvent.additionalProperties
545546
).doesNotContainKeys(
546-
InternalTelemetryEvent.CREATION_SAMPLING_RATE_KEY
547+
LocalAttribute.Key.CREATION_SAMPLING_RATE.string
547548
)
548549

549550
assertThat(
550-
apiUsageEvent.additionalProperties[InternalTelemetryEvent.REPORTING_SAMPLING_RATE_KEY]
551+
apiUsageEvent.additionalProperties[LocalAttribute.Key.REPORTING_SAMPLING_RATE.string]
551552
).isEqualTo(
552553
samplingRate
553554
)
@@ -568,7 +569,7 @@ internal class SdkInternalLoggerTest {
568569
),
569570
target = InternalLogger.Target.TELEMETRY,
570571
messageBuilder = { forge.aString() },
571-
additionalProperties = mapOf(InternalTelemetryEvent.REPORTING_SAMPLING_RATE_KEY to samplingRate)
572+
additionalProperties = mapOf(LocalAttribute.Key.REPORTING_SAMPLING_RATE.string to samplingRate)
572573
)
573574

574575
// Then
@@ -580,11 +581,11 @@ internal class SdkInternalLoggerTest {
580581
assertThat(
581582
debugEvent.additionalProperties
582583
).doesNotContainKeys(
583-
InternalTelemetryEvent.CREATION_SAMPLING_RATE_KEY
584+
LocalAttribute.Key.CREATION_SAMPLING_RATE.string
584585
)
585586

586587
assertThat(
587-
debugEvent.additionalProperties?.get(InternalTelemetryEvent.REPORTING_SAMPLING_RATE_KEY)
588+
debugEvent.additionalProperties?.get(LocalAttribute.Key.REPORTING_SAMPLING_RATE.string)
588589
).isEqualTo(
589590
samplingRate
590591
)
@@ -603,7 +604,7 @@ internal class SdkInternalLoggerTest {
603604
target = InternalLogger.Target.TELEMETRY,
604605
throwable = forge.aThrowable(),
605606
messageBuilder = { forge.aString() },
606-
additionalProperties = mapOf(InternalTelemetryEvent.REPORTING_SAMPLING_RATE_KEY to samplingRate)
607+
additionalProperties = mapOf(LocalAttribute.Key.REPORTING_SAMPLING_RATE.string to samplingRate)
607608
)
608609

609610
// Then
@@ -615,11 +616,11 @@ internal class SdkInternalLoggerTest {
615616
assertThat(
616617
debugEvent.additionalProperties
617618
).doesNotContainKeys(
618-
InternalTelemetryEvent.CREATION_SAMPLING_RATE_KEY
619+
LocalAttribute.Key.CREATION_SAMPLING_RATE.string
619620
)
620621

621622
assertThat(
622-
debugEvent.additionalProperties?.get(InternalTelemetryEvent.REPORTING_SAMPLING_RATE_KEY)
623+
debugEvent.additionalProperties?.get(LocalAttribute.Key.REPORTING_SAMPLING_RATE.string)
623624
).isEqualTo(
624625
samplingRate
625626
)

dd-sdk-android-internal/api/apiSurface

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ sealed class com.datadog.android.internal.telemetry.InternalTelemetryEvent
2828
class AddViewLoadingTime : ApiUsage
2929
constructor(Boolean, Boolean, Boolean, MutableMap<String, Any?> = mutableMapOf())
3030
object InterceptorInstantiated : InternalTelemetryEvent
31-
companion object
32-
const val CREATION_SAMPLING_RATE_KEY: String
33-
const val REPORTING_SAMPLING_RATE_KEY: String
3431
fun ByteArray.toHexString(): String
3532
object com.datadog.android.internal.utils.ImageViewUtils
3633
fun resolveParentRectAbsPosition(android.view.View, Boolean = true): android.graphics.Rect

dd-sdk-android-internal/api/dd-sdk-android-internal.api

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@ public final class com/datadog/android/internal/profiler/GlobalBenchmark {
3030
}
3131

3232
public abstract class com/datadog/android/internal/telemetry/InternalTelemetryEvent {
33-
public static final field CREATION_SAMPLING_RATE_KEY Ljava/lang/String;
34-
public static final field Companion Lcom/datadog/android/internal/telemetry/InternalTelemetryEvent$Companion;
35-
public static final field REPORTING_SAMPLING_RATE_KEY Ljava/lang/String;
3633
}
3734

3835
public abstract class com/datadog/android/internal/telemetry/InternalTelemetryEvent$ApiUsage : com/datadog/android/internal/telemetry/InternalTelemetryEvent {
@@ -49,9 +46,6 @@ public final class com/datadog/android/internal/telemetry/InternalTelemetryEvent
4946
public final fun getOverwrite ()Z
5047
}
5148

52-
public final class com/datadog/android/internal/telemetry/InternalTelemetryEvent$Companion {
53-
}
54-
5549
public final class com/datadog/android/internal/telemetry/InternalTelemetryEvent$Configuration : com/datadog/android/internal/telemetry/InternalTelemetryEvent {
5650
public fun <init> (ZJJZZI)V
5751
public final fun component1 ()Z

0 commit comments

Comments
 (0)