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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
### Behavioral Changes

- Measure HTTP rate-limit backoff on a monotonic clock instead of the wall clock, so that a device time change no longer lifts or extends an active rate limit ([#6030](https://github.com/getsentry/sentry-java/pull/6030))
- Deprecate `DateUtils.getCurrentDateTime()` in favour of `options.getDateProvider().now()`, which is configurable and resolves finer than a millisecond ([#6043](https://github.com/getsentry/sentry-java/pull/6043))

### Internal

- Add internal `UptimeClock` and `ElapsedRealtimeClock` abstractions with `Deadline` and `Stopwatch` primitives ([#6028](https://github.com/getsentry/sentry-java/pull/6028))
- Add internal `Timestamp`, `Timing` and `EpochClock`, separating a serialized wall-clock instant from a monotonically measured duration ([#6045](https://github.com/getsentry/sentry-java/pull/6045))
- Deprecate `RateLimiter(ICurrentDateProvider, SentryOptions)` in favour of `RateLimiter(ElapsedRealtimeClock, RateLimiterConfig)` ([#6030](https://github.com/getsentry/sentry-java/pull/6030))
- Measure ANR detection thresholds on the internal `UptimeClock`, so the clock that excludes deep sleep is named by the type instead of chosen at each call site ([#6041](https://github.com/getsentry/sentry-java/pull/6041))
- Deprecate `ICurrentDateProvider.getCurrentTimeMillis()`, `CurrentDateProvider.getInstance()`, `AndroidCurrentDateProvider.getInstance()` and `AndroidDateUtils.getCurrentSentryDateTime()` in favour of `UptimeClock`, `ElapsedRealtimeClock` and `SentryDateProvider` ([#6043](https://github.com/getsentry/sentry-java/pull/6043))

### Fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,9 @@ private void finishTransaction(
}
}

// TODO [MAJOR]: replace AndroidDateUtils.getCurrentSentryDateTime() with
// options.getDateProvider().now()
@SuppressWarnings("deprecation")
@Override
public void onActivityPreCreated(
final @NotNull Activity activity, final @Nullable Bundle savedInstanceState) {
Expand Down Expand Up @@ -604,6 +607,9 @@ public void onActivityPostCreated(
}
}

// TODO [MAJOR]: replace AndroidDateUtils.getCurrentSentryDateTime() with
// options.getDateProvider().now()
@SuppressWarnings("deprecation")
@Override
public void onActivityPreStarted(final @NotNull Activity activity) {
final ActivityLifecycleSpanHelper helper = activitySpanHelpers.get(activity);
Expand Down Expand Up @@ -672,6 +678,9 @@ public void onActivityPostResumed(@NotNull Activity activity) {
// empty override, required to avoid a api-level breaking super.onActivityPostResumed() calls
}

// TODO [MAJOR]: replace AndroidDateUtils.getCurrentSentryDateTime() with
// options.getDateProvider().now()
@SuppressWarnings("deprecation")
@Override
public void onActivityPrePaused(@NotNull Activity activity) {
// only executed if API >= 29 otherwise it happens on onActivityPaused
Expand Down Expand Up @@ -1094,6 +1103,9 @@ private void onHeadlessAppStart() {
* Standalone-only: this is only registered as a listener when standalone app start tracing is
* enabled.
*/
// TODO [MAJOR]: replace AndroidDateUtils.getCurrentSentryDateTime() with
// options.getDateProvider().now()
@SuppressWarnings("deprecation")
private @Nullable AppStartExtension.ExtendedAppStart onExtendAppStartRequested() {
if (scopes == null
|| options == null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ public final class AndroidDateUtils {
* invocations.
*
* @return the UTC SentryDate
* @deprecated use {@code options.getDateProvider()}. This static holder cannot be configured or
* stubbed, which is why the note above already asked callers to prefer the options.
*/
@Deprecated
public static @NotNull SentryDate getCurrentSentryDateTime() {
return dateProvider.now();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,9 @@ private static void setupProfiler(
}
}

// TODO [MAJOR]: replace CurrentDateProvider (wall clock) with SentryDateProvider or
// ElapsedRealtimeClock
@SuppressWarnings("deprecation")
static void installDefaultIntegrations(
final @NotNull Context context,
final @NotNull SentryAndroidOptions options,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ public AndroidProfiler(
}

@SuppressLint("NewApi")
// TODO [MAJOR]: replace DateUtils.getCurrentDateTime() with options.getDateProvider().now()
@SuppressWarnings("deprecation")
public @Nullable ProfileStartData start() {
try (final @NotNull ISentryLifecycleToken ignored = lock.acquire()) {
// intervalUs is 0 only if there was a problem in the init
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ public AndroidTransactionProfiler(
() -> executorService);
}

// TODO [MAJOR]: replace DateUtils.getCurrentDateTime() with options.getDateProvider().now()
@SuppressWarnings("deprecation")
public AndroidTransactionProfiler(
final @NotNull Context context,
final @NotNull BuildInfoProvider buildInfoProvider,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ public class AnrV2Integration implements Integration, Closeable {
private final @NotNull ICurrentDateProvider dateProvider;
private @Nullable SentryAndroidOptions options;

// TODO [MAJOR]: replace CurrentDateProvider (wall clock) with SentryDateProvider; the epoch
// comparison it feeds must stay wall time
@SuppressWarnings("deprecation")
public AnrV2Integration(final @NotNull Context context) {
// using CurrentDateProvider instead of AndroidCurrentDateProvider as AppExitInfo uses
// System.currentTimeMillis
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public final class AppComponentsBreadcrumbsIntegration
private @Nullable IScopes scopes;
private @Nullable SentryAndroidOptions options;

// TODO [MAJOR]: replace AndroidCurrentDateProvider with UptimeClock
@SuppressWarnings("deprecation")
private final @NotNull Debouncer trimMemoryDebouncer =
new Debouncer(AndroidCurrentDateProvider.getInstance(), DEBOUNCE_WAIT_TIME_MS, 0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ final class ApplicationExitInfoHistoryDispatcher implements Runnable {
private final @NotNull ApplicationExitInfoPolicy policy;
private final long threshold;

// TODO [MAJOR]: replace CurrentDateProvider (wall clock) with SentryDateProvider; the epoch
// comparison it feeds must stay wall time
@SuppressWarnings("deprecation")
ApplicationExitInfoHistoryDispatcher(
final @NotNull Context context,
final @NotNull IScopes scopes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ final class LifecycleWatcher implements AppState.AppStateListener {

private final @NotNull ICurrentDateProvider currentDateProvider;

// TODO [MAJOR]: replace CurrentDateProvider (wall clock) with SentryDateProvider; the epoch
// comparison it feeds must stay wall time
@SuppressWarnings("deprecation")
LifecycleWatcher(
final @NotNull IScopes scopes,
final long sessionIntervalMillis,
Expand Down Expand Up @@ -60,6 +63,9 @@ public void onForeground() {
addAppBreadcrumb("foreground");
}

// TODO [MAJOR]: replace CurrentDateProvider (wall clock) with SentryDateProvider; the epoch
// comparison it feeds must stay wall time
@SuppressWarnings("deprecation")
private void startSession() {
cancelTask();

Expand Down Expand Up @@ -90,6 +96,9 @@ private void startSession() {

// App went to background and triggered this callback after 700ms
// as no new screen was shown
// TODO [MAJOR]: replace CurrentDateProvider (wall clock) with SentryDateProvider; the epoch
// comparison it feeds must stay wall time
@SuppressWarnings("deprecation")
@Override
public void onBackground() {
final long currentTimeMillis = currentDateProvider.getCurrentTimeMillis();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public final class ScreenshotEventProcessor implements EventProcessor {
private final boolean isReplayAvailable;
private final AtomicBoolean isReplayModuleAbsenceLogged = new AtomicBoolean(false);

// TODO [MAJOR]: replace AndroidCurrentDateProvider with UptimeClock
@SuppressWarnings("deprecation")
public ScreenshotEventProcessor(
final @NotNull SentryAndroidOptions options,
final @NotNull BuildInfoProvider buildInfoProvider,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,9 @@ final class SystemEventsBroadcastReceiver extends BroadcastReceiver {
private static final long DEBOUNCE_WAIT_TIME_MS = 60 * 1000;
private final @NotNull IScopes scopes;
private final @NotNull SentryAndroidOptions options;

// TODO [MAJOR]: replace AndroidCurrentDateProvider with UptimeClock
@SuppressWarnings("deprecation")
private final @NotNull Debouncer batteryChangedDebouncer =
new Debouncer(AndroidCurrentDateProvider.getInstance(), DEBOUNCE_WAIT_TIME_MS, 0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ public class TombstoneIntegration implements Integration, Closeable {
private final @NotNull ICurrentDateProvider dateProvider;
private @Nullable SentryAndroidOptions options;

// TODO [MAJOR]: replace CurrentDateProvider (wall clock) with SentryDateProvider; the epoch
// comparison it feeds must stay wall time
@SuppressWarnings("deprecation")
public TombstoneIntegration(final @NotNull Context context) {
// using CurrentDateProvider instead of AndroidCurrentDateProvider as AppExitInfo uses
// System.currentTimeMillis
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ public final class ViewHierarchyEventProcessor implements EventProcessor {
private static final long DEBOUNCE_WAIT_TIME_MS = 2000;
private static final int DEBOUNCE_MAX_EXECUTIONS = 3;

// TODO [MAJOR]: replace AndroidCurrentDateProvider with UptimeClock
@SuppressWarnings("deprecation")
public ViewHierarchyEventProcessor(final @NotNull SentryAndroidOptions options) {
this.options = Objects.requireNonNull(options, "SentryAndroidOptions is required");
this.debouncer =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public final class AndroidEnvelopeCache extends EnvelopeCache {

private final @NotNull ICurrentDateProvider currentDateProvider;

// TODO [MAJOR]: replace AndroidCurrentDateProvider with UptimeClock
@SuppressWarnings("deprecation")
public AndroidEnvelopeCache(final @NotNull SentryAndroidOptions options) {
this(options, AndroidCurrentDateProvider.getInstance());
}
Expand All @@ -63,6 +65,9 @@ public boolean storeEnvelope(@NotNull SentryEnvelope envelope, @NotNull Hint hin
return storeInternalAndroid(envelope, hint);
}

// TODO [MAJOR]: replace with UptimeClock; the reading must stay paired with
// AppStartMetrics.getStartUptimeMs()
@SuppressWarnings("deprecation")
private boolean storeInternalAndroid(@NotNull SentryEnvelope envelope, @NotNull Hint hint) {
final boolean didStore = super.storeEnvelope(envelope, hint);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,33 @@
import io.sentry.transport.ICurrentDateProvider;
import org.jetbrains.annotations.ApiStatus;

/**
* An uptime clock: {@link SystemClock#uptimeMillis()} excludes time the device spent in deep sleep,
* which the name does not say.
*
* <p>Superseded by {@link io.sentry.time.UptimeClock} where that is the intent, and {@link
* io.sentry.time.ElapsedRealtimeClock} where it is not.
*/
@ApiStatus.Internal
public final class AndroidCurrentDateProvider implements ICurrentDateProvider {

@SuppressWarnings("deprecation")
private static final ICurrentDateProvider instance = new AndroidCurrentDateProvider();

/**
* @deprecated use {@link io.sentry.time.UptimeClock} where deep sleep must be excluded, {@link
* io.sentry.time.ElapsedRealtimeClock} where it must not.
*/
@Deprecated
@SuppressWarnings("deprecation")
public static ICurrentDateProvider getInstance() {
return instance;
}

private AndroidCurrentDateProvider() {}

@Override
@SuppressWarnings("deprecation")
public long getCurrentTimeMillis() {
return SystemClock.uptimeMillis();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public Debouncer(
* @return true if the execution should be debounced due to maxExecutions executions being made
* within waitTimeMs, otherwise false.
*/
// TODO [MAJOR]: replace AndroidCurrentDateProvider with UptimeClock
@SuppressWarnings("deprecation")
public boolean checkForDebounce() {
final long now = timeProvider.getCurrentTimeMillis();
if (lastExecutionTime.get() == 0 || (lastExecutionTime.get() + waitTimeMs) <= now) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ public void createAndStopOnStartSpan(final @Nullable ISpan parentSpan) {
return onStartStartTimestamp;
}

// TODO [MAJOR]: replace AndroidDateUtils.getCurrentSentryDateTime() with
// options.getDateProvider().now()
@SuppressWarnings("deprecation")
public void saveSpanToAppStartMetrics() {
if (onCreateSpan == null || onStartSpan == null) {
return;
Expand Down
6 changes: 4 additions & 2 deletions sentry/src/main/java/io/sentry/Breadcrumb.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ public Breadcrumb(final long timestamp) {
* @param options - the sentry options
* @return the breadcrumb
*/
@SuppressWarnings("unchecked")
// TODO [MAJOR]: replace DateUtils.getCurrentDateTime() with options.getDateProvider().now()
@SuppressWarnings({"unchecked", "deprecation"})
public static Breadcrumb fromMap(
@NotNull Map<String, Object> map, @NotNull SentryOptions options) {

Expand Down Expand Up @@ -882,7 +883,8 @@ public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger
}

public static final class Deserializer implements JsonDeserializer<Breadcrumb> {
@SuppressWarnings("unchecked")
// TODO [MAJOR]: replace DateUtils.getCurrentDateTime() with options.getDateProvider().now()
@SuppressWarnings({"unchecked", "deprecation"})
@Override
public @NotNull Breadcrumb deserialize(@NotNull ObjectReader reader, @NotNull ILogger logger)
throws Exception {
Expand Down
6 changes: 5 additions & 1 deletion sentry/src/main/java/io/sentry/DateUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@ private DateUtils() {}
* Get the current Date (UTC)
*
* @return the UTC Date
* @deprecated use {@code options.getDateProvider().now()}, which is configurable and resolves
* finer than a millisecond.
*/
@SuppressWarnings("JavaUtilDate")
@Deprecated
// not @InlineMe: the replacement is options.getDateProvider().now(), not this method's body
@SuppressWarnings({"JavaUtilDate", "InlineMeSuggester"})
public static @NotNull Date getCurrentDateTime() {
return new Date();
}
Expand Down
2 changes: 2 additions & 0 deletions sentry/src/main/java/io/sentry/ProfilingTraceData.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ private ProfilingTraceData() {
this(new File("dummy"), NoOpTransaction.getInstance());
}

// TODO [MAJOR]: replace DateUtils.getCurrentDateTime() with options.getDateProvider().now()
@SuppressWarnings("deprecation")
public ProfilingTraceData(
final @NotNull File traceFile, final @NotNull ITransaction transaction) {
this(
Expand Down
2 changes: 2 additions & 0 deletions sentry/src/main/java/io/sentry/SentryEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ public SentryEvent(final @Nullable Throwable throwable) {
this.throwable = throwable;
}

// TODO [MAJOR]: replace DateUtils.getCurrentDateTime() with options.getDateProvider().now()
@SuppressWarnings("deprecation")
public SentryEvent() {
this(new SentryId(), DateUtils.getCurrentDateTime());
}
Expand Down
2 changes: 2 additions & 0 deletions sentry/src/main/java/io/sentry/SentryReplayEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public static final class Deserializer implements JsonDeserializer<ReplayType> {
private @Nullable List<String> segmentNames;
private @Nullable Map<String, Object> unknown;

// TODO [MAJOR]: replace DateUtils.getCurrentDateTime() with options.getDateProvider().now()
@SuppressWarnings("deprecation")
public SentryReplayEvent() {
super();
this.replayId = new SentryId();
Expand Down
10 changes: 10 additions & 0 deletions sentry/src/main/java/io/sentry/Session.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ public Session(
this.abnormalMechanism = abnormalMechanism;
}

// TODO [MAJOR]: replace DateUtils.getCurrentDateTime() with options.getDateProvider().now()
@SuppressWarnings("deprecation")
public Session(
@Nullable String distinctId,
final @Nullable User user,
Expand Down Expand Up @@ -221,6 +223,8 @@ public boolean hasNonTerminatingUnhandledError() {
*
* @return whether the session was updated, i.e. false if it had already reached a terminal state
*/
// TODO [MAJOR]: replace DateUtils.getCurrentDateTime() with options.getDateProvider().now()
@SuppressWarnings("deprecation")
@ApiStatus.Internal
public boolean recordNonTerminatingUnhandledError() {
try (final @NotNull ISentryLifecycleToken ignored = sessionLock.acquire()) {
Expand All @@ -242,6 +246,8 @@ public boolean recordNonTerminatingUnhandledError() {
}

/** Ends a session and update its values */
// TODO [MAJOR]: replace DateUtils.getCurrentDateTime() with options.getDateProvider().now()
@SuppressWarnings("deprecation")
public void end() {
end(DateUtils.getCurrentDateTime());
}
Expand All @@ -251,6 +257,8 @@ public void end() {
*
* @param timestamp the timestamp or null
*/
// TODO [MAJOR]: replace DateUtils.getCurrentDateTime() with options.getDateProvider().now()
@SuppressWarnings("deprecation")
public void end(final @Nullable Date timestamp) {
try (final @NotNull ISentryLifecycleToken ignored = sessionLock.acquire()) {
init = null;
Expand Down Expand Up @@ -301,6 +309,8 @@ public boolean update(
* @param abnormalMechanism the mechanism which caused the session to be abnormal
* @return if the session has been updated
*/
// TODO [MAJOR]: replace DateUtils.getCurrentDateTime() with options.getDateProvider().now()
@SuppressWarnings("deprecation")
public boolean update(
final @Nullable State status,
final @Nullable String userAgent,
Expand Down
2 changes: 2 additions & 0 deletions sentry/src/main/java/io/sentry/cache/EnvelopeCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@ private void tryEndPreviousSession(final @NotNull Hint hint) {
}
}

// TODO [MAJOR]: replace DateUtils.getCurrentDateTime() with options.getDateProvider().now()
@SuppressWarnings("deprecation")
private void writeCrashMarkerFile() {
final File crashMarkerFile = new File(options.getCacheDirPath(), CRASH_MARKER_FILE);
try (final OutputStream outputStream = new FileOutputStream(crashMarkerFile)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ private long itemCountFromHeader(final @NotNull SentryEnvelopeItem envelopeItem)
return itemCount != null ? itemCount : 1L;
}

// TODO [MAJOR]: replace DateUtils.getCurrentDateTime() with options.getDateProvider().now()
@SuppressWarnings("deprecation")
@Nullable
ClientReport resetCountsAndGenerateClientReport() {
final Date currentDate = DateUtils.getCurrentDateTime();
Expand Down
Loading
Loading