Skip to content

Commit

Permalink
RUM-7174 Introduce the setNetworkSettledInitialResourceIdentifier Pub…
Browse files Browse the repository at this point in the history
…lic API
  • Loading branch information
mariusc83 committed Dec 2, 2024
1 parent 614e7c0 commit dd94ef2
Show file tree
Hide file tree
Showing 22 changed files with 294 additions and 52 deletions.
11 changes: 11 additions & 0 deletions features/dd-sdk-android-rum/api/apiSurface
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ data class com.datadog.android.rum.RumConfiguration
fun setVitalsUpdateFrequency(com.datadog.android.rum.configuration.VitalsUpdateFrequency): Builder
fun useCustomEndpoint(String): Builder
fun setSessionListener(RumSessionListener): Builder
fun setNetworkSettledInitialResourceIdentifier(com.datadog.android.rum.internal.metric.networksettled.InitialResourceIdentifier): Builder
fun build(): RumConfiguration
enum com.datadog.android.rum.RumErrorSource
- NETWORK
Expand Down Expand Up @@ -166,6 +167,16 @@ interface com.datadog.android.rum.event.ViewEventMapper : com.datadog.android.ev
override fun map(com.datadog.android.rum.model.ViewEvent): com.datadog.android.rum.model.ViewEvent
data class com.datadog.android.rum.internal.domain.event.ResourceTiming
constructor(Long = 0L, Long = 0L, Long = 0L, Long = 0L, Long = 0L, Long = 0L, Long = 0L, Long = 0L, Long = 0L, Long = 0L)
interface com.datadog.android.rum.internal.metric.networksettled.InitialResourceIdentifier
fun validate(NetworkSettledResourceContext): Boolean
data class com.datadog.android.rum.internal.metric.networksettled.NetworkSettledResourceContext
constructor(String, Long, Long?)
class com.datadog.android.rum.internal.metric.networksettled.TimeBasedInitialResourceIdentifier : InitialResourceIdentifier
constructor(Long = TimeUnit.MILLISECONDS.toNanos(DEFAULT_TIME_THRESHOLD_MS))
override fun validate(NetworkSettledResourceContext): Boolean
override fun equals(Any?): Boolean
override fun hashCode(): Int
companion object
interface com.datadog.android.rum.internal.monitor.AdvancedNetworkRumMonitor : com.datadog.android.rum.RumMonitor
fun waitForResourceTiming(Any)
fun addResourceTiming(Any, com.datadog.android.rum.internal.domain.event.ResourceTiming)
Expand Down
27 changes: 27 additions & 0 deletions features/dd-sdk-android-rum/api/dd-sdk-android-rum.api
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ public final class com/datadog/android/rum/RumConfiguration$Builder {
public final fun setActionEventMapper (Lcom/datadog/android/event/EventMapper;)Lcom/datadog/android/rum/RumConfiguration$Builder;
public final fun setErrorEventMapper (Lcom/datadog/android/event/EventMapper;)Lcom/datadog/android/rum/RumConfiguration$Builder;
public final fun setLongTaskEventMapper (Lcom/datadog/android/event/EventMapper;)Lcom/datadog/android/rum/RumConfiguration$Builder;
public final fun setNetworkSettledInitialResourceIdentifier (Lcom/datadog/android/rum/internal/metric/networksettled/InitialResourceIdentifier;)Lcom/datadog/android/rum/RumConfiguration$Builder;
public final fun setResourceEventMapper (Lcom/datadog/android/event/EventMapper;)Lcom/datadog/android/rum/RumConfiguration$Builder;
public final fun setSessionListener (Lcom/datadog/android/rum/RumSessionListener;)Lcom/datadog/android/rum/RumConfiguration$Builder;
public final fun setSessionSampleRate (F)Lcom/datadog/android/rum/RumConfiguration$Builder;
Expand Down Expand Up @@ -287,6 +288,32 @@ public abstract class com/datadog/android/rum/internal/instrumentation/gestures/
public fun onScroll (Landroid/view/MotionEvent;Landroid/view/MotionEvent;FF)Z
}

public abstract interface class com/datadog/android/rum/internal/metric/networksettled/InitialResourceIdentifier {
public abstract fun validate (Lcom/datadog/android/rum/internal/metric/networksettled/NetworkSettledResourceContext;)Z
}

public final class com/datadog/android/rum/internal/metric/networksettled/NetworkSettledResourceContext {
public fun <init> (Ljava/lang/String;JLjava/lang/Long;)V
public final fun copy (Ljava/lang/String;JLjava/lang/Long;)Lcom/datadog/android/rum/internal/metric/networksettled/NetworkSettledResourceContext;
public static synthetic fun copy$default (Lcom/datadog/android/rum/internal/metric/networksettled/NetworkSettledResourceContext;Ljava/lang/String;JLjava/lang/Long;ILjava/lang/Object;)Lcom/datadog/android/rum/internal/metric/networksettled/NetworkSettledResourceContext;
public fun equals (Ljava/lang/Object;)Z
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class com/datadog/android/rum/internal/metric/networksettled/TimeBasedInitialResourceIdentifier : com/datadog/android/rum/internal/metric/networksettled/InitialResourceIdentifier {
public static final field Companion Lcom/datadog/android/rum/internal/metric/networksettled/TimeBasedInitialResourceIdentifier$Companion;
public fun <init> ()V
public fun <init> (J)V
public synthetic fun <init> (JILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun equals (Ljava/lang/Object;)Z
public fun hashCode ()I
public fun validate (Lcom/datadog/android/rum/internal/metric/networksettled/NetworkSettledResourceContext;)Z
}

public final class com/datadog/android/rum/internal/metric/networksettled/TimeBasedInitialResourceIdentifier$Companion {
}

public abstract interface class com/datadog/android/rum/internal/monitor/AdvancedNetworkRumMonitor : com/datadog/android/rum/RumMonitor {
public abstract fun addResourceTiming (Ljava/lang/Object;Lcom/datadog/android/rum/internal/domain/event/ResourceTiming;)V
public abstract fun notifyInterceptorInstantiated ()V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ object Rum {
backgroundTrackingEnabled = rumFeature.backgroundEventTracking,
trackFrustrations = rumFeature.trackFrustrations,
sessionListener = rumFeature.sessionListener,
executorService = sdkCore.createSingleThreadExecutorService("rum-pipeline")
executorService = sdkCore.createSingleThreadExecutorService("rum-pipeline"),
networkSettledResourceIdentifier = rumFeature.networkSettledInitialResourceIdentifier
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import com.datadog.android.rum.configuration.VitalsUpdateFrequency
import com.datadog.android.rum.event.ViewEventMapper
import com.datadog.android.rum.internal.RumFeature
import com.datadog.android.rum.internal.instrumentation.MainLooperLongTaskStrategy
import com.datadog.android.rum.internal.metric.networksettled.InitialResourceIdentifier
import com.datadog.android.rum.internal.metric.networksettled.TimeBasedInitialResourceIdentifier
import com.datadog.android.rum.internal.tracking.NoOpInteractionPredicate
import com.datadog.android.rum.model.ActionEvent
import com.datadog.android.rum.model.ErrorEvent
Expand Down Expand Up @@ -257,6 +259,17 @@ data class RumConfiguration internal constructor(
return this
}

/**
* Sets the identifier strategy for initial network resources used to compute the time to network settled
* in a RUM View event. By default, the SDK uses a [TimeBasedInitialResourceIdentifier] with
* a threshold of 100ms.
* @param initialResourceIdentifier the [InitialResourceIdentifier] to use.
*/
fun setNetworkSettledInitialResourceIdentifier(initialResourceIdentifier: InitialResourceIdentifier): Builder {
rumConfig = rumConfig.copy(networkSettledInitialResourceIdentifier = initialResourceIdentifier)
return this
}

/**
* Builds a [RumConfiguration] based on the current state of this Builder.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ import com.datadog.android.rum.internal.instrumentation.MainLooperLongTaskStrate
import com.datadog.android.rum.internal.instrumentation.UserActionTrackingStrategyApi29
import com.datadog.android.rum.internal.instrumentation.UserActionTrackingStrategyLegacy
import com.datadog.android.rum.internal.instrumentation.gestures.DatadogGesturesTracker
import com.datadog.android.rum.internal.metric.networksettled.InitialResourceIdentifier
import com.datadog.android.rum.internal.metric.networksettled.NoOpInitialResourceIdentifier
import com.datadog.android.rum.internal.metric.networksettled.TimeBasedInitialResourceIdentifier
import com.datadog.android.rum.internal.monitor.AdvancedRumMonitor
import com.datadog.android.rum.internal.monitor.DatadogRumMonitor
import com.datadog.android.rum.internal.net.RumRequestFactory
Expand Down Expand Up @@ -127,6 +130,7 @@ internal class RumFeature(
private var anrDetectorExecutorService: ExecutorService? = null
internal var anrDetectorRunnable: ANRDetectorRunnable? = null
internal lateinit var appContext: Context
internal var networkSettledInitialResourceIdentifier: InitialResourceIdentifier = NoOpInitialResourceIdentifier()

private val lateCrashEventHandler by lazy { lateCrashReporterFactory(sdkCore as InternalSdkCore) }

Expand All @@ -136,7 +140,7 @@ internal class RumFeature(

override fun onInitialize(appContext: Context) {
this.appContext = appContext

networkSettledInitialResourceIdentifier = configuration.networkSettledInitialResourceIdentifier
dataWriter = createDataWriter(
configuration,
sdkCore as InternalSdkCore
Expand Down Expand Up @@ -530,6 +534,7 @@ internal class RumFeature(
val trackNonFatalAnrs: Boolean,
val vitalsMonitorUpdateFrequency: VitalsUpdateFrequency,
val sessionListener: RumSessionListener,
val networkSettledInitialResourceIdentifier: InitialResourceIdentifier,
val additionalConfig: Map<String, Any>
)

Expand Down Expand Up @@ -573,6 +578,7 @@ internal class RumFeature(
trackNonFatalAnrs = isTrackNonFatalAnrsEnabledByDefault(),
vitalsMonitorUpdateFrequency = VitalsUpdateFrequency.AVERAGE,
sessionListener = NoOpRumSessionListener(),
networkSettledInitialResourceIdentifier = TimeBasedInitialResourceIdentifier(),
additionalConfig = emptyMap()
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import com.datadog.android.rum.RumSessionListener
import com.datadog.android.rum.internal.domain.RumContext
import com.datadog.android.rum.internal.domain.Time
import com.datadog.android.rum.internal.metric.SessionMetricDispatcher
import com.datadog.android.rum.internal.metric.networksettled.InitialResourceIdentifier
import com.datadog.android.rum.internal.vitals.VitalMonitor
import java.util.concurrent.TimeUnit

Expand All @@ -33,7 +34,8 @@ internal class RumApplicationScope(
private val memoryVitalMonitor: VitalMonitor,
private val frameRateVitalMonitor: VitalMonitor,
private val sessionEndedMetricDispatcher: SessionMetricDispatcher,
private val sessionListener: RumSessionListener?
private val sessionListener: RumSessionListener?,
private val networkSettledResourceIdentifier: InitialResourceIdentifier
) : RumScope, RumViewChangedListener {

private var rumContext = RumContext(applicationId = applicationId)
Expand All @@ -52,7 +54,8 @@ internal class RumApplicationScope(
memoryVitalMonitor,
frameRateVitalMonitor,
sessionListener,
false
false,
networkSettledResourceIdentifier
)
)

Expand Down Expand Up @@ -144,7 +147,8 @@ internal class RumApplicationScope(
memoryVitalMonitor,
frameRateVitalMonitor,
sessionListener,
true
true,
networkSettledResourceIdentifier
)
childScopes.add(newSession)
if (event !is RumRawEvent.StartView) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.datadog.android.core.internal.net.FirstPartyHostHeaderTypeResolver
import com.datadog.android.rum.RumSessionListener
import com.datadog.android.rum.internal.domain.RumContext
import com.datadog.android.rum.internal.metric.SessionMetricDispatcher
import com.datadog.android.rum.internal.metric.networksettled.InitialResourceIdentifier
import com.datadog.android.rum.internal.utils.percent
import com.datadog.android.rum.internal.vitals.VitalMonitor
import java.security.SecureRandom
Expand All @@ -37,6 +38,7 @@ internal class RumSessionScope(
frameRateVitalMonitor: VitalMonitor,
private val sessionListener: RumSessionListener?,
applicationDisplayed: Boolean,
networkSettledResourceIdentifier: InitialResourceIdentifier,
private val sessionInactivityNanos: Long = DEFAULT_SESSION_INACTIVITY_NS,
private val sessionMaxDurationNanos: Long = DEFAULT_SESSION_MAX_DURATION_NS
) : RumScope {
Expand Down Expand Up @@ -66,7 +68,8 @@ internal class RumSessionScope(
memoryVitalMonitor,
frameRateVitalMonitor,
applicationDisplayed,
sampleRate
sampleRate,
networkSettledResourceIdentifier
)

init {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import com.datadog.android.rum.internal.domain.Time
import com.datadog.android.rum.internal.metric.SessionEndedMetric
import com.datadog.android.rum.internal.metric.SessionMetricDispatcher
import com.datadog.android.rum.internal.metric.interactiontonextview.InteractionToNextViewMetricResolver
import com.datadog.android.rum.internal.metric.networksettled.InitialResourceIdentifier
import com.datadog.android.rum.internal.metric.networksettled.NetworkSettledMetricResolver
import com.datadog.android.rum.internal.vitals.NoOpVitalMonitor
import com.datadog.android.rum.internal.vitals.VitalMonitor
import java.util.Locale
Expand All @@ -40,6 +42,7 @@ internal class RumViewManagerScope(
private val frameRateVitalMonitor: VitalMonitor,
internal var applicationDisplayed: Boolean,
internal val sampleRate: Float,
internal val networkSettledResourceIdentifier: InitialResourceIdentifier,
private val interactionToNextViewMetricResolver: InteractionToNextViewMetricResolver =
InteractionToNextViewMetricResolver(internalLogger = sdkCore.internalLogger)
) : RumScope {
Expand Down Expand Up @@ -202,7 +205,8 @@ internal class RumViewManagerScope(
frameRateVitalMonitor,
trackFrustrations,
sampleRate,
interactionToNextViewMetricResolver
interactionToNextViewMetricResolver,
networkSettledResourceIdentifier
)
applicationDisplayed = true
childrenScopes.add(viewScope)
Expand Down Expand Up @@ -265,7 +269,11 @@ internal class RumViewManagerScope(
type = RumViewScope.RumViewType.BACKGROUND,
trackFrustrations = trackFrustrations,
sampleRate = sampleRate,
interactionToNextViewMetricResolver = interactionToNextViewMetricResolver
interactionToNextViewMetricResolver = interactionToNextViewMetricResolver,
networkSettledMetricResolver = NetworkSettledMetricResolver(
networkSettledResourceIdentifier,
sdkCore.internalLogger
)
)
}

Expand All @@ -289,7 +297,11 @@ internal class RumViewManagerScope(
type = RumViewScope.RumViewType.APPLICATION_LAUNCH,
trackFrustrations = trackFrustrations,
sampleRate = sampleRate,
interactionToNextViewMetricResolver = interactionToNextViewMetricResolver
interactionToNextViewMetricResolver = interactionToNextViewMetricResolver,
networkSettledMetricResolver = NetworkSettledMetricResolver(
networkSettledResourceIdentifier,
sdkCore.internalLogger
)
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import com.datadog.android.rum.internal.domain.Time
import com.datadog.android.rum.internal.metric.SessionMetricDispatcher
import com.datadog.android.rum.internal.metric.interactiontonextview.InteractionToNextViewMetricResolver
import com.datadog.android.rum.internal.metric.interactiontonextview.InternalInteractionContext
import com.datadog.android.rum.internal.metric.networksettled.InitialResourceIdentifier
import com.datadog.android.rum.internal.metric.networksettled.NetworkSettledMetricResolver
import com.datadog.android.rum.internal.monitor.StorageEvent
import com.datadog.android.rum.internal.utils.hasUserData
Expand Down Expand Up @@ -62,8 +63,7 @@ internal open class RumViewScope(
private val trackFrustrations: Boolean,
internal val sampleRate: Float,
private val interactionToNextViewMetricResolver: InteractionToNextViewMetricResolver,
private val networkSettledMetricResolver: NetworkSettledMetricResolver =
NetworkSettledMetricResolver(internalLogger = sdkCore.internalLogger)
private val networkSettledMetricResolver: NetworkSettledMetricResolver
) : RumScope {

internal val url = key.url.replace('.', '/')
Expand Down Expand Up @@ -330,10 +330,10 @@ internal open class RumViewScope(
event: RumRawEvent.StopView,
writer: DataWriter<Any>
) {
networkSettledMetricResolver.viewWasStopped()
delegateEventToChildren(event, writer)
val shouldStop = (event.key.id == key.id)
if (shouldStop && !stopped) {
networkSettledMetricResolver.viewWasStopped()
stopScope(event, writer) {
// we should not reset the timestamp offset here as due to async nature of feature context update
// we still need a stable value for the view timestamp offset for WebView RUM events timestamp
Expand Down Expand Up @@ -1350,7 +1350,8 @@ internal open class RumViewScope(
frameRateVitalMonitor: VitalMonitor,
trackFrustrations: Boolean,
sampleRate: Float,
interactionToNextViewMetricResolver: InteractionToNextViewMetricResolver
interactionToNextViewMetricResolver: InteractionToNextViewMetricResolver,
networkSettledResourceIdentifier: InitialResourceIdentifier
): RumViewScope {
return RumViewScope(
parentScope,
Expand All @@ -1366,7 +1367,11 @@ internal open class RumViewScope(
frameRateVitalMonitor,
trackFrustrations = trackFrustrations,
sampleRate = sampleRate,
interactionToNextViewMetricResolver = interactionToNextViewMetricResolver
interactionToNextViewMetricResolver = interactionToNextViewMetricResolver,
networkSettledMetricResolver = NetworkSettledMetricResolver(
networkSettledResourceIdentifier,
sdkCore.internalLogger
)
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,17 @@ package com.datadog.android.rum.internal.metric.networksettled

import com.datadog.tools.annotation.NoOpImplementation

/**
* Interface for identifying initial network resources.
*/
@NoOpImplementation
internal interface InitialResourceIdentifier {
interface InitialResourceIdentifier {
/**
* Validates whether the given network resource context meets the criteria for an initial resource.
*
* @param context The context of the network resource to validate.
* @return `true` if the context meets the criteria, `false` otherwise.
*/
fun validate(
context: NetworkSettledResourceContext
): Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@

package com.datadog.android.rum.internal.metric.networksettled

internal data class NetworkSettledResourceContext(
/**
* Represents the context of a network resource that has settled.
*
* @property resourceId The unique identifier of the network resource.
* @property eventCreatedAtNanos The timestamp (in nanoseconds) when the event was created.
* @property viewCreatedTimestamp The timestamp (in nanoseconds) when the view was created, or null if not applicable.
*/
data class NetworkSettledResourceContext(
internal val resourceId: String,
internal val eventCreatedAtNanos: Long,
internal val viewCreatedTimestamp: Long?
Expand Down
Loading

0 comments on commit dd94ef2

Please sign in to comment.