Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@
import io.sentry.protocol.Message;
import io.sentry.protocol.SentryId;
import io.sentry.protocol.SentryThread;
import io.sentry.transport.CurrentDateProvider;
import io.sentry.transport.ICurrentDateProvider;
import io.sentry.util.HintUtils;
import io.sentry.util.Objects;
import java.io.BufferedReader;
Expand All @@ -47,19 +45,10 @@
public final class AnrV2Integration implements Integration, Closeable {

private final @NotNull Context context;
private final @NotNull ICurrentDateProvider dateProvider;
private @Nullable SentryAndroidOptions options;

public AnrV2Integration(final @NotNull Context context) {
// using CurrentDateProvider instead of AndroidCurrentDateProvider as AppExitInfo uses
// System.currentTimeMillis
this(context, CurrentDateProvider.getInstance());
}

AnrV2Integration(
final @NotNull Context context, final @NotNull ICurrentDateProvider dateProvider) {
this.context = ContextUtils.getApplicationContext(context);
this.dateProvider = dateProvider;
}

@SuppressLint("NewApi") // we do the check in the AnrIntegrationFactory
Expand Down Expand Up @@ -88,7 +77,7 @@ public void register(@NotNull IScopes scopes, @NotNull SentryOptions options) {
.getExecutorService()
.submit(
new ApplicationExitInfoHistoryDispatcher(
context, scopes, this.options, dateProvider, new AnrV2Policy(this.options)));
context, scopes, this.options, new AnrV2Policy(this.options)));
} catch (Throwable e) {
options.getLogger().log(SentryLevel.DEBUG, "Failed to start ANR processor.", e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import io.sentry.cache.IEnvelopeCache;
import io.sentry.hints.BlockingFlushHint;
import io.sentry.protocol.SentryId;
import io.sentry.transport.ICurrentDateProvider;
import io.sentry.util.HintUtils;
import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -57,13 +56,13 @@ final class ApplicationExitInfoHistoryDispatcher implements Runnable {
final @NotNull Context context,
final @NotNull IScopes scopes,
final @NotNull SentryAndroidOptions options,
final @NotNull ICurrentDateProvider dateProvider,
final @NotNull ApplicationExitInfoPolicy policy) {
this.context = ContextUtils.getApplicationContext(context);
this.scopes = scopes;
this.options = options;
this.policy = policy;
this.threshold = dateProvider.getCurrentTimeMillis() - NINETY_DAYS_THRESHOLD;
// ApplicationExitInfo timestamps are epoch millis, so the cutoff has to be on the wall clock.
this.threshold = options.getEpochClock().now().epochMillis() - NINETY_DAYS_THRESHOLD;
}

@RequiresApi(api = Build.VERSION_CODES.R)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@
import io.sentry.protocol.Message;
import io.sentry.protocol.SentryException;
import io.sentry.protocol.SentryId;
import io.sentry.transport.CurrentDateProvider;
import io.sentry.transport.ICurrentDateProvider;
import io.sentry.util.ExceptionUtils;
import io.sentry.util.HintUtils;
import io.sentry.util.Objects;
Expand All @@ -41,7 +39,6 @@
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;

/**
* Reports Android process deaths that the OS records as <a
Expand Down Expand Up @@ -85,24 +82,12 @@ public final class MemoryLimiterIntegration implements Integration, Closeable {
static final @NotNull String PROCESS_IMPORTANCE_FINGERPRINT_PREFIX = "process_importance:";

private final @NotNull Context context;
private final @NotNull ICurrentDateProvider dateProvider;
private final @NotNull BuildInfoProvider buildInfoProvider;
private @Nullable SentryAndroidOptions androidOptions;

public MemoryLimiterIntegration(
final @NotNull Context context, final @NotNull BuildInfoProvider buildInfoProvider) {
// Use CurrentDateProvider instead of AndroidCurrentDateProvider as ApplicationExitInfo uses
// epochal System.currentTimeMillis and not time since boot.
this(context, CurrentDateProvider.getInstance(), buildInfoProvider);
}

@TestOnly
MemoryLimiterIntegration(
final @NotNull Context context,
final @NotNull ICurrentDateProvider dateProvider,
final @NotNull BuildInfoProvider buildInfoProvider) {
this.context = ContextUtils.getApplicationContext(context);
this.dateProvider = dateProvider;
this.buildInfoProvider = buildInfoProvider;
}

Expand Down Expand Up @@ -146,11 +131,7 @@ public void register(@NotNull IScopes scopes, @NotNull SentryOptions options) {
.getExecutorService()
.submit(
new ApplicationExitInfoHistoryDispatcher(
context,
scopes,
androidOptions,
dateProvider,
new MemoryLimiterPolicy(androidOptions)));
context, scopes, androidOptions, new MemoryLimiterPolicy(androidOptions)));
} catch (Throwable e) {
ExceptionUtils.rethrowIfFatal(e);
options.getLogger().log(DEBUG, "Failed to start MemoryLimiter processor.", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@
import io.sentry.protocol.SentryException;
import io.sentry.protocol.SentryId;
import io.sentry.protocol.SentryThread;
import io.sentry.transport.CurrentDateProvider;
import io.sentry.transport.ICurrentDateProvider;
import io.sentry.util.HintUtils;
import io.sentry.util.Objects;
import java.io.ByteArrayInputStream;
Expand All @@ -51,19 +49,10 @@
@ApiStatus.Internal
public final class TombstoneIntegration implements Integration, Closeable {
private final @NotNull Context context;
private final @NotNull ICurrentDateProvider dateProvider;
private @Nullable SentryAndroidOptions options;

public TombstoneIntegration(final @NotNull Context context) {
// using CurrentDateProvider instead of AndroidCurrentDateProvider as AppExitInfo uses
// System.currentTimeMillis
this(context, CurrentDateProvider.getInstance());
}

TombstoneIntegration(
final @NotNull Context context, final @NotNull ICurrentDateProvider dateProvider) {
this.context = ContextUtils.getApplicationContext(context);
this.dateProvider = dateProvider;
}

@Override
Expand Down Expand Up @@ -97,7 +86,6 @@ public void register(@NotNull IScopes scopes, @NotNull SentryOptions options) {
context,
scopes,
this.options,
dateProvider,
new TombstonePolicy(this.options, this.context)));
} catch (Throwable e) {
options.getLogger().log(SentryLevel.DEBUG, "Failed to start tombstone processor.", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,7 @@ class ApplicationExitInfoCrossIntegrationTest {
}
val buildInfoProvider = mock<BuildInfoProvider>()
whenever(buildInfoProvider.sdkInfoVersion).thenReturn(37)
MemoryLimiterIntegration(
fixture.context,
io.sentry.transport.CurrentDateProvider.getInstance(),
buildInfoProvider,
)
MemoryLimiterIntegration(fixture.context, buildInfoProvider)
.register(memoryLimiterScopes, memoryLimiterOptions)

verify(memoryLimiterScopes)
Expand Down Expand Up @@ -224,11 +220,7 @@ class ApplicationExitInfoCrossIntegrationTest {
}
val buildInfoProvider = mock<BuildInfoProvider>()
whenever(buildInfoProvider.sdkInfoVersion).thenReturn(37)
MemoryLimiterIntegration(
fixture.context,
io.sentry.transport.CurrentDateProvider.getInstance(),
buildInfoProvider,
)
MemoryLimiterIntegration(fixture.context, buildInfoProvider)
.register(memoryLimiterScopes, memoryLimiterOptions)

verify(memoryLimiterScopes)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import io.sentry.android.core.cache.AndroidEnvelopeCache
import io.sentry.cache.EnvelopeCache
import io.sentry.protocol.SentryId
import io.sentry.test.ImmediateExecutorService
import io.sentry.transport.CurrentDateProvider
import io.sentry.util.HintUtils
import java.io.File
import kotlin.test.BeforeTest
Expand Down Expand Up @@ -105,7 +104,7 @@ class MemoryLimiterIntegrationTest {
whenever(scopes.captureEvent(any(), anyOrNull<Hint>())).thenReturn(SentryId())
val buildInfoProvider = mock<BuildInfoProvider>()
whenever(buildInfoProvider.sdkInfoVersion).thenReturn(sdkVersion)
return MemoryLimiterIntegration(context, CurrentDateProvider.getInstance(), buildInfoProvider)
return MemoryLimiterIntegration(context, buildInfoProvider)
}

fun addAppExitInfo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import io.sentry.SentryDate
import io.sentry.SpanDataConvention
import io.sentry.SpanOptions
import io.sentry.TypeCheckHint
import io.sentry.transport.CurrentDateProvider
import io.sentry.util.Platform
import io.sentry.util.UrlUtils
import io.sentry.util.network.NetworkRequestData
Expand Down Expand Up @@ -51,7 +50,7 @@ internal class SentryOkHttpEvent(private val scopes: IScopes, private val reques
// needs this as unix timestamp for rrweb
setData(
SpanDataConvention.HTTP_START_TIMESTAMP,
CurrentDateProvider.getInstance().currentTimeMillis,
scopes.options.epochClock.now().epochMillis(),
)
}

Expand Down Expand Up @@ -177,7 +176,7 @@ internal class SentryOkHttpEvent(private val scopes: IScopes, private val reques
// needs this as unix timestamp for rrweb
breadcrumb.setData(
SpanDataConvention.HTTP_END_TIMESTAMP,
CurrentDateProvider.getInstance().currentTimeMillis,
scopes.options.epochClock.now().epochMillis(),
)
// We send the breadcrumb even without spans.
scopes.addBreadcrumb(breadcrumb, hint)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import io.sentry.TypeCheckHint.OKHTTP_REQUEST
import io.sentry.TypeCheckHint.OKHTTP_RESPONSE
import io.sentry.TypeCheckHint.SENTRY_REPLAY_NETWORK_DETAILS
import io.sentry.clientreport.DiscardReason
import io.sentry.transport.CurrentDateProvider
import io.sentry.util.ExceptionUtils
import io.sentry.util.IntegrationUtils.addIntegrationToSdkVersion
import io.sentry.util.Platform
Expand Down Expand Up @@ -109,7 +108,7 @@ public open class SentryOkHttpInterceptor(
)
}

val startTimestamp = CurrentDateProvider.getInstance().currentTimeMillis
val startTimestamp = scopes.options.epochClock.now().epochMillis()

urlDetails.applyToSpan(span)

Expand Down Expand Up @@ -269,7 +268,7 @@ public open class SentryOkHttpInterceptor(
breadcrumb.setData(SpanDataConvention.HTTP_START_TIMESTAMP, startTimestamp)
breadcrumb.setData(
SpanDataConvention.HTTP_END_TIMESTAMP,
CurrentDateProvider.getInstance().currentTimeMillis,
scopes.options.epochClock.now().epochMillis(),
)

scopes.addBreadcrumb(breadcrumb, hint)
Expand Down
1 change: 1 addition & 0 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -7760,6 +7760,7 @@ public final class io/sentry/time/SystemEpochClock : io/sentry/time/EpochClock {
}

public final class io/sentry/time/Timestamp {
public fun epochMillis ()J
public fun epochNanos ()J
public fun equals (Ljava/lang/Object;)Z
public fun hashCode ()I
Expand Down
6 changes: 6 additions & 0 deletions sentry/src/main/java/io/sentry/time/Timestamp.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.sentry.time;

import java.util.concurrent.TimeUnit;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -34,6 +35,11 @@ public long epochNanos() {
return epochNanos;
}

/** Truncated to whole milliseconds, the precision of {@link java.util.Date} and most payloads. */
public long epochMillis() {
return TimeUnit.NANOSECONDS.toMillis(epochNanos);
}

@Override
public boolean equals(final @Nullable Object other) {
if (this == other) {
Expand Down
6 changes: 6 additions & 0 deletions sentry/src/test/java/io/sentry/time/TimestampTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ class TimestampTest {
.isEqualTo(1_700_000_000_000_000_000)
}

@Test
fun `truncates to whole milliseconds`() {
assertThat(Timestamp.ofEpochNanos(1_700_000_000_123_999_999).epochMillis())
.isEqualTo(1_700_000_000_123)
}

@Test
fun `compares by instant, whatever produced it`() {
val anchored = AnchoredClock.create(FixedEpochClock(42), TestMonotonicTicker())
Expand Down
Loading