Skip to content

Commit 4df0cde

Browse files
Merge pull request #2637 from DataDog/aleksandr-gringauz/RUM-9509/traces-benchmark-scenario
RUM-9509: Trace scenario for android benchmark app
2 parents f11cf14 + 4164398 commit 4df0cde

File tree

9 files changed

+495
-9
lines changed

9 files changed

+495
-9
lines changed

sample/benchmark/src/main/java/com/datadog/benchmark/sample/DatadogFeaturesInitializer.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import com.datadog.android.sessionreplay.SessionReplayConfiguration
1818
import com.datadog.android.sessionreplay.SessionReplayPrivacy
1919
import com.datadog.android.sessionreplay.compose.ComposeExtensionSupport
2020
import com.datadog.android.sessionreplay.material.MaterialExtensionSupport
21+
import com.datadog.android.trace.Trace
22+
import com.datadog.android.trace.TraceConfiguration
2123
import com.datadog.benchmark.sample.config.BenchmarkConfig
2224
import com.datadog.benchmark.sample.config.SyntheticsRun
2325
import com.datadog.benchmark.sample.config.SyntheticsScenario
@@ -55,6 +57,10 @@ internal class DatadogFeaturesInitializer @Inject constructor(
5557
if (needToEnableSessionReplay(config)) {
5658
enableSessionReplay()
5759
}
60+
61+
if (needToEnableTracing(config)) {
62+
enableTracing()
63+
}
5864
}
5965

6066
private fun needToEnableSessionReplay(config: BenchmarkConfig): Boolean {
@@ -164,6 +170,21 @@ internal class DatadogFeaturesInitializer @Inject constructor(
164170
null -> false
165171
}
166172

173+
private fun isTracingScenario(config: BenchmarkConfig) = when (config.scenario) {
174+
SyntheticsScenario.Trace -> true
175+
else -> false
176+
}
177+
178+
private fun needToEnableTracing(config: BenchmarkConfig): Boolean {
179+
return isInstrumentedRun(config) && isTracingScenario(config)
180+
}
181+
182+
private fun enableTracing() {
183+
val tracesConfig = TraceConfiguration.Builder().build()
184+
185+
Trace.enable(tracesConfig, sdkCore)
186+
}
187+
167188
private fun isInstrumentedRun(config: BenchmarkConfig) = config.run == SyntheticsRun.Instrumented
168189

169190
companion object {

sample/benchmark/src/main/java/com/datadog/benchmark/sample/di/activity/BenchmarkActivityComponent.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import com.datadog.benchmark.sample.ui.logscustom.LogsFragment
1515
import com.datadog.benchmark.sample.ui.logsheavytraffic.di.LogsHeavyTrafficComponentDependencies
1616
import com.datadog.benchmark.sample.ui.sessionreplay.SessionReplayAppcompatFragment
1717
import com.datadog.benchmark.sample.ui.sessionreplay.SessionReplayMaterialFragment
18+
import com.datadog.benchmark.sample.ui.trace.TraceScenarioFragment
1819
import dagger.BindsInstance
1920
import dagger.Component
2021
import javax.inject.Scope
@@ -35,7 +36,8 @@ internal interface BenchmarkActivityComponentDependencies {
3536
BenchmarkActivityModule::class,
3637
ViewModelsModule::class,
3738
DatadogActivityModule::class,
38-
DispatchersModule::class
39+
DispatchersModule::class,
40+
OpenTelemetryModule::class
3941
]
4042
)
4143
@BenchmarkActivityScope
@@ -54,4 +56,5 @@ internal interface BenchmarkActivityComponent : LogsHeavyTrafficComponentDepende
5456
fun inject(sessionReplayAppcompatFragment: SessionReplayAppcompatFragment)
5557
fun inject(sessionReplayMaterialFragment: SessionReplayMaterialFragment)
5658
fun inject(logsFragment: LogsFragment)
59+
fun inject(traceScenarioFragment: TraceScenarioFragment)
5760
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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.benchmark.sample.di.activity
8+
9+
import com.datadog.android.api.SdkCore
10+
import com.datadog.android.trace.opentelemetry.OtelTracerProvider
11+
import com.datadog.benchmark.sample.config.BenchmarkConfig
12+
import com.datadog.benchmark.sample.config.SyntheticsRun
13+
import com.datadog.benchmark.sample.config.SyntheticsScenario
14+
import dagger.Module
15+
import dagger.Provides
16+
import io.opentelemetry.api.OpenTelemetry
17+
import io.opentelemetry.api.trace.Tracer
18+
import io.opentelemetry.api.trace.TracerProvider
19+
import io.opentelemetry.context.propagation.ContextPropagators
20+
21+
@Module
22+
internal interface OpenTelemetryModule {
23+
companion object {
24+
@Provides
25+
@BenchmarkActivityScope
26+
fun provideOpenTelemetry(
27+
sdkCore: SdkCore,
28+
config: BenchmarkConfig
29+
): OpenTelemetry {
30+
val isTracingEnabled = config.run == SyntheticsRun.Instrumented &&
31+
config.scenario == SyntheticsScenario.Trace
32+
33+
val tracerProvider = when (isTracingEnabled) {
34+
true -> OtelTracerProvider.Builder(sdkCore).build()
35+
false -> TracerProvider.noop()
36+
}
37+
38+
return object : OpenTelemetry {
39+
override fun getTracerProvider(): TracerProvider {
40+
return tracerProvider
41+
}
42+
43+
override fun getPropagators(): ContextPropagators {
44+
return ContextPropagators.noop()
45+
}
46+
}
47+
}
48+
49+
@Provides
50+
@BenchmarkActivityScope
51+
fun provideTracer(
52+
openTelemetry: OpenTelemetry
53+
): Tracer {
54+
return openTelemetry.getTracer(BENCHMARK_APP_TRACER_INSTRUMENTATION_SCOPE_NAME)
55+
}
56+
}
57+
}
58+
59+
private const val BENCHMARK_APP_TRACER_INSTRUMENTATION_SCOPE_NAME = "dd-sdk-android-benchmark"

sample/benchmark/src/main/java/com/datadog/benchmark/sample/di/activity/ViewModelsModule.kt

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,22 @@ import com.datadog.android.log.Logger
1313
import com.datadog.benchmark.sample.di.common.CoroutineDispatcherQualifier
1414
import com.datadog.benchmark.sample.di.common.CoroutineDispatcherType
1515
import com.datadog.benchmark.sample.ui.logscustom.LogsScreenViewModel
16+
import com.datadog.benchmark.sample.ui.trace.TraceScenarioViewModel
1617
import dagger.Module
1718
import dagger.Provides
19+
import io.opentelemetry.api.trace.Tracer
1820
import kotlinx.coroutines.CoroutineDispatcher
1921
import javax.inject.Qualifier
2022
import kotlin.reflect.KClass
2123

2224
@Qualifier
23-
internal annotation class ViewModel(val viewModelType: KClass<*>)
25+
internal annotation class ViewModelQualifier(val viewModelType: KClass<*>)
2426

2527
@Module
2628
internal interface ViewModelsModule {
2729
companion object {
2830
@Provides
29-
@ViewModel(LogsScreenViewModel::class)
31+
@ViewModelQualifier(LogsScreenViewModel::class)
3032
fun provideLogsScreenViewModelFactory(
3133
logger: Logger,
3234
@CoroutineDispatcherQualifier(CoroutineDispatcherType.Default)
@@ -39,5 +41,20 @@ internal interface ViewModelsModule {
3941
)
4042
}
4143
}
44+
45+
@Provides
46+
@ViewModelQualifier(TraceScenarioViewModel::class)
47+
fun provideTraceScenarioViewModelFactory(
48+
tracer: Tracer,
49+
@CoroutineDispatcherQualifier(CoroutineDispatcherType.Default)
50+
defaultDispatcher: CoroutineDispatcher
51+
): ViewModelProvider.Factory = viewModelFactory {
52+
initializer {
53+
TraceScenarioViewModel(
54+
tracer = tracer,
55+
defaultDispatcher = defaultDispatcher
56+
)
57+
}
58+
}
4259
}
4360
}

sample/benchmark/src/main/java/com/datadog/benchmark/sample/navigation/FragmentsNavigationManagerImpl.kt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import com.datadog.benchmark.sample.ui.logscustom.LogsFragment
1717
import com.datadog.benchmark.sample.ui.logsheavytraffic.LogsHeavyTrafficHostFragment
1818
import com.datadog.benchmark.sample.ui.sessionreplay.SessionReplayAppcompatFragment
1919
import com.datadog.benchmark.sample.ui.sessionreplay.SessionReplayMaterialFragment
20+
import com.datadog.benchmark.sample.ui.trace.TraceScenarioFragment
2021
import javax.inject.Inject
2122

2223
internal class FragmentsNavigationManagerImpl @Inject constructor(
@@ -54,8 +55,8 @@ private fun createStartDestination(scenario: SyntheticsScenario?): String {
5455
SyntheticsScenario.SessionReplayCompose -> error("Using fragments for SessionReplayCompose scenario")
5556
SyntheticsScenario.LogsCustom -> LOGS_FRAGMENT_KEY
5657
SyntheticsScenario.LogsHeavyTraffic -> LOGS_HEAVY_TRAFFIC_FRAGMENT_KEY
57-
SyntheticsScenario.Rum, // TODO RUM-9510
58-
SyntheticsScenario.Trace -> SESSION_REPLAY_METERIAL_FRAGMENT_KEY // TODO RUM-9509
58+
SyntheticsScenario.Rum -> SESSION_REPLAY_METERIAL_FRAGMENT_KEY // TODO RUM-9510
59+
SyntheticsScenario.Trace -> TRACE_SCENARIO_FRAGMENT_KEY
5960
}
6061
}
6162

@@ -67,8 +68,8 @@ private fun NavGraphBuilder.navGraph(scenario: SyntheticsScenario?) {
6768
SyntheticsScenario.SessionReplayCompose -> error("Using fragments for SessionReplayCompose scenario")
6869
SyntheticsScenario.LogsCustom -> navGraphLogs()
6970
SyntheticsScenario.LogsHeavyTraffic -> navGraphLogsHeavyTraffic()
70-
SyntheticsScenario.Rum, // TODO RUM-9510
71-
SyntheticsScenario.Trace -> navGraphSessionReplay() // TODO RUM-9509
71+
SyntheticsScenario.Rum -> navGraphSessionReplay() // TODO RUM-9510
72+
SyntheticsScenario.Trace -> navGraphTraceScenario()
7273
}
7374
}
7475

@@ -94,7 +95,14 @@ private fun NavGraphBuilder.navGraphSessionReplay() {
9495
}
9596
}
9697

98+
private fun NavGraphBuilder.navGraphTraceScenario() {
99+
fragment<TraceScenarioFragment>(route = TRACE_SCENARIO_FRAGMENT_KEY) {
100+
label = "trace scenario"
101+
}
102+
}
103+
97104
private const val LOGS_FRAGMENT_KEY = "logs_fragment"
98105
private const val LOGS_HEAVY_TRAFFIC_FRAGMENT_KEY = "logs_heavy_traffic_fragment"
99106
private const val SESSION_REPLAY_METERIAL_FRAGMENT_KEY = "fragment_session_replay_material"
100107
private const val SESSION_REPLAY_APPCOMPAT_FRAGMENT_KEY = "fragment_session_replay_appcompat"
108+
private const val TRACE_SCENARIO_FRAGMENT_KEY = "fragment_trace_scenario"

sample/benchmark/src/main/java/com/datadog/benchmark/sample/ui/logscustom/LogsFragment.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ import androidx.fragment.app.viewModels
1919
import androidx.lifecycle.ViewModelProvider
2020
import androidx.lifecycle.compose.collectAsStateWithLifecycle
2121
import com.datadog.benchmark.sample.benchmarkActivityComponent
22-
import com.datadog.benchmark.sample.di.activity.ViewModel
22+
import com.datadog.benchmark.sample.di.activity.ViewModelQualifier
2323
import javax.inject.Inject
2424

2525
internal class LogsFragment : Fragment() {
2626

2727
@Inject
28-
@ViewModel(LogsScreenViewModel::class)
28+
@ViewModelQualifier(LogsScreenViewModel::class)
2929
internal lateinit var viewModelFactory: ViewModelProvider.Factory
3030

3131
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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.benchmark.sample.ui.trace
8+
9+
import android.os.Bundle
10+
import android.view.LayoutInflater
11+
import android.view.View
12+
import android.view.ViewGroup
13+
import androidx.compose.foundation.layout.fillMaxSize
14+
import androidx.compose.runtime.getValue
15+
import androidx.compose.ui.Modifier
16+
import androidx.compose.ui.platform.ComposeView
17+
import androidx.fragment.app.Fragment
18+
import androidx.fragment.app.viewModels
19+
import androidx.lifecycle.ViewModelProvider
20+
import androidx.lifecycle.compose.collectAsStateWithLifecycle
21+
import com.datadog.benchmark.sample.benchmarkActivityComponent
22+
import com.datadog.benchmark.sample.di.activity.ViewModelQualifier
23+
import javax.inject.Inject
24+
25+
internal class TraceScenarioFragment : Fragment() {
26+
@Inject
27+
@ViewModelQualifier(TraceScenarioViewModel::class)
28+
internal lateinit var viewModelFactory: ViewModelProvider.Factory
29+
30+
private val viewModel: TraceScenarioViewModel by viewModels { viewModelFactory }
31+
32+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
33+
requireActivity().benchmarkActivityComponent.inject(this)
34+
35+
return ComposeView(requireActivity()).apply {
36+
setContent {
37+
val state by viewModel.traceScenarioState.collectAsStateWithLifecycle()
38+
39+
TraceScenarioScreen(
40+
modifier = Modifier.fillMaxSize(),
41+
state = state,
42+
dispatch = viewModel::dispatch
43+
)
44+
}
45+
}
46+
}
47+
}
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+
7+
package com.datadog.benchmark.sample.ui.trace
8+
9+
import androidx.compose.foundation.layout.Column
10+
import androidx.compose.foundation.layout.Row
11+
import androidx.compose.foundation.layout.fillMaxSize
12+
import androidx.compose.foundation.layout.fillMaxWidth
13+
import androidx.compose.foundation.layout.padding
14+
import androidx.compose.material3.Button
15+
import androidx.compose.material3.Switch
16+
import androidx.compose.material3.Text
17+
import androidx.compose.material3.TextField
18+
import androidx.compose.runtime.Composable
19+
import androidx.compose.ui.Alignment
20+
import androidx.compose.ui.Modifier
21+
import androidx.compose.ui.tooling.preview.Preview
22+
import androidx.compose.ui.unit.dp
23+
import com.datadog.benchmark.sample.ui.common.ValueChooserItemView
24+
25+
@Composable
26+
internal fun TraceScenarioScreen(
27+
modifier: Modifier,
28+
state: TraceScenarioScreenState,
29+
dispatch: (TraceScenarioScreenAction) -> Unit
30+
) {
31+
Column(modifier = modifier.padding(8.dp)) {
32+
TextField(
33+
value = state.config.spanOperation,
34+
onValueChange = { dispatch(TraceScenarioScreenAction.ChangeSpanOperation(it)) }
35+
)
36+
TextField(
37+
value = state.config.spanResource,
38+
onValueChange = { dispatch(TraceScenarioScreenAction.ChangeSpanResource(it)) }
39+
)
40+
Row(
41+
modifier = Modifier.fillMaxWidth(),
42+
verticalAlignment = Alignment.CenterVertically
43+
) {
44+
Text(text = "Is Error", modifier = Modifier.weight(1f))
45+
46+
Switch(
47+
checked = state.config.isError,
48+
onCheckedChange = { isChecked ->
49+
dispatch(TraceScenarioScreenAction.SetIsError(isChecked))
50+
}
51+
)
52+
}
53+
54+
ValueChooserItemView(
55+
titleText = "Children count:",
56+
currentValue = state.config.childrenCount.toString(),
57+
increaseClick = { dispatch(TraceScenarioScreenAction.IncreaseChildrenCount) },
58+
decreaseClick = { dispatch(TraceScenarioScreenAction.DecreaseChildrenCount) }
59+
)
60+
61+
ValueChooserItemView(
62+
titleText = "Depth:",
63+
currentValue = state.config.depth.toString(),
64+
increaseClick = { dispatch(TraceScenarioScreenAction.IncreaseDepth) },
65+
decreaseClick = { dispatch(TraceScenarioScreenAction.DecreaseDepth) }
66+
)
67+
68+
ValueChooserItemView(
69+
titleText = "Child delay (ms):",
70+
currentValue = state.config.childDelayMillis.toString(),
71+
increaseClick = { dispatch(TraceScenarioScreenAction.IncreaseChildDelay) },
72+
decreaseClick = { dispatch(TraceScenarioScreenAction.DecreaseChildDelay) }
73+
)
74+
75+
Row {
76+
Button(onClick = { dispatch(TraceScenarioScreenAction.SendButtonClicked) }) {
77+
Text(text = "Send")
78+
}
79+
80+
if (state.tracingTasksMap.isNotEmpty()) {
81+
Button(onClick = { dispatch(TraceScenarioScreenAction.CancelButtonClicked) }) {
82+
Text(text = "Cancel")
83+
}
84+
}
85+
}
86+
87+
Text(text = "Traces sent: ${state.tracesSent}")
88+
89+
if (state.tracingTasksMap.isNotEmpty()) {
90+
Text(text = "Number of running tasks: ${state.tracingTasksMap.size}")
91+
}
92+
}
93+
}
94+
95+
@Preview(showBackground = true)
96+
@Composable
97+
internal fun TraceScenarioScreenPreview() {
98+
TraceScenarioScreen(
99+
modifier = Modifier.fillMaxSize(),
100+
state = TraceScenarioScreenState.INITIAL,
101+
dispatch = { }
102+
)
103+
}

0 commit comments

Comments
 (0)