Skip to content

Commit e0a7ca3

Browse files
committed
RUM-12923: Attach RUM information on profiling event
1 parent 3d91afb commit e0a7ca3

File tree

15 files changed

+517
-32
lines changed

15 files changed

+517
-32
lines changed

dd-sdk-android-internal/api/apiSurface

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,6 @@ class com.datadog.android.rum.DdRumContentProvider : android.content.ContentProv
158158
var processImportance: Int
159159
val createTimeNs: Long
160160
data class com.datadog.android.rum.TTIDEvent
161-
constructor(Long)
161+
constructor(Long, String, String?, String?, String?)
162162
annotation com.datadog.tools.annotation.NoOpImplementation
163163
constructor(Boolean = false)

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,12 +382,20 @@ public final class com/datadog/android/rum/DdRumContentProvider$Companion {
382382
}
383383

384384
public final class com/datadog/android/rum/TTIDEvent {
385-
public fun <init> (J)V
385+
public fun <init> (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
386386
public final fun component1 ()J
387-
public final fun copy (J)Lcom/datadog/android/rum/TTIDEvent;
388-
public static synthetic fun copy$default (Lcom/datadog/android/rum/TTIDEvent;JILjava/lang/Object;)Lcom/datadog/android/rum/TTIDEvent;
387+
public final fun component2 ()Ljava/lang/String;
388+
public final fun component3 ()Ljava/lang/String;
389+
public final fun component4 ()Ljava/lang/String;
390+
public final fun component5 ()Ljava/lang/String;
391+
public final fun copy (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lcom/datadog/android/rum/TTIDEvent;
392+
public static synthetic fun copy$default (Lcom/datadog/android/rum/TTIDEvent;JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/datadog/android/rum/TTIDEvent;
389393
public fun equals (Ljava/lang/Object;)Z
394+
public final fun getSessionId ()Ljava/lang/String;
390395
public final fun getValue ()J
396+
public final fun getViewId ()Ljava/lang/String;
397+
public final fun getViewName ()Ljava/lang/String;
398+
public final fun getVitalId ()Ljava/lang/String;
391399
public fun hashCode ()I
392400
public fun toString ()Ljava/lang/String;
393401
}

dd-sdk-android-internal/src/main/java/com/datadog/android/rum/TTIDEvent.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,15 @@ package com.datadog.android.rum
1010
* Internal event to pass the Time To Initial Display (TTID) value in nanoseconds.
1111
*
1212
* @param value The TTID value in nanoseconds.
13+
* @param sessionId The Id of the RUM session where TTID is captured
14+
* @param viewId The Id of the view where TTID is captured
15+
* @param viewName The name of the view where TTID is captured
16+
* @param vitalId The Id of the TTID vital event
1317
*/
14-
data class TTIDEvent(val value: Long)
18+
data class TTIDEvent(
19+
val value: Long,
20+
val sessionId: String,
21+
val viewId: String?,
22+
val viewName: String?,
23+
val vitalId: String?
24+
)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
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+
7+
package com.datadog.android.profiling.internal
8+
9+
internal data class ProfilingContext(
10+
val sessionId: String? = null,
11+
val vitalId: String? = null,
12+
val viewId: String? = null,
13+
val viewName: String? = null
14+
)

features/dd-sdk-android-profiling/src/main/java/com/datadog/android/profiling/internal/ProfilingDataWriter.kt

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,16 @@ internal class ProfilingDataWriter(
2121
private val sdkCore: FeatureSdkCore
2222
) : ProfilingWriter {
2323
override fun write(
24-
profilingResult: PerfettoResult
24+
profilingResult: PerfettoResult,
25+
profilingContext: ProfilingContext
2526
) {
2627
sdkCore.getFeature(Feature.PROFILING_FEATURE_NAME)
2728
?.withWriteContext { context, writeScope ->
2829
writeScope { writer ->
2930
val rawBatchEvent = buildRawBatchEvent(
3031
context = context,
31-
profilingResult = profilingResult
32+
profilingResult = profilingResult,
33+
profilingContext = profilingContext
3234
)
3335
if (rawBatchEvent != null) {
3436
synchronized(this) {
@@ -45,21 +47,27 @@ internal class ProfilingDataWriter(
4547

4648
private fun buildRawBatchEvent(
4749
context: DatadogContext,
48-
profilingResult: PerfettoResult
50+
profilingResult: PerfettoResult,
51+
profilingContext: ProfilingContext
4952
): RawBatchEvent? {
5053
val byteData = readProfilingData(profilingResult.resultFilePath)
5154
if (byteData == null || byteData.isEmpty()) {
5255
return null
5356
}
54-
val profileEvent = createProfileEvent(context, profilingResult)
57+
val profileEvent = createProfileEvent(
58+
context,
59+
profilingResult,
60+
profilingContext
61+
)
5562
val serializedEvent =
5663
profileEvent.toJson().toString().toByteArray(Charsets.UTF_8)
5764
return RawBatchEvent(data = serializedEvent, metadata = byteData)
5865
}
5966

6067
private fun createProfileEvent(
6168
context: DatadogContext,
62-
profilingResult: PerfettoResult
69+
profilingResult: PerfettoResult,
70+
profilingContext: ProfilingContext
6371
): ProfileEvent {
6472
return ProfileEvent(
6573
start = formatIsoUtc(profilingResult.start),
@@ -68,18 +76,38 @@ internal class ProfilingDataWriter(
6876
family = ANDROID_FAMILY_NAME,
6977
runtime = ANDROID_RUNTIME_NAME,
7078
version = VERSION_NUMBER,
71-
tagsProfiler = buildTags(context)
79+
tagsProfiler = buildTags(context, profilingContext)
7280
)
7381
}
7482

75-
private fun buildTags(context: DatadogContext): String = buildString {
83+
private fun buildTags(
84+
context: DatadogContext,
85+
profilingContext: ProfilingContext
86+
): String = buildString {
7687
append("$TAG_KEY_SERVICE:${context.service}")
7788
append(",")
7889
append("$TAG_KEY_ENV:${context.env}")
7990
append(",")
8091
append("$TAG_KEY_VERSION:${context.version}")
8192
append(",")
8293
append("$TAG_KEY_SDK_VERSION:${context.sdkVersion}")
94+
95+
profilingContext.sessionId?.let {
96+
append(",")
97+
append("$TAG_KEY_RUM_SESSION_ID:$it")
98+
}
99+
profilingContext.vitalId?.let {
100+
append(",")
101+
append("$TAG_KEY_RUM_VITAL_ID:$it")
102+
}
103+
profilingContext.viewId?.let {
104+
append(",")
105+
append("$TAG_KEY_RUM_VIEW_ID:$it")
106+
}
107+
profilingContext.viewName?.let {
108+
append(",")
109+
append("$TAG_KEY_RUM_VIEW_NAME:$it")
110+
}
83111
}
84112

85113
private fun readProfilingData(profilingPath: String): ByteArray? {
@@ -92,6 +120,10 @@ internal class ProfilingDataWriter(
92120
private const val TAG_KEY_SERVICE = "service"
93121
private const val TAG_KEY_VERSION = "version"
94122
private const val TAG_KEY_SDK_VERSION = "sdk_version"
123+
private const val TAG_KEY_RUM_SESSION_ID = "session_id"
124+
private const val TAG_KEY_RUM_VITAL_ID = "vital_id"
125+
private const val TAG_KEY_RUM_VIEW_ID = "view_id"
126+
private const val TAG_KEY_RUM_VIEW_NAME = "view_name"
95127
private const val TAG_KEY_ENV = "env"
96128
private const val PERFETTO_ATTACHMENT_NAME = "perfetto.proto"
97129
private const val ANDROID_FAMILY_NAME = "android"

features/dd-sdk-android-profiling/src/main/java/com/datadog/android/profiling/internal/ProfilingFeature.kt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ internal class ProfilingFeature(
2929

3030
private var dataWriter: ProfilingWriter = NoOpProfilingWriter()
3131

32+
private var profilingContext: ProfilingContext = ProfilingContext()
33+
3234
override val requestFactory: RequestFactory = ProfilingRequestFactory(
3335
configuration.customEndpointUrl,
3436
sdkCore.internalLogger
@@ -44,7 +46,10 @@ internal class ProfilingFeature(
4446
profiler.apply {
4547
this.internalLogger = sdkCore.internalLogger
4648
this.onProfilingSuccess = { result ->
47-
dataWriter.write(profilingResult = result)
49+
dataWriter.write(
50+
profilingResult = result,
51+
profilingContext = profilingContext
52+
)
4853
}
4954
}
5055
// Set the profiling flag in SharedPreferences to profile for the next app launch
@@ -67,6 +72,7 @@ internal class ProfilingFeature(
6772
)
6873
return
6974
}
75+
updateProfilingContext(event)
7076
profiler.stop()
7177
sdkCore.internalLogger.log(
7278
InternalLogger.Level.INFO,
@@ -75,6 +81,15 @@ internal class ProfilingFeature(
7581
)
7682
}
7783

84+
private fun updateProfilingContext(event: TTIDEvent) {
85+
this.profilingContext = ProfilingContext(
86+
sessionId = event.sessionId,
87+
vitalId = event.vitalId,
88+
viewId = event.viewId,
89+
viewName = event.viewName
90+
)
91+
}
92+
7893
private fun createDataWriter(sdkCore: FeatureSdkCore): ProfilingDataWriter {
7994
return ProfilingDataWriter(sdkCore)
8095
}

features/dd-sdk-android-profiling/src/main/java/com/datadog/android/profiling/internal/ProfilingWriter.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import com.datadog.tools.annotation.NoOpImplementation
1313
internal interface ProfilingWriter {
1414

1515
fun write(
16-
profilingResult: PerfettoResult
16+
profilingResult: PerfettoResult,
17+
profilingContext: ProfilingContext
1718
)
1819
}

features/dd-sdk-android-profiling/src/test/kotlin/com/datadog/android/profiling/ProfilingFeatureTest.kt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,23 @@ class ProfilingFeatureTest {
110110
}
111111

112112
@Test
113-
fun `M stop Profiling W receive TTID event`(@LongForgery fakeTtid: Long) {
113+
fun `M stop Profiling W receive TTID event`(
114+
@LongForgery fakeTtid: Long,
115+
@StringForgery fakeSessionId: String,
116+
@StringForgery fakeViewId: String,
117+
@StringForgery fakeViewName: String,
118+
@StringForgery fakeVitalId: String
119+
) {
114120
// When
115-
testedFeature.onReceive(TTIDEvent(fakeTtid))
121+
testedFeature.onReceive(
122+
TTIDEvent(
123+
fakeTtid,
124+
sessionId = fakeSessionId,
125+
viewId = fakeViewId,
126+
viewName = fakeViewName,
127+
vitalId = fakeVitalId
128+
)
129+
)
116130

117131
// Then
118132
verify(mockProfiler).stop()

features/dd-sdk-android-profiling/src/test/kotlin/com/datadog/android/profiling/forge/Configurator.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ class Configurator : BaseConfigurator() {
1717
forge.useCoreFactories()
1818
forge.addFactory(ProfilingConfigurationForgeryFactory())
1919
forge.addFactory(PerfettoResultFactory())
20+
forge.addFactory(ProfilingContextFactory())
2021
}
2122
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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+
7+
package com.datadog.android.profiling.forge
8+
9+
import com.datadog.android.profiling.internal.ProfilingContext
10+
import fr.xgouchet.elmyr.Forge
11+
import fr.xgouchet.elmyr.ForgeryFactory
12+
13+
internal class ProfilingContextFactory : ForgeryFactory<ProfilingContext> {
14+
override fun getForgery(forge: Forge): ProfilingContext {
15+
return ProfilingContext(
16+
sessionId = forge.anAlphabeticalString(),
17+
vitalId = forge.anAlphabeticalString(),
18+
viewId = forge.anAlphabeticalString(),
19+
viewName = forge.anAlphabeticalString()
20+
)
21+
}
22+
}

0 commit comments

Comments
 (0)