Skip to content

Commit

Permalink
Merge branch 'main' into chore/craft-release-registry
Browse files Browse the repository at this point in the history
  • Loading branch information
bruno-garcia authored Feb 17, 2021
2 parents 79424e2 + 462be01 commit 82eedc3
Show file tree
Hide file tree
Showing 36 changed files with 384 additions and 139 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
# vNext

* Fix: Remove experimental annotation for Attachment #1257
* Fix: Mark stacktrace as snapshot if captured at arbitrary moment #1231
* Enchancement: Improve EventProcessor nullability annotations (#1229).
* Bump: sentry-native to 0.4.7
* Enchancement: Add ability to flush events synchronously.
* Fix: Disable Gson HTML escaping
* Enchancement: Support @SentrySpan and @SentryTransaction on classes and interfaces. (#1243)
* Enchancement: Do not serialize empty collections and maps (#1245)
* Ref: Simplify RestTemplate instrumentation (#1246)
* Ref: Prefix sdk.package names with io.sentry (#1249)
* Enchancement: Integration interface better compatibility with Kotlin null-safety

Breaking Changes:
* Enchancement: SentryExceptionResolver should not send handled errors by default (#1248).


# 4.1.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,6 @@ public interface ANRListener {
*
* @param error The error describing the ANR.
*/
void onAppNotResponding(ApplicationNotResponding error);
void onAppNotResponding(@NotNull ApplicationNotResponding error);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ void reportANR(
final @NotNull ApplicationNotResponding error) {
logger.log(SentryLevel.INFO, "ANR triggered with message: %s", error.getMessage());

Mechanism mechanism = new Mechanism();
final Mechanism mechanism = new Mechanism();
mechanism.setType("ANR");
ExceptionMechanismException throwable =
new ExceptionMechanismException(mechanism, error, error.getThread());
final ExceptionMechanismException throwable =
new ExceptionMechanismException(mechanism, error, error.getThread(), true);

hub.captureException(throwable);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import io.sentry.util.Objects;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* Error thrown by ANRWatchDog when an ANR is detected. Contains the stack trace of the frozen UI
Expand All @@ -16,15 +17,15 @@
final class ApplicationNotResponding extends RuntimeException {
private static final long serialVersionUID = 252541144579117016L;

private final Thread thread;
private final @NotNull Thread thread;

ApplicationNotResponding(@NotNull String message, @NotNull Thread thread) {
ApplicationNotResponding(final @Nullable String message, final @NotNull Thread thread) {
super(message);
this.thread = Objects.requireNonNull(thread, "Thread must be provided.");
setStackTrace(this.thread.getStackTrace());
}

public Thread getThread() {
public @NotNull Thread getThread() {
return thread;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,33 @@ public DefaultAndroidEventProcessor(
if (event.getContexts().getDevice() == null) {
event.getContexts().setDevice(getDevice());
}
if (event.getContexts().getOperatingSystem() == null) {
event.getContexts().setOperatingSystem(getOperatingSystem());
}

mergeOS(event);

setSideLoadedInfo(event);

return event;
}

private void mergeOS(final @NotNull SentryEvent event) {
final OperatingSystem currentOS = event.getContexts().getOperatingSystem();
final OperatingSystem androidOS = getOperatingSystem();

// make Android OS the main OS using the 'os' key
event.getContexts().setOperatingSystem(androidOS);

if (currentOS != null) {
// add additional OS which was already part of the SentryEvent (eg Linux read from NDK)
String osNameKey = currentOS.getName();
if (osNameKey != null && !osNameKey.isEmpty()) {
osNameKey = "os_" + osNameKey.trim().toLowerCase(Locale.ROOT);
} else {
osNameKey = "os_1";
}
event.getContexts().put(osNameKey, currentOS);
}
}

// Data to be applied to events that was created in the running process
private void processNonCachedEvent(final @NotNull SentryEvent event) {
App app = event.getContexts().getApp();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package io.sentry.android.core;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;

@TestOnly
interface IHandler {
void post(Runnable runnable);
void post(@NotNull Runnable runnable);

@NotNull
Thread getThread();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,26 @@

import android.os.Handler;
import android.os.Looper;
import org.jetbrains.annotations.NotNull;

final class MainLooperHandler implements IHandler {
private final Handler handler;
private final @NotNull Handler handler;

MainLooperHandler() {
handler = new Handler(Looper.getMainLooper());
this(Looper.getMainLooper());
}

MainLooperHandler(final @NotNull Looper looper) {
handler = new Handler(looper);
}

@Override
public void post(Runnable runnable) {
public void post(final @NotNull Runnable runnable) {
handler.post(runnable);
}

@Override
public Thread getThread() {
public @NotNull Thread getThread() {
return handler.getLooper().getThread();
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package io.sentry.android.core

import android.content.Context
import com.nhaarman.mockitokotlin2.any
import com.nhaarman.mockitokotlin2.check
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.verify
import io.sentry.IHub
import io.sentry.exception.ExceptionMechanismException
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertNotNull
Expand All @@ -12,49 +15,80 @@ import kotlin.test.assertTrue

class AnrIntegrationTest {

private val integration = AnrIntegration(mock())
private class Fixture {
val context = mock<Context>()
val hub = mock<IHub>()
val options = SentryAndroidOptions()

fun getSut(): AnrIntegration {
return AnrIntegration(context)
}
}

private val fixture = Fixture()

@BeforeTest
fun `before each test`() {
val sut = fixture.getSut()
// watch dog is static and has shared state
integration.close()
sut.close()
}

@Test
fun `When ANR is enabled, ANR watch dog should be started`() {
val options = SentryAndroidOptions()
val hub = mock<IHub>()
integration.register(hub, options)
assertNotNull(integration.anrWatchDog)
assertTrue((integration.anrWatchDog as ANRWatchDog).isAlive)
val sut = fixture.getSut()

sut.register(fixture.hub, fixture.options)

assertNotNull(sut.anrWatchDog)
assertTrue((sut.anrWatchDog as ANRWatchDog).isAlive)
}

@Test
fun `When ANR is disabled, ANR should not be started`() {
val options = SentryAndroidOptions()
options.isAnrEnabled = false
val hub = mock<IHub>()
val integration = AnrIntegration(mock())
integration.register(hub, options)
assertNull(integration.anrWatchDog)
val sut = fixture.getSut()
fixture.options.isAnrEnabled = false

sut.register(fixture.hub, fixture.options)

assertNull(sut.anrWatchDog)
}

@Test
fun `When ANR watch dog is triggered, it should capture exception`() {
val hub = mock<IHub>()
val integration = AnrIntegration(mock())
integration.reportANR(hub, mock(), mock())
verify(hub).captureException(any())
val sut = fixture.getSut()

sut.reportANR(fixture.hub, mock(), getApplicationNotResponding())

verify(fixture.hub).captureException(any())
}

@Test
fun `When ANR integration is closed, watch dog should stop`() {
val options = SentryAndroidOptions()
val hub = mock<IHub>()
val integration = AnrIntegration(mock())
integration.register(hub, options)
assertNotNull(integration.anrWatchDog)
integration.close()
assertNull(integration.anrWatchDog)
val sut = fixture.getSut()

sut.register(fixture.hub, fixture.options)

assertNotNull(sut.anrWatchDog)

sut.close()

assertNull(sut.anrWatchDog)
}

@Test
fun `When ANR watch dog is triggered, snapshot flag should be true`() {
val sut = fixture.getSut()

sut.reportANR(fixture.hub, mock(), getApplicationNotResponding())

verify(fixture.hub).captureException(check {
val ex = it as ExceptionMechanismException
assertTrue(ex.isSnapshot)
})
}

private fun getApplicationNotResponding(): ApplicationNotResponding {
return ApplicationNotResponding("ApplicationNotResponding", Thread.currentThread())
}
}
Loading

0 comments on commit 82eedc3

Please sign in to comment.