Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
05535a2
RUM-10363: Replace all System static calls to TimeProvider
kikoveiga Nov 17, 2025
2475ff6
RUM-10363: Begin simplification
kikoveiga Nov 18, 2025
bc0d909
RUM-10363: Local CI tests pass
kikoveiga Nov 18, 2025
ca5ef5b
Merge branch 'develop' into kikoveiga/RUM-10363/use-time-provider
kikoveiga Nov 18, 2025
bde228e
RUM-10363: Fix detekt
kikoveiga Nov 18, 2025
fe46009
Merge remote-tracking branch 'origin/kikoveiga/RUM-10363/use-time-pro…
kikoveiga Nov 18, 2025
d95c227
RUM-10363: Fix documentation
kikoveiga Nov 18, 2025
127a3b8
RUM-10363: Small improvements
kikoveiga Nov 19, 2025
4fea2b5
RUM-10363: Remove NoOpTimeProvider
kikoveiga Nov 19, 2025
a7972b0
RUM-10363: Remove SdkTimeProvider.kt, local CI working
kikoveiga Nov 19, 2025
7ddfa2f
RUM-10363: Update api files
kikoveiga Nov 19, 2025
3b13a23
Merge branch 'develop' into kikoveiga/RUM-10363/use-time-provider
kikoveiga Nov 19, 2025
82947e8
RUM-10363: Revert test files changes
kikoveiga Nov 19, 2025
14fe852
RUM-10363: Continue improving tests
kikoveiga Nov 20, 2025
779a6cf
RUM-10363: Compilation errors fixed on tests
kikoveiga Nov 20, 2025
f02a916
Merge branch 'develop' into kikoveiga/RUM-10363/use-time-provider
kikoveiga Nov 20, 2025
01a9fa6
RUM-10363: Fix test
kikoveiga Nov 20, 2025
8fc31c5
RUM-10363: Continue fixing tests
kikoveiga Nov 20, 2025
f5c25e2
RUM-10363: Continue fixing tests
kikoveiga Nov 20, 2025
4ceba2d
RUM-10363: Continue fixing tests
kikoveiga Nov 20, 2025
3b37f8a
RUM-10363: Fix ktlint
kikoveiga Nov 20, 2025
38e08a8
RUM-10363: Continue fixing tests
kikoveiga Nov 20, 2025
5fa41d5
RUM-10363: Tests pass
kikoveiga Nov 21, 2025
ec09360
RUM-10363: Fix ktlint
kikoveiga Nov 21, 2025
405f014
Merge branch 'develop' into kikoveiga/RUM-10363/use-time-provider
kikoveiga Nov 21, 2025
50978b7
RUM-10363: Small improvements
kikoveiga Nov 21, 2025
8db5d89
RUM-10363: Update api files
kikoveiga Nov 21, 2025
4676a54
RUM-10363: Add timeProvider to StubSDKCore.kt
kikoveiga Nov 23, 2025
e1a033a
Merge branch 'develop' into kikoveiga/RUM-10363/use-time-provider
kikoveiga Nov 23, 2025
3a43bca
RUM-10363: Test fix for min API integration test
kikoveiga Nov 24, 2025
d0e0b3c
Merge remote-tracking branch 'origin/kikoveiga/RUM-10363/use-time-pro…
kikoveiga Nov 24, 2025
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
3 changes: 2 additions & 1 deletion dd-sdk-android-core/api/apiSurface
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ fun <R: Any?> com.datadog.android.api.InternalLogger.measureMethodCallPerf(Class
fun FeatureScope.getContextFuture(Set<String> = emptySet()): java.util.concurrent.Future<com.datadog.android.api.context.DatadogContext?>?
interface com.datadog.android.api.feature.FeatureSdkCore : com.datadog.android.api.SdkCore
val internalLogger: com.datadog.android.api.InternalLogger
val timeProvider: com.datadog.android.internal.time.TimeProvider
fun registerFeature(Feature)
fun getFeature(String): FeatureScope?
fun updateFeatureContext(String, Boolean = true, (MutableMap<String, Any?>) -> Unit)
Expand Down Expand Up @@ -363,7 +364,7 @@ interface com.datadog.android.core.sampling.Sampler<T: Any>
interface com.datadog.android.core.thread.FlushableExecutorService : java.util.concurrent.ExecutorService
fun drainTo(MutableCollection<Runnable>)
interface Factory
fun create(com.datadog.android.api.InternalLogger, String, com.datadog.android.core.configuration.BackPressureStrategy): FlushableExecutorService
fun create(com.datadog.android.api.InternalLogger, String, com.datadog.android.core.configuration.BackPressureStrategy, com.datadog.android.internal.time.TimeProvider): FlushableExecutorService
interface com.datadog.android.event.EventMapper<T: Any>
fun map(T): T?
class com.datadog.android.event.MapperSerializer<T: Any> : com.datadog.android.core.persistence.Serializer<T>
Expand Down
3 changes: 2 additions & 1 deletion dd-sdk-android-core/api/dd-sdk-android-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ public abstract interface class com/datadog/android/api/feature/FeatureSdkCore :
public abstract fun getFeature (Ljava/lang/String;)Lcom/datadog/android/api/feature/FeatureScope;
public abstract fun getFeatureContext (Ljava/lang/String;Z)Ljava/util/Map;
public abstract fun getInternalLogger ()Lcom/datadog/android/api/InternalLogger;
public abstract fun getTimeProvider ()Lcom/datadog/android/internal/time/TimeProvider;
public abstract fun registerFeature (Lcom/datadog/android/api/feature/Feature;)V
public abstract fun removeContextUpdateReceiver (Lcom/datadog/android/api/feature/FeatureContextUpdateReceiver;)V
public abstract fun removeEventReceiver (Ljava/lang/String;)V
Expand Down Expand Up @@ -955,7 +956,7 @@ public abstract interface class com/datadog/android/core/thread/FlushableExecuto
}

public abstract interface class com/datadog/android/core/thread/FlushableExecutorService$Factory {
public abstract fun create (Lcom/datadog/android/api/InternalLogger;Ljava/lang/String;Lcom/datadog/android/core/configuration/BackPressureStrategy;)Lcom/datadog/android/core/thread/FlushableExecutorService;
public abstract fun create (Lcom/datadog/android/api/InternalLogger;Ljava/lang/String;Lcom/datadog/android/core/configuration/BackPressureStrategy;Lcom/datadog/android/internal/time/TimeProvider;)Lcom/datadog/android/core/thread/FlushableExecutorService;
}

public abstract interface class com/datadog/android/event/EventMapper {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package com.datadog.android.api.feature

import com.datadog.android.api.InternalLogger
import com.datadog.android.api.SdkCore
import com.datadog.android.internal.time.TimeProvider
import okhttp3.Call
import okhttp3.OkHttpClient
import java.util.UUID
Expand All @@ -27,6 +28,11 @@ interface FeatureSdkCore : SdkCore {
*/
val internalLogger: InternalLogger

/**
* The [TimeProvider] used by this core instance for current timestamps.
*/
val timeProvider: TimeProvider

/**
* Registers a feature to this instance of the Datadog SDK.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ internal class CoreFeature(
.writeTimeout(NETWORK_TIMEOUT_MS, TimeUnit.MILLISECONDS)
.protocols(listOf(Protocol.HTTP_2, Protocol.HTTP_1_1))
.connectionSpecs(listOf(connectionSpec))
.dns(RotatingDnsResolver()) // NPE cannot happen here
.dns(RotatingDnsResolver(timeProvider = timeProvider)) // NPE cannot happen here
.build()
}

Expand Down Expand Up @@ -323,7 +323,7 @@ internal class CoreFeature(
}

fun createExecutorService(executorContext: String): ExecutorService {
return executorServiceFactory.create(internalLogger, executorContext, backpressureStrategy)
return executorServiceFactory.create(internalLogger, executorContext, backpressureStrategy, timeProvider)
}

fun createScheduledExecutorService(executorContext: String): ScheduledExecutorService {
Expand Down Expand Up @@ -648,7 +648,8 @@ internal class CoreFeature(
persistenceExecutorService = executorServiceFactory.create(
internalLogger = internalLogger,
executorContext = "storage",
backPressureStrategy = backpressureStrategy
backPressureStrategy = backpressureStrategy,
timeProvider = timeProvider
)
val contextQueue = BackPressuredBlockingQueue<Runnable>(
internalLogger,
Expand All @@ -658,7 +659,8 @@ internal class CoreFeature(
// just notify when reached
onItemDropped = {},
onThresholdReached = {},
backpressureMitigation = null
backpressureMitigation = null,
timeProvider = timeProvider
)
@Suppress("UnsafeThirdPartyFunctionCall") // all parameters are safe
contextExecutorService = ThreadPoolExecutor(
Expand Down Expand Up @@ -749,8 +751,8 @@ internal class CoreFeature(
" process of your application."

internal val DEFAULT_FLUSHABLE_EXECUTOR_SERVICE_FACTORY =
FlushableExecutorService.Factory { logger, executorContext, backPressureStrategy ->
BackPressureExecutorService(logger, executorContext, backPressureStrategy)
FlushableExecutorService.Factory { logger, executorContext, backPressureStrategy, timeProvider ->
BackPressureExecutorService(logger, executorContext, backPressureStrategy, timeProvider)
}

internal val DEFAULT_SCHEDULED_EXECUTOR_SERVICE_FACTORY =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ import com.datadog.android.core.internal.utils.submitSafe
import com.datadog.android.core.thread.FlushableExecutorService
import com.datadog.android.error.internal.CrashReportsFeature
import com.datadog.android.internal.telemetry.InternalTelemetryEvent
import com.datadog.android.internal.time.DefaultTimeProvider
import com.datadog.android.internal.time.TimeProvider
import com.datadog.android.privacy.TrackingConsent
import com.google.gson.JsonObject
import okhttp3.Call
Expand Down Expand Up @@ -117,6 +119,10 @@ internal class DatadogCore(
override val service: String
get() = coreFeature.serviceName

/** @inheritDoc */
override val timeProvider: TimeProvider
get() = coreFeature.timeProvider

/** @inheritDoc */
override val firstPartyHostResolver: FirstPartyHostHeaderTypeResolver
get() = coreFeature.firstPartyHostHeaderTypeResolver
Expand Down Expand Up @@ -458,7 +464,7 @@ internal class DatadogCore(
executorServiceFactory ?: CoreFeature.DEFAULT_FLUSHABLE_EXECUTOR_SERVICE_FACTORY
coreFeature = CoreFeature(
internalLogger,
DefaultAppStartTimeProvider(),
DefaultAppStartTimeProvider(DefaultTimeProvider()),
flushableExecutorServiceFactory,
CoreFeature.DEFAULT_SCHEDULED_EXECUTOR_SERVICE_FACTORY
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import com.datadog.android.core.InternalSdkCore
import com.datadog.android.core.internal.logger.SdkInternalLogger
import com.datadog.android.core.internal.net.DefaultFirstPartyHostHeaderTypeResolver
import com.datadog.android.core.internal.net.FirstPartyHostHeaderTypeResolver
import com.datadog.android.internal.time.DefaultTimeProvider
import com.datadog.android.internal.time.TimeProvider
import com.datadog.android.privacy.TrackingConsent
import com.google.gson.JsonObject
import okhttp3.Call
Expand All @@ -45,7 +47,7 @@ internal object NoOpInternalSdkCore : InternalSdkCore {

override val name: String = "no-op"

override val time: TimeInfo = with(System.currentTimeMillis()) {
override val time: TimeInfo = with(timeProvider.getDeviceTimestamp()) {
TimeInfo(
deviceTimeNs = TimeUnit.MILLISECONDS.toNanos(this),
serverTimeNs = TimeUnit.MILLISECONDS.toNanos(this),
Expand All @@ -54,6 +56,9 @@ internal object NoOpInternalSdkCore : InternalSdkCore {
)
}

override val timeProvider: TimeProvider
get() = DefaultTimeProvider()

override val service: String
get() = ""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,8 @@ internal class SdkFeature(
executorService = coreFeature.persistenceExecutorService,
filePersistenceConfig = filePersistenceConfig,
internalLogger = internalLogger,
metricsDispatcher = metricsDispatcher
metricsDispatcher = metricsDispatcher,
timeProvider = coreFeature.timeProvider
)
this.fileOrchestrator = fileOrchestrator

Expand Down Expand Up @@ -398,7 +399,8 @@ internal class SdkFeature(
sdkVersion = coreFeature.sdkVersion,
androidInfoProvider = coreFeature.androidInfoProvider,
executionTimer = GlobalBenchmark.createExecutionTimer(
track = wrappedFeature.name
track = wrappedFeature.name,
timeProvider = coreFeature.timeProvider
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

package com.datadog.android.core.internal.data.upload

import com.datadog.android.internal.time.TimeProvider
import okhttp3.Dns
import java.net.InetAddress
import kotlin.time.Duration
Expand All @@ -14,17 +15,19 @@ import kotlin.time.Duration.Companion.nanoseconds

internal class RotatingDnsResolver(
private val delegate: Dns = Dns.SYSTEM,
private val ttl: Duration = TTL_30_MIN
private val ttl: Duration = TTL_30_MIN,
private val timeProvider: TimeProvider
) : Dns {

data class ResolvedHost(
val hostname: String,
val addresses: MutableList<InetAddress>
val addresses: MutableList<InetAddress>,
private val timeProvider: TimeProvider
) {
private val resolutionTimestamp: Long = System.nanoTime()
private val resolutionTimestamp: Long = timeProvider.getDeviceElapsedTimeNs()

fun getAge(): Duration {
return (System.nanoTime() - resolutionTimestamp).nanoseconds
return (timeProvider.getDeviceElapsedTimeNs() - resolutionTimestamp).nanoseconds
}

fun rotate() {
Expand All @@ -50,7 +53,7 @@ internal class RotatingDnsResolver(
} else {
@Suppress("UnsafeThirdPartyFunctionCall") // handled by caller
val result = delegate.lookup(hostname)
knownHosts[hostname] = ResolvedHost(hostname, result.toMutableList())
knownHosts[hostname] = ResolvedHost(hostname, result.toMutableList(), timeProvider)
safeCopy(result)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.datadog.android.core.sampling.RateBasedSampler
import com.datadog.android.internal.attributes.LocalAttribute
import com.datadog.android.internal.attributes.enrichWithNonNullAttribute
import com.datadog.android.internal.telemetry.InternalTelemetryEvent
import com.datadog.android.internal.time.DefaultTimeProvider

internal class SdkInternalLogger(
private val sdkCore: FeatureSdkCore?,
Expand Down Expand Up @@ -134,7 +135,8 @@ internal class SdkInternalLogger(
internalLogger = this,
operationName = operationName,
callerClass = callerClass,
creationSampleRate = samplingRate
creationSampleRate = samplingRate,
timeProvider = sdkCore?.timeProvider ?: DefaultTimeProvider()
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ internal class BatchMetricsDispatcher(
private val uploadConfiguration: DataUploadConfiguration?,
private val filePersistenceConfig: FilePersistenceConfig,
private val internalLogger: InternalLogger,
private val dateTimeProvider: TimeProvider
private val timeProvider: TimeProvider

) : MetricsDispatcher, ProcessLifecycleMonitor.Callback {

Expand Down Expand Up @@ -90,7 +90,7 @@ internal class BatchMetricsDispatcher(
numPendingBatches: Int
): Map<String, Any?>? {
val fileCreationTimestamp = file.nameAsTimestampSafe(internalLogger) ?: return null
val fileAgeInMillis = dateTimeProvider.getDeviceTimestamp() - fileCreationTimestamp
val fileAgeInMillis = timeProvider.getDeviceTimestamp() - fileCreationTimestamp
if (fileAgeInMillis < 0) {
// the device time was manually modified or the time zone changed
// we are dropping this metric to not skew our charts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,28 @@ import com.datadog.android.api.InternalLogger
import com.datadog.android.core.metrics.MethodCallSamplingRate
import com.datadog.android.core.metrics.PerformanceMetric
import com.datadog.android.core.metrics.PerformanceMetric.Companion.METRIC_TYPE
import com.datadog.android.internal.time.TimeProvider

/**
* Performance metric to measure the execution time for a method.
* @param internalLogger - an instance of the internal logger.
* @param operationName the operation name
* @param callerClass - the class calling the performance metric.
* @param creationSampleRate - sampling frequency used to create the metric
* @param startTime - the time when the metric is instantiated, to be used as the start point for the measurement.
* @param timeProvider - the provider for time measurements.
*/
internal class MethodCalledTelemetry(
internal val internalLogger: InternalLogger,
internal val operationName: String,
internal val callerClass: String,
internal val creationSampleRate: Float,
internal val startTime: Long = System.nanoTime()
internal val timeProvider: TimeProvider
) : PerformanceMetric {

internal val startTime: Long = timeProvider.getDeviceElapsedTimeNs()

override fun stopAndSend(isSuccessful: Boolean) {
val executionTime = System.nanoTime() - startTime
val executionTime = timeProvider.getDeviceElapsedTimeNs() - startTime
val additionalProperties: MutableMap<String, Any> = mutableMapOf()

additionalProperties[EXECUTION_TIME] = executionTime
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import androidx.annotation.WorkerThread
import com.datadog.android.api.InternalLogger
import com.datadog.android.core.internal.persistence.file.FileMover
import com.datadog.android.core.internal.persistence.file.FileOrchestrator
import com.datadog.android.internal.time.TimeProvider
import com.datadog.android.privacy.TrackingConsent

internal class ConsentAwareFileMigrator(
private val fileMover: FileMover,
private val internalLogger: InternalLogger
private val internalLogger: InternalLogger,
private val timeProvider: TimeProvider
) : DataMigrator<TrackingConsent> {

@WorkerThread
Expand Down Expand Up @@ -47,7 +49,8 @@ internal class ConsentAwareFileMigrator(
WipeDataMigrationOperation(
previousFileOrchestrator.getRootDir(),
fileMover,
internalLogger
internalLogger,
timeProvider
)
}

Expand All @@ -56,7 +59,8 @@ internal class ConsentAwareFileMigrator(
WipeDataMigrationOperation(
newFileOrchestrator.getRootDir(),
fileMover,
internalLogger
internalLogger,
timeProvider
)
}

Expand All @@ -65,7 +69,8 @@ internal class ConsentAwareFileMigrator(
previousFileOrchestrator.getRootDir(),
newFileOrchestrator.getRootDir(),
fileMover,
internalLogger
internalLogger,
timeProvider
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.datadog.android.core.internal.persistence.file.FileOrchestrator
import com.datadog.android.core.internal.persistence.file.FilePersistenceConfig
import com.datadog.android.core.internal.persistence.file.batch.BatchFileOrchestrator
import com.datadog.android.core.internal.privacy.ConsentProvider
import com.datadog.android.internal.time.TimeProvider
import com.datadog.android.privacy.TrackingConsent
import java.io.File
import java.util.Locale
Expand Down Expand Up @@ -41,24 +42,28 @@ internal class FeatureFileOrchestrator(
executorService: ExecutorService,
filePersistenceConfig: FilePersistenceConfig,
internalLogger: InternalLogger,
metricsDispatcher: MetricsDispatcher
metricsDispatcher: MetricsDispatcher,
timeProvider: TimeProvider
) : this(
consentProvider,
BatchFileOrchestrator(
File(storageDir, PENDING_DIR.format(Locale.US, featureName)),
filePersistenceConfig,
internalLogger,
metricsDispatcher
metricsDispatcher,
timeProvider
),
BatchFileOrchestrator(
File(storageDir, GRANTED_DIR.format(Locale.US, featureName)),
filePersistenceConfig,
internalLogger,
metricsDispatcher
metricsDispatcher,
timeProvider
),
ConsentAwareFileMigrator(
FileMover(internalLogger),
internalLogger
internalLogger,
timeProvider
),
executorService,
internalLogger
Expand Down
Loading
Loading