Skip to content

Commit

Permalink
Merge branch 'main' into adinauer-patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
buenaflor committed May 10, 2024
2 parents 7cf6026 + 9e57f46 commit af2cd16
Show file tree
Hide file tree
Showing 21 changed files with 445 additions and 70 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
# Changelog

## Unreleased
## 7.9.0

### Features

- Add start_type to app context ([#3379](https://github.com/getsentry/sentry-java/pull/3379))
- Add ttid/ttfd contribution flags ([#3386](https://github.com/getsentry/sentry-java/pull/3386))

### Fixes

- (Internal) Metrics code cleanup ([#3403](https://github.com/getsentry/sentry-java/pull/3403))
- Fix Frame measurements in app start transactions ([#3382](https://github.com/getsentry/sentry-java/pull/3382))
- Fix timing metric value different from span duration ([#3368](https://github.com/getsentry/sentry-java/pull/3368))
- Do not always write startup crash marker ([#3409](https://github.com/getsentry/sentry-java/pull/3409))
- This may have been causing the SDK init logic to block the main thread

## 7.8.0

Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2019 Sentry
Copyright (c) 2019-2024 Sentry
Copyright (c) 2015 Salomon BRYS for Android ANRWatchDog

Permission is hereby granted, free of charge, to any person obtaining a copy
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ android.useAndroidX=true
android.defaults.buildfeatures.buildconfig=true

# Release information
versionName=7.8.0
versionName=7.9.0

# Override the SDK name on native crashes on Android
sentryAndroidSdkName=sentry.native.android
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ public SentryEvent process(@NotNull SentryEvent event, @NotNull Hint hint) {
appContext.setStartType(appStartType);
}

setContributingFlags(transaction);

final SentryId eventId = transaction.getEventId();
final SpanContext spanContext = transaction.getContexts().getTrace();

Expand All @@ -135,6 +137,71 @@ public SentryEvent process(@NotNull SentryEvent event, @NotNull Hint hint) {
return transaction;
}

private void setContributingFlags(SentryTransaction transaction) {

@Nullable SentrySpan ttidSpan = null;
@Nullable SentrySpan ttfdSpan = null;
for (final @NotNull SentrySpan span : transaction.getSpans()) {
if (ActivityLifecycleIntegration.TTID_OP.equals(span.getOp())) {
ttidSpan = span;
} else if (ActivityLifecycleIntegration.TTFD_OP.equals(span.getOp())) {
ttfdSpan = span;
}
// once both are found we can early exit
if (ttidSpan != null && ttfdSpan != null) {
break;
}
}

if (ttidSpan == null && ttfdSpan == null) {
return;
}

for (final @NotNull SentrySpan span : transaction.getSpans()) {
// as ttid and ttfd spans are artificially created, we don't want to set the flags on them
if (span == ttidSpan || span == ttfdSpan) {
continue;
}

// let's assume main thread, unless it's set differently
boolean spanOnMainThread = true;
final @Nullable Map<String, Object> spanData = span.getData();
if (spanData != null) {
final @Nullable Object threadName = spanData.get(SpanDataConvention.THREAD_NAME);
spanOnMainThread = threadName == null || "main".equals(threadName);
}

// for ttid, only main thread spans are relevant
final boolean withinTtid =
(ttidSpan != null)
&& isTimestampWithinSpan(span.getStartTimestamp(), ttidSpan)
&& spanOnMainThread;

final boolean withinTtfd =
(ttfdSpan != null) && isTimestampWithinSpan(span.getStartTimestamp(), ttfdSpan);

if (withinTtid || withinTtfd) {
@Nullable Map<String, Object> data = span.getData();
if (data == null) {
data = new ConcurrentHashMap<>();
span.setData(data);
}
if (withinTtid) {
data.put(SpanDataConvention.CONTRIBUTES_TTID, true);
}
if (withinTtfd) {
data.put(SpanDataConvention.CONTRIBUTES_TTFD, true);
}
}
}
}

private static boolean isTimestampWithinSpan(
final double timestamp, final @NotNull SentrySpan target) {
return timestamp >= target.getStartTimestamp()
&& (target.getTimestamp() == null || timestamp <= target.getTimestamp());
}

private boolean hasAppStartSpan(final @NotNull SentryTransaction txn) {
final @NotNull List<SentrySpan> spans = txn.getSpans();
for (final @NotNull SentrySpan span : spans) {
Expand Down Expand Up @@ -253,6 +320,9 @@ private static SentrySpan timeSpanToSentrySpan(
defaultSpanData.put(SpanDataConvention.THREAD_ID, Looper.getMainLooper().getThread().getId());
defaultSpanData.put(SpanDataConvention.THREAD_NAME, "main");

defaultSpanData.put(SpanDataConvention.CONTRIBUTES_TTID, true);
defaultSpanData.put(SpanDataConvention.CONTRIBUTES_TTFD, true);

return new SentrySpan(
span.getStartTimestampSecs(),
span.getProjectedStopTimestampSecs(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package io.sentry.android.core;

import io.sentry.DateUtils;
import io.sentry.IPerformanceContinuousCollector;
import io.sentry.ISpan;
import io.sentry.ITransaction;
import io.sentry.NoOpSpan;
import io.sentry.NoOpTransaction;
import io.sentry.SentryDate;
import io.sentry.SentryLongDate;
import io.sentry.SentryNanotimeDate;
import io.sentry.SentryTracer;
import io.sentry.SpanDataConvention;
Expand Down Expand Up @@ -143,8 +145,6 @@ private void captureFrameMetrics(@NotNull final ISpan span) {
if (spanFinishDate == null) {
return;
}
// Note: The comparison between two values obtained by realNanos() works only if both are the
// same kind of dates (both are SentryNanotimeDate or both SentryLongDate)
final long spanEndNanos = realNanos(spanFinishDate);

final @NotNull SentryFrameMetrics frameMetrics = new SentryFrameMetrics();
Expand Down Expand Up @@ -308,7 +308,16 @@ private static int addPendingFrameDelay(
* @return a timestamp in nano precision
*/
private static long realNanos(final @NotNull SentryDate date) {
return date.diff(UNIX_START_DATE);
// SentryNanotimeDate nanotime is based on System.nanotime(), like UNIX_START_DATE
if (date instanceof SentryNanotimeDate) {
return date.diff(UNIX_START_DATE);
}

// SentryLongDate nanotime is based on current date converted to nanoseconds, which is a
// different order than frames based System.nanotime(). So we have to convert the nanotime of
// the SentryLongDate to a System.nanotime() compatible one.
return date.diff(new SentryLongDate(DateUtils.millisToNanos(System.currentTimeMillis())))
+ System.nanoTime();
}

private static class Frame implements Comparable<Frame> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public void store(@NotNull SentryEnvelope envelope, @NotNull Hint hint) {
if (HintUtils.hasType(hint, UncaughtExceptionHandlerIntegration.UncaughtExceptionHint.class)
&& sdkInitTimeSpan.hasStarted()) {
long timeSinceSdkInit =
currentDateProvider.getCurrentTimeMillis() - sdkInitTimeSpan.getStartTimestampMs();
currentDateProvider.getCurrentTimeMillis() - sdkInitTimeSpan.getStartUptimeMs();
if (timeSinceSdkInit <= options.getStartupCrashDurationThresholdMillis()) {
options
.getLogger()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import io.sentry.DateUtils;
import io.sentry.SentryDate;
import io.sentry.SentryLongDate;
import io.sentry.SentryNanotimeDate;
import java.util.concurrent.TimeUnit;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -95,8 +94,7 @@ public long getStartTimestampMs() {
*/
public @Nullable SentryDate getStartTimestamp() {
if (hasStarted()) {
return new SentryNanotimeDate(
DateUtils.nanosToDate(DateUtils.millisToNanos(getStartTimestampMs())), startSystemNanos);
return new SentryLongDate(DateUtils.millisToNanos(getStartTimestampMs()));
}
return null;
}
Expand Down
Loading

0 comments on commit af2cd16

Please sign in to comment.