Skip to content

Commit

Permalink
Merge main into 8.x.x with 7.18.0 being latest release (#3920)
Browse files Browse the repository at this point in the history
* Merge main into 8.x.x with 7.18.0 being latest release

* fix SessionCaptureStrategy by copying over from main

* deletion from main was missing here

* mention main merge in changelog
  • Loading branch information
adinauer authored Nov 22, 2024
1 parent e1b0b23 commit f4948b2
Show file tree
Hide file tree
Showing 32 changed files with 1,988 additions and 75 deletions.
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

- Send `otel.kind` to Sentry ([#3907](https://github.com/getsentry/sentry-java/pull/3907))
- Allow passing `environment` to `CheckinUtils.withCheckIn` ([3889](https://github.com/getsentry/sentry-java/pull/3889))
- Changes up to `7.18.0` have been merged and are now included as well

### Fixes

Expand Down Expand Up @@ -59,6 +60,7 @@
- Uses faster Random implementation to generate UUIDs
- Android 15: Add support for 16KB page sizes ([#3851](https://github.com/getsentry/sentry-java/pull/3851))
- See https://developer.android.com/guide/practices/page-sizes for more details
- Changes up to `7.17.0` have been merged and are now included as well

### Fixes

Expand Down Expand Up @@ -326,6 +328,29 @@ You may also use `LifecycleHelper.close(token)`, e.g. in case you need to pass t

- Report exceptions returned by Throwable.getSuppressed() to Sentry as exception groups ([#3396] https://github.com/getsentry/sentry-java/pull/3396)

## 7.18.0

### Features

- Android 15: Add support for 16KB page sizes ([#3620](https://github.com/getsentry/sentry-java/pull/3620))
- See https://developer.android.com/guide/practices/page-sizes for more details
- Session Replay: Add `beforeSendReplay` callback ([#3855](https://github.com/getsentry/sentry-java/pull/3855))
- Session Replay: Add support for masking/unmasking view containers ([#3881](https://github.com/getsentry/sentry-java/pull/3881))

### Fixes

- Avoid collecting normal frames ([#3782](https://github.com/getsentry/sentry-java/pull/3782))
- Ensure android initialization process continues even if options configuration block throws an exception ([#3887](https://github.com/getsentry/sentry-java/pull/3887))
- Do not report parsing ANR error when there are no threads ([#3888](https://github.com/getsentry/sentry-java/pull/3888))
- This should significantly reduce the number of events with message "Sentry Android SDK failed to parse system thread dump..." reported
- Session Replay: Disable replay in session mode when rate limit is active ([#3854](https://github.com/getsentry/sentry-java/pull/3854))

### Dependencies

- Bump Native SDK from v0.7.2 to v0.7.8 ([#3620](https://github.com/getsentry/sentry-java/pull/3620))
- [changelog](https://github.com/getsentry/sentry-native/blob/master/CHANGELOG.md#078)
- [diff](https://github.com/getsentry/sentry-native/compare/0.7.2...0.7.8)

## 7.17.0

### Features
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ spotless {
target("**/*.java")
removeUnusedImports()
googleJavaFormat()
targetExclude("**/generated/**", "**/vendor/**")
targetExclude("**/generated/**", "**/vendor/**", "**/sentry-native/**")
}
kotlin {
target("**/*.kt")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,11 @@ private void reportAsSentryEvent(
final ThreadDumpParser threadDumpParser = new ThreadDumpParser(options, isBackground);
final List<SentryThread> threads = threadDumpParser.parse(lines);
if (threads.isEmpty()) {
// if the list is empty this means our regex matching is garbage and this is still error
return new ParseResult(ParseResult.Type.ERROR, dump);
// if the list is empty this means the system failed to capture a proper thread dump of
// the android threads, and only contains kernel-level threads and statuses, those ANRs
// are not actionable and neither they are reported by Google Play Console, so we just
// fall back to not reporting them
return new ParseResult(ParseResult.Type.NO_DUMP);
}
return new ParseResult(ParseResult.Type.DUMP, dump, threads);
} catch (Throwable e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,17 @@ public static void init(
isTimberAvailable,
isReplayAvailable);

configuration.configure(options);
try {
configuration.configure(options);
} catch (Throwable t) {
// let it slip, but log it
options
.getLogger()
.log(
SentryLevel.ERROR,
"Error in the 'OptionsConfiguration.configure' callback.",
t);
}

// if SentryPerformanceProvider was disabled or removed,
// we set the app start / sdk init time here instead
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
@ApiStatus.Internal
final class SentryFrameMetrics {

private int normalFrameCount;
private int slowFrameCount;
private int frozenFrameCount;

Expand All @@ -18,15 +17,11 @@ final class SentryFrameMetrics {
public SentryFrameMetrics() {}

public SentryFrameMetrics(
final int normalFrameCount,
final int slowFrameCount,
final long slowFrameDelayNanos,
final int frozenFrameCount,
final long frozenFrameDelayNanos,
final long totalDurationNanos) {

this.normalFrameCount = normalFrameCount;

this.slowFrameCount = slowFrameCount;
this.slowFrameDelayNanos = slowFrameDelayNanos;

Expand All @@ -47,15 +42,9 @@ public void addFrame(
} else if (isSlow) {
slowFrameDelayNanos += delayNanos;
slowFrameCount += 1;
} else {
normalFrameCount += 1;
}
}

public int getNormalFrameCount() {
return normalFrameCount;
}

public int getSlowFrameCount() {
return slowFrameCount;
}
Expand All @@ -72,17 +61,16 @@ public long getFrozenFrameDelayNanos() {
return frozenFrameDelayNanos;
}

public int getTotalFrameCount() {
return normalFrameCount + slowFrameCount + frozenFrameCount;
/** Returns the sum of the slow and frozen frames. */
public int getSlowFrozenFrameCount() {
return slowFrameCount + frozenFrameCount;
}

public long getTotalDurationNanos() {
return totalDurationNanos;
}

public void clear() {
normalFrameCount = 0;

slowFrameCount = 0;
slowFrameDelayNanos = 0;

Expand All @@ -95,7 +83,6 @@ public void clear() {
@NotNull
public SentryFrameMetrics duplicate() {
return new SentryFrameMetrics(
normalFrameCount,
slowFrameCount,
slowFrameDelayNanos,
frozenFrameCount,
Expand All @@ -110,7 +97,6 @@ public SentryFrameMetrics duplicate() {
@NotNull
public SentryFrameMetrics diffTo(final @NotNull SentryFrameMetrics other) {
return new SentryFrameMetrics(
normalFrameCount - other.normalFrameCount,
slowFrameCount - other.slowFrameCount,
slowFrameDelayNanos - other.slowFrameDelayNanos,
frozenFrameCount - other.frozenFrameCount,
Expand All @@ -123,8 +109,7 @@ public SentryFrameMetrics diffTo(final @NotNull SentryFrameMetrics other) {
* to 0
*/
public boolean containsValidData() {
return normalFrameCount >= 0
&& slowFrameCount >= 0
return slowFrameCount >= 0
&& slowFrameDelayNanos >= 0
&& frozenFrameCount >= 0
&& frozenFrameDelayNanos >= 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ private void captureFrameMetrics(@NotNull final ISpan span) {
}
}

int totalFrameCount = frameMetrics.getTotalFrameCount();
int totalFrameCount = frameMetrics.getSlowFrozenFrameCount();

final long nextScheduledFrameNanos = frameMetricsCollector.getLastKnownFrameStartTimeNanos();
// nextScheduledFrameNanos might be -1 if no frames have been scheduled for drawing yet
Expand Down Expand Up @@ -258,15 +258,17 @@ public void onFrameMetricCollected(
(long) ((double) ONE_SECOND_NANOS / (double) refreshRate);
lastKnownFrameDurationNanos = expectedFrameDurationNanos;

frames.add(
new Frame(
frameStartNanos,
frameEndNanos,
durationNanos,
delayNanos,
isSlow,
isFrozen,
expectedFrameDurationNanos));
if (isSlow || isFrozen) {
frames.add(
new Frame(
frameStartNanos,
frameEndNanos,
durationNanos,
delayNanos,
isSlow,
isFrozen,
expectedFrameDurationNanos));
}
}

private static int interpolateFrameCount(
Expand All @@ -281,7 +283,7 @@ private static int interpolateFrameCount(
final long frameMetricsDurationNanos = frameMetrics.getTotalDurationNanos();
final long nonRenderedDuration = spanDurationNanos - frameMetricsDurationNanos;
if (nonRenderedDuration > 0) {
return (int) (nonRenderedDuration / frameDurationNanos);
return (int) Math.ceil((double) nonRenderedDuration / frameDurationNanos);
}
return 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ class AnrV2IntegrationTest {
reason: Int? = ApplicationExitInfo.REASON_ANR,
timestamp: Long? = null,
importance: Int? = null,
addTrace: Boolean = true
addTrace: Boolean = true,
addBadTrace: Boolean = false
) {
val builder = ApplicationExitInfoBuilder.newBuilder()
if (reason != null) {
Expand All @@ -117,8 +118,36 @@ class AnrV2IntegrationTest {
if (!addTrace) {
return
}
whenever(mock.traceInputStream).thenReturn(
"""
if (addBadTrace) {
whenever(mock.traceInputStream).thenReturn(
"""
Subject: Input dispatching timed out (7985007 com.example.app/com.example.app.ui.MainActivity (server) is not responding. Waited 5000ms for FocusEvent(hasFocus=false))
Here are no Binder-related exception messages available.
Pid(12233) have D state thread(tid:12236 name:Signal Catcher)
RssHwmKb: 823716
RssKb: 548348
RssAnonKb: 382156
RssShmemKb: 13304
VmSwapKb: 82484
--- CriticalEventLog ---
capacity: 20
timestamp_ms: 1731507490032
window_ms: 300000
----- dumping pid: 12233 at 313446151
libdebuggerd_client: unexpected registration response: 0
----- Waiting Channels: pid 12233 at 2024-11-13 19:48:09.980104540+0530 -----
Cmd line: com.example.app:mainProcess
""".trimIndent().byteInputStream()
)
} else {
whenever(mock.traceInputStream).thenReturn(
"""
"main" prio=5 tid=1 Blocked
| group="main" sCount=1 ucsCount=0 flags=1 obj=0x72a985e0 self=0xb400007cabc57380
| sysTid=28941 nice=-10 cgrp=top-app sched=0/0 handle=0x7deceb74f8
Expand Down Expand Up @@ -147,8 +176,9 @@ class AnrV2IntegrationTest {
native: #02 pc 00000000000b63b0 /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+208) (BuildId: 01331f74b0bb2cb958bdc15282b8ec7b)
native: #03 pc 00000000000530b8 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) (BuildId: 01331f74b0bb2cb958bdc15282b8ec7b)
(no managed stack frames)
""".trimIndent().byteInputStream()
)
""".trimIndent().byteInputStream()
)
}
}
shadowActivityManager.addApplicationExitInfo(exitInfo)
}
Expand Down Expand Up @@ -551,4 +581,14 @@ class AnrV2IntegrationTest {

verify(fixture.scopes, never()).captureEvent(any(), anyOrNull<Hint>())
}

@Test
fun `when traceInputStream has bad data, does not report ANR`() {
val integration = fixture.getSut(tmpDir, lastReportedAnrTimestamp = oldTimestamp)
fixture.addAppExitInfo(timestamp = newTimestamp, addBadTrace = true)

integration.register(fixture.scopes, fixture.options)

verify(fixture.scopes, never()).captureEvent(any(), anyOrNull<Hint>())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,19 @@ class SentryAndroidTest {
assertEquals(99, AppStartMetrics.getInstance().appStartTimeSpan.startUptimeMs)
}

@Test
fun `if the config options block throws still intializes android event processors`() {
lateinit var optionsRef: SentryOptions
fixture.initSut(context = mock<Application>()) { options ->
optionsRef = options
options.dsn = "https://key@sentry.io/123"
throw RuntimeException("Boom!")
}

assertTrue(optionsRef.eventProcessors.any { it is DefaultAndroidEventProcessor })
assertTrue(optionsRef.eventProcessors.any { it is AnrV2EventProcessor })
}

private fun prefillScopeCache(cacheDir: String) {
val scopeDir = File(cacheDir, SCOPE_CACHE).also { it.mkdirs() }
File(scopeDir, BREADCRUMBS_FILENAME).writeText(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,6 @@ import kotlin.test.assertFalse
import kotlin.test.assertTrue

class SentryFrameMetricsTest {
@Test
fun addFastFrame() {
val frameMetrics = SentryFrameMetrics()
frameMetrics.addFrame(10, 0, false, false)
assertEquals(1, frameMetrics.normalFrameCount)

frameMetrics.addFrame(10, 0, false, false)
assertEquals(2, frameMetrics.normalFrameCount)
}

@Test
fun addSlowFrame() {
Expand Down Expand Up @@ -43,10 +34,12 @@ class SentryFrameMetricsTest {
@Test
fun totalFrameCount() {
val frameMetrics = SentryFrameMetrics()
// Normal frames are ignored
frameMetrics.addFrame(10, 0, false, false)
// Slow and frozen frames are considered
frameMetrics.addFrame(116, 100, true, false)
frameMetrics.addFrame(1016, 1000, true, true)
assertEquals(3, frameMetrics.totalFrameCount)
assertEquals(2, frameMetrics.slowFrozenFrameCount)
}

@Test
Expand All @@ -57,12 +50,11 @@ class SentryFrameMetricsTest {
frameMetrics.addFrame(1016, 1000, true, true)

val dup = frameMetrics.duplicate()
assertEquals(1, dup.normalFrameCount)
assertEquals(1, dup.slowFrameCount)
assertEquals(100, dup.slowFrameDelayNanos)
assertEquals(1, dup.frozenFrameCount)
assertEquals(1000, dup.frozenFrameDelayNanos)
assertEquals(3, dup.totalFrameCount)
assertEquals(2, dup.slowFrozenFrameCount)
}

@Test
Expand All @@ -89,7 +81,7 @@ class SentryFrameMetricsTest {
assertEquals(1, diff.frozenFrameCount)
assertEquals(1000, diff.frozenFrameDelayNanos)

assertEquals(2, diff.totalFrameCount)
assertEquals(2, diff.slowFrozenFrameCount)
}

@Test
Expand All @@ -102,12 +94,11 @@ class SentryFrameMetricsTest {

frameMetrics.clear()

assertEquals(0, frameMetrics.normalFrameCount)
assertEquals(0, frameMetrics.slowFrameCount)
assertEquals(0, frameMetrics.slowFrameDelayNanos)
assertEquals(0, frameMetrics.frozenFrameCount)
assertEquals(0, frameMetrics.frozenFrameDelayNanos)
assertEquals(0, frameMetrics.totalFrameCount)
assertEquals(0, frameMetrics.slowFrozenFrameCount)
}

@Test
Expand Down
Loading

0 comments on commit f4948b2

Please sign in to comment.