diff --git a/CHANGELOG.md b/CHANGELOG.md index 78d8e784af6..1174f348f08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ * Enchancement: Do not serialize empty collections and maps (#1245) * Ref: Simplify RestTemplate instrumentation (#1246) +Breaking Changes: +* Enchancement: SentryExceptionResolver should not send handled errors by default (#1248). + + # 4.1.0 * Improve Kotlin compatibility for SdkVersion (#1213) diff --git a/sentry-spring-boot-starter/src/main/java/io/sentry/spring/boot/SentryProperties.java b/sentry-spring-boot-starter/src/main/java/io/sentry/spring/boot/SentryProperties.java index ae5ddbb9ea4..876aa2c60a9 100644 --- a/sentry-spring-boot-starter/src/main/java/io/sentry/spring/boot/SentryProperties.java +++ b/sentry-spring-boot-starter/src/main/java/io/sentry/spring/boot/SentryProperties.java @@ -19,7 +19,7 @@ public class SentryProperties extends SentryOptions { private boolean enableTracing; /** Report all or only uncaught web exceptions. */ - private int exceptionResolverOrder = Integer.MIN_VALUE; + private int exceptionResolverOrder = 1; /** Logging framework integration properties. */ private @NotNull Logging logging = new Logging(); diff --git a/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/it/SentrySpringIntegrationTest.kt b/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/it/SentrySpringIntegrationTest.kt index 8f0b5d93e90..2efc2a69720 100644 --- a/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/it/SentrySpringIntegrationTest.kt +++ b/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/it/SentrySpringIntegrationTest.kt @@ -3,9 +3,11 @@ package io.sentry.spring.boot.it import com.nhaarman.mockitokotlin2.any import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.mock +import com.nhaarman.mockitokotlin2.never import com.nhaarman.mockitokotlin2.reset import com.nhaarman.mockitokotlin2.verify import com.nhaarman.mockitokotlin2.whenever +import io.sentry.IHub import io.sentry.ITransportFactory import io.sentry.Sentry import io.sentry.spring.tracing.SentrySpan @@ -21,6 +23,7 @@ import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.test.context.SpringBootTest +import org.springframework.boot.test.mock.mockito.SpyBean import org.springframework.boot.test.web.client.TestRestTemplate import org.springframework.boot.web.server.LocalServerPort import org.springframework.context.annotation.Bean @@ -28,6 +31,7 @@ import org.springframework.context.annotation.Configuration import org.springframework.http.HttpEntity import org.springframework.http.HttpHeaders import org.springframework.http.HttpMethod +import org.springframework.http.ResponseEntity import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter import org.springframework.security.core.userdetails.User @@ -38,6 +42,8 @@ import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.security.provisioning.InMemoryUserDetailsManager import org.springframework.stereotype.Service import org.springframework.test.context.junit4.SpringRunner +import org.springframework.web.bind.annotation.ControllerAdvice +import org.springframework.web.bind.annotation.ExceptionHandler import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RestController @@ -52,6 +58,9 @@ class SentrySpringIntegrationTest { @Autowired lateinit var transport: ITransport + @SpyBean + lateinit var hub: IHub + @LocalServerPort lateinit var port: Integer @@ -137,6 +146,15 @@ class SentrySpringIntegrationTest { }, anyOrNull()) } } + + @Test + fun `does not send events for handled exceptions`() { + val restTemplate = TestRestTemplate().withBasicAuth("user", "password") + + restTemplate.getForEntity("http://localhost:$port/throws-handled", String::class.java) + + verify(hub, never()).captureEvent(any()) + } } @SpringBootApplication @@ -168,6 +186,11 @@ class HelloController(private val helloService: HelloService) { throw RuntimeException("something went wrong") } + @GetMapping("/throws-handled") + fun throwsHandled() { + throw CustomException("handled exception") + } + @GetMapping("/performance") fun performance() { helloService.throws() @@ -211,3 +234,12 @@ open class SecurityConfiguration : WebSecurityConfigurerAdapter() { return InMemoryUserDetailsManager(user) } } + +class CustomException(message: String) : RuntimeException(message) + +@ControllerAdvice +class ExceptionHandlers { + + @ExceptionHandler(CustomException::class) + fun handle(e: CustomException) = ResponseEntity.badRequest().build() +} diff --git a/sentry-spring-boot-starter/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/sentry-spring-boot-starter/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 00000000000..1f0955d450f --- /dev/null +++ b/sentry-spring-boot-starter/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline diff --git a/sentry-spring/src/main/java/io/sentry/spring/EnableSentry.java b/sentry-spring/src/main/java/io/sentry/spring/EnableSentry.java index 7957ebdfc01..3cd9305a513 100644 --- a/sentry-spring/src/main/java/io/sentry/spring/EnableSentry.java +++ b/sentry-spring/src/main/java/io/sentry/spring/EnableSentry.java @@ -5,7 +5,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.context.annotation.Import; -import org.springframework.core.Ordered; /** * Enables Sentry error handling capabilities. @@ -44,5 +43,5 @@ * * @return the order to use for {@link SentryExceptionResolver} */ - int exceptionResolverOrder() default Ordered.HIGHEST_PRECEDENCE; + int exceptionResolverOrder() default 1; } diff --git a/sentry-spring/src/test/kotlin/io/sentry/spring/EnableSentryTest.kt b/sentry-spring/src/test/kotlin/io/sentry/spring/EnableSentryTest.kt index d7533b7fd40..84f41a92915 100644 --- a/sentry-spring/src/test/kotlin/io/sentry/spring/EnableSentryTest.kt +++ b/sentry-spring/src/test/kotlin/io/sentry/spring/EnableSentryTest.kt @@ -70,7 +70,7 @@ class EnableSentryTest { contextRunner.run { assertThat(it).hasSingleBean(SentryExceptionResolver::class.java) assertThat(it).getBean(SentryExceptionResolver::class.java) - .hasFieldOrPropertyWithValue("order", Integer.MIN_VALUE) + .hasFieldOrPropertyWithValue("order", 1) } } diff --git a/sentry-spring/src/test/kotlin/io/sentry/spring/SentrySpringIntegrationTest.kt b/sentry-spring/src/test/kotlin/io/sentry/spring/SentrySpringIntegrationTest.kt index 0e40229f468..55cedaef9a4 100644 --- a/sentry-spring/src/test/kotlin/io/sentry/spring/SentrySpringIntegrationTest.kt +++ b/sentry-spring/src/test/kotlin/io/sentry/spring/SentrySpringIntegrationTest.kt @@ -25,7 +25,6 @@ import org.springframework.boot.test.web.client.TestRestTemplate import org.springframework.boot.web.server.LocalServerPort import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.core.Ordered import org.springframework.http.HttpEntity import org.springframework.http.HttpHeaders import org.springframework.http.HttpMethod @@ -140,7 +139,7 @@ class SentrySpringIntegrationTest { } @SpringBootApplication -@EnableSentry(dsn = "http://key@localhost/proj", sendDefaultPii = true, exceptionResolverOrder = Ordered.LOWEST_PRECEDENCE) +@EnableSentry(dsn = "http://key@localhost/proj", sendDefaultPii = true) open class App { private val transport = mock()