From 1db3fea84045a07fdd3872ca090c29ac96f01eba Mon Sep 17 00:00:00 2001 From: xeromank Date: Fri, 2 Jun 2023 21:25:47 +0900 Subject: [PATCH 1/7] Add Annotation SentryCaptureException for org.springframework.web.bind.annotation.ExceptionHandler --- .../api/sentry-spring-jakarta.api | 12 +++++ .../tracing/SentryAdviceConfiguration.java | 14 +++++- .../tracing/SentryCaptureException.java | 17 +++++++ .../tracing/SentryCaptureExceptionAdvice.java | 44 +++++++++++++++++++ ...CaptureExceptionPointcutConfiguration.java | 27 ++++++++++++ 5 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureException.java create mode 100644 sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdvice.java create mode 100644 sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionPointcutConfiguration.java diff --git a/sentry-spring-jakarta/api/sentry-spring-jakarta.api b/sentry-spring-jakarta/api/sentry-spring-jakarta.api index f4387ce93a..365791a326 100644 --- a/sentry-spring-jakarta/api/sentry-spring-jakarta.api +++ b/sentry-spring-jakarta/api/sentry-spring-jakarta.api @@ -149,6 +149,18 @@ public class io/sentry/spring/jakarta/tracing/SentryTransactionPointcutConfigura public fun sentryTransactionPointcut ()Lorg/springframework/aop/Pointcut; } +public abstract interface annotation class io/sentry/spring/jakarta/tracing/SentryCaptureException : java/lang/annotation/Annotation { +} + +public class io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdvice : org/aopalliance/intercept/MethodInterceptor { +public fun invoke (Lorg/aopalliance/intercept/MethodInvocation;)Ljava/lang/Object; +} + +public class io/sentry/spring/jakarta/tracing/SentryCaptureExceptionPointcutConfiguration { +public fun ()V +public fun sentryCaptureExceptionPointcut ()Lorg/springframework/aop/Pointcut; +} + public final class io/sentry/spring/jakarta/tracing/SpringMvcTransactionNameProvider : io/sentry/spring/jakarta/tracing/TransactionNameProvider { public fun ()V public fun provideTransactionName (Ljakarta/servlet/http/HttpServletRequest;)Ljava/lang/String; diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryAdviceConfiguration.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryAdviceConfiguration.java index 006c7b38c5..f05e424214 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryAdviceConfiguration.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryAdviceConfiguration.java @@ -11,7 +11,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -/** Creates advice infrastructure for {@link SentrySpan} and {@link SentryTransaction}. */ +/** Creates advice infrastructure for {@link SentrySpan} and {@link SentryTransaction} and {@link SentryCaptureException}. */ @Configuration(proxyBeanMethods = false) @Open public class SentryAdviceConfiguration { @@ -39,4 +39,16 @@ public class SentryAdviceConfiguration { final @NotNull @Qualifier("sentrySpanAdvice") Advice sentrySpanAdvice) { return new DefaultPointcutAdvisor(sentrySpanPointcut, sentrySpanAdvice); } + + @Bean + public @NotNull Advice sentryCaptureExceptionAdvice() { + return new SentryCaptureExceptionAdvice(); + } + + @Bean + public @NotNull Advisor sentryCaptureExceptionAdvisor( + final @NotNull @Qualifier("sentryCaptureExceptionPointcut") Pointcut sentryCaptureExceptionPointcut, + final @NotNull @Qualifier("sentryCaptureExceptionAdvice") Advice sentryCaptureExceptionAdvice) { + return new DefaultPointcutAdvisor(sentryCaptureExceptionPointcut, sentryCaptureExceptionAdvice); + } } diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureException.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureException.java new file mode 100644 index 0000000000..6f39035080 --- /dev/null +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureException.java @@ -0,0 +1,17 @@ +package io.sentry.spring.jakarta.tracing; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * If there is an Exception in the method argument, + * running captureException(final @NotNull Throwable throwable) in {@link io.sentry.Sentry}. + * for {@link org.springframework.web.bind.annotation.ExceptionHandler} + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD}) +public @interface SentryCaptureException { + +} diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdvice.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdvice.java new file mode 100644 index 0000000000..587109fdb9 --- /dev/null +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdvice.java @@ -0,0 +1,44 @@ +package io.sentry.spring.jakarta.tracing; + +import com.jakewharton.nopen.annotation.Open; +import io.sentry.Sentry; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.springframework.aop.support.AopUtils; +import org.springframework.core.annotation.AnnotationUtils; + +import java.lang.reflect.Method; + +/** + * CaptureException execution of every bean method annotated with {@link SentryCaptureException}. + */ + +@ApiStatus.Internal +@Open +public class SentryCaptureExceptionAdvice implements MethodInterceptor { + @Override + public Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { + final Method mostSpecificMethod = + AopUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass()); + SentryCaptureException sentryCaptureException = AnnotationUtils.findAnnotation(mostSpecificMethod, SentryCaptureException.class); + + if (sentryCaptureException != null) { + Object[] args = invocation.getArguments(); + for (Object arg : args) { + if (arg instanceof Exception) { + Sentry.captureException((Exception) arg); + break; + } + } + } + + try { + final Object result = invocation.proceed(); + return result; + } catch (Throwable e) { + throw e; + } + } +} diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionPointcutConfiguration.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionPointcutConfiguration.java new file mode 100644 index 0000000000..2c29e66edb --- /dev/null +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionPointcutConfiguration.java @@ -0,0 +1,27 @@ +package io.sentry.spring.jakarta.tracing; + +import com.jakewharton.nopen.annotation.Open; +import org.jetbrains.annotations.NotNull; +import org.springframework.aop.Pointcut; +import org.springframework.aop.support.ComposablePointcut; +import org.springframework.aop.support.annotation.AnnotationClassFilter; +import org.springframework.aop.support.annotation.AnnotationMatchingPointcut; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** AOP pointcut configuration for {@link SentryCaptureException}. */ +@Configuration(proxyBeanMethods = false) +@Open +public class SentryCaptureExceptionPointcutConfiguration { + + /** + * Pointcut around which spans are created. + * + * @return pointcut used by {@link SentryCaptureExceptionAdvice}. + */ + @Bean + public @NotNull Pointcut sentryCaptureExceptionPointcut() { + return new ComposablePointcut(new AnnotationClassFilter(SentryCaptureException.class, true)) + .union(new AnnotationMatchingPointcut(null, SentryCaptureException.class)); + } +} From 29a990d104cc282ccc38a6badc28011b83e1d96b Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Mon, 12 Jun 2023 12:34:25 +0200 Subject: [PATCH 2/7] Fix config; Add tests --- .../boot/jakarta/SentryAutoConfiguration.java | 14 ++++ .../jakarta/SentryAutoConfigurationTest.kt | 31 +++++++++ .../api/sentry-spring-jakarta.api | 35 ++++++---- .../tracing/SentryAdviceConfiguration.java | 14 +--- .../tracing/SentryCaptureException.java | 10 ++- .../tracing/SentryCaptureExceptionAdvice.java | 43 +++++++----- .../SentryCaptureExceptionConfiguration.java | 17 +++++ .../SentryExceptionAdviceConfiguration.java | 32 +++++++++ .../mvc/SentrySpringIntegrationTest.kt | 40 ++++++++++- .../SentryCaptureExceptionAdviceTest.kt | 68 +++++++++++++++++++ 10 files changed, 256 insertions(+), 48 deletions(-) create mode 100644 sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionConfiguration.java create mode 100644 sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryExceptionAdviceConfiguration.java create mode 100644 sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdviceTest.kt diff --git a/sentry-spring-boot-starter-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryAutoConfiguration.java b/sentry-spring-boot-starter-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryAutoConfiguration.java index 2a0def3722..5f07e81fe3 100644 --- a/sentry-spring-boot-starter-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryAutoConfiguration.java +++ b/sentry-spring-boot-starter-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryAutoConfiguration.java @@ -20,6 +20,8 @@ import io.sentry.spring.jakarta.SentryWebConfiguration; import io.sentry.spring.jakarta.SpringSecuritySentryUserProvider; import io.sentry.spring.jakarta.tracing.SentryAdviceConfiguration; +import io.sentry.spring.jakarta.tracing.SentryCaptureExceptionPointcutConfiguration; +import io.sentry.spring.jakarta.tracing.SentryExceptionAdviceConfiguration; import io.sentry.spring.jakarta.tracing.SentrySpanPointcutConfiguration; import io.sentry.spring.jakarta.tracing.SentryTracingFilter; import io.sentry.spring.jakarta.tracing.SentryTransactionPointcutConfiguration; @@ -262,6 +264,18 @@ public FilterRegistrationBean sentryTracingFilter( } } + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(ProceedingJoinPoint.class) + @Import(SentryExceptionAdviceConfiguration.class) + @Open + static class SentryErrorAspectsConfiguration { + @Configuration(proxyBeanMethods = false) + @ConditionalOnMissingBean(name = "sentryCaptureExceptionPointcut") + @Import(SentryCaptureExceptionPointcutConfiguration.class) + @Open + static class SentryCaptureExceptionPointcutAutoConfiguration {} + } + @Configuration(proxyBeanMethods = false) @Conditional(SentryTracingCondition.class) @ConditionalOnClass(ProceedingJoinPoint.class) diff --git a/sentry-spring-boot-starter-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt b/sentry-spring-boot-starter-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt index 0d7e363732..47d24dda12 100644 --- a/sentry-spring-boot-starter-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt +++ b/sentry-spring-boot-starter-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt @@ -489,6 +489,23 @@ class SentryAutoConfigurationTest { } } + @Test + fun `creates AOP beans to support @SentryCaptureException`() { + contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj") + .run { + assertThat(it).hasSentryExceptionAdviceBeans() + } + } + + @Test + fun `does not create AOP beans to support @SentryCaptureException if AOP class is missing`() { + contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj") + .withClassLoader(FilteredClassLoader(ProceedingJoinPoint::class.java)) + .run { + assertThat(it).doesNotHaveSentryExceptionAdviceBeans() + } + } + @Test fun `when tracing is enabled creates AOP beans to support @SentryTransaction`() { contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj", "sentry.traces-sample-rate=1.0") @@ -920,6 +937,20 @@ class SentryAutoConfigurationTest { return this } + private fun ApplicationContextAssert.hasSentryExceptionAdviceBeans(): ApplicationContextAssert { + this.hasBean("sentryCaptureExceptionPointcut") + this.hasBean("sentryCaptureExceptionAdvice") + this.hasBean("sentryCaptureExceptionAdvisor") + return this + } + + private fun ApplicationContextAssert.doesNotHaveSentryExceptionAdviceBeans(): ApplicationContextAssert { + this.doesNotHaveBean("sentryCaptureExceptionPointcut") + this.doesNotHaveBean("sentryCaptureExceptionAdvice") + this.doesNotHaveBean("sentryCaptureExceptionAdvisor") + return this + } + private fun ApplicationContext.getSentryUserProviders(): List { val userFilter = this.getBean("sentryUserFilter", FilterRegistrationBean::class.java).filter as SentryUserFilter return userFilter.sentryUserProviders diff --git a/sentry-spring-jakarta/api/sentry-spring-jakarta.api b/sentry-spring-jakarta/api/sentry-spring-jakarta.api index 365791a326..c85da15906 100644 --- a/sentry-spring-jakarta/api/sentry-spring-jakarta.api +++ b/sentry-spring-jakarta/api/sentry-spring-jakarta.api @@ -96,6 +96,29 @@ public class io/sentry/spring/jakarta/tracing/SentryAdviceConfiguration { public fun sentryTransactionAdvisor (Lorg/springframework/aop/Pointcut;Lorg/aopalliance/aop/Advice;)Lorg/springframework/aop/Advisor; } +public abstract interface annotation class io/sentry/spring/jakarta/tracing/SentryCaptureException : java/lang/annotation/Annotation { +} + +public class io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdvice : org/aopalliance/intercept/MethodInterceptor { + public fun (Lio/sentry/IHub;)V + public fun invoke (Lorg/aopalliance/intercept/MethodInvocation;)Ljava/lang/Object; +} + +public class io/sentry/spring/jakarta/tracing/SentryCaptureExceptionConfiguration { + public fun ()V +} + +public class io/sentry/spring/jakarta/tracing/SentryCaptureExceptionPointcutConfiguration { + public fun ()V + public fun sentryCaptureExceptionPointcut ()Lorg/springframework/aop/Pointcut; +} + +public class io/sentry/spring/jakarta/tracing/SentryExceptionAdviceConfiguration { + public fun ()V + public fun sentryCaptureExceptionAdvice (Lio/sentry/IHub;)Lorg/aopalliance/aop/Advice; + public fun sentryCaptureExceptionAdvisor (Lorg/springframework/aop/Pointcut;Lorg/aopalliance/aop/Advice;)Lorg/springframework/aop/Advisor; +} + public abstract interface annotation class io/sentry/spring/jakarta/tracing/SentrySpan : java/lang/annotation/Annotation { public abstract fun description ()Ljava/lang/String; public abstract fun operation ()Ljava/lang/String; @@ -149,18 +172,6 @@ public class io/sentry/spring/jakarta/tracing/SentryTransactionPointcutConfigura public fun sentryTransactionPointcut ()Lorg/springframework/aop/Pointcut; } -public abstract interface annotation class io/sentry/spring/jakarta/tracing/SentryCaptureException : java/lang/annotation/Annotation { -} - -public class io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdvice : org/aopalliance/intercept/MethodInterceptor { -public fun invoke (Lorg/aopalliance/intercept/MethodInvocation;)Ljava/lang/Object; -} - -public class io/sentry/spring/jakarta/tracing/SentryCaptureExceptionPointcutConfiguration { -public fun ()V -public fun sentryCaptureExceptionPointcut ()Lorg/springframework/aop/Pointcut; -} - public final class io/sentry/spring/jakarta/tracing/SpringMvcTransactionNameProvider : io/sentry/spring/jakarta/tracing/TransactionNameProvider { public fun ()V public fun provideTransactionName (Ljakarta/servlet/http/HttpServletRequest;)Ljava/lang/String; diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryAdviceConfiguration.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryAdviceConfiguration.java index f05e424214..006c7b38c5 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryAdviceConfiguration.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryAdviceConfiguration.java @@ -11,7 +11,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -/** Creates advice infrastructure for {@link SentrySpan} and {@link SentryTransaction} and {@link SentryCaptureException}. */ +/** Creates advice infrastructure for {@link SentrySpan} and {@link SentryTransaction}. */ @Configuration(proxyBeanMethods = false) @Open public class SentryAdviceConfiguration { @@ -39,16 +39,4 @@ public class SentryAdviceConfiguration { final @NotNull @Qualifier("sentrySpanAdvice") Advice sentrySpanAdvice) { return new DefaultPointcutAdvisor(sentrySpanPointcut, sentrySpanAdvice); } - - @Bean - public @NotNull Advice sentryCaptureExceptionAdvice() { - return new SentryCaptureExceptionAdvice(); - } - - @Bean - public @NotNull Advisor sentryCaptureExceptionAdvisor( - final @NotNull @Qualifier("sentryCaptureExceptionPointcut") Pointcut sentryCaptureExceptionPointcut, - final @NotNull @Qualifier("sentryCaptureExceptionAdvice") Advice sentryCaptureExceptionAdvice) { - return new DefaultPointcutAdvisor(sentryCaptureExceptionPointcut, sentryCaptureExceptionAdvice); - } } diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureException.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureException.java index 6f39035080..1578b4ea07 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureException.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureException.java @@ -6,12 +6,10 @@ import java.lang.annotation.Target; /** - * If there is an Exception in the method argument, - * running captureException(final @NotNull Throwable throwable) in {@link io.sentry.Sentry}. - * for {@link org.springframework.web.bind.annotation.ExceptionHandler} + * Captures an exception passed to an annotated method. Can be used to capture exceptions from your + * {@link org.springframework.web.bind.annotation.ExceptionHandler} but can also be used on other + * methods. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) -public @interface SentryCaptureException { - -} +public @interface SentryCaptureException {} diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdvice.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdvice.java index 587109fdb9..0aa015c4b9 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdvice.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdvice.java @@ -1,7 +1,11 @@ package io.sentry.spring.jakarta.tracing; import com.jakewharton.nopen.annotation.Open; -import io.sentry.Sentry; +import io.sentry.IHub; +import io.sentry.exception.ExceptionMechanismException; +import io.sentry.protocol.Mechanism; +import io.sentry.util.Objects; +import java.lang.reflect.Method; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.jetbrains.annotations.ApiStatus; @@ -9,36 +13,43 @@ import org.springframework.aop.support.AopUtils; import org.springframework.core.annotation.AnnotationUtils; -import java.lang.reflect.Method; - -/** - * CaptureException execution of every bean method annotated with {@link SentryCaptureException}. - */ - +/** Captures an exception passed to a bean method annotated with {@link SentryCaptureException}. */ @ApiStatus.Internal @Open public class SentryCaptureExceptionAdvice implements MethodInterceptor { + private static final String MECHANISM_TYPE = "SentrySpring6CaptureExceptionAdvice"; + private final @NotNull IHub hub; + + public SentryCaptureExceptionAdvice(final @NotNull IHub hub) { + this.hub = Objects.requireNonNull(hub, "hub is required"); + } + @Override public Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { final Method mostSpecificMethod = - AopUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass()); - SentryCaptureException sentryCaptureException = AnnotationUtils.findAnnotation(mostSpecificMethod, SentryCaptureException.class); + AopUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass()); + SentryCaptureException sentryCaptureException = + AnnotationUtils.findAnnotation(mostSpecificMethod, SentryCaptureException.class); if (sentryCaptureException != null) { Object[] args = invocation.getArguments(); for (Object arg : args) { if (arg instanceof Exception) { - Sentry.captureException((Exception) arg); + captureException((Exception) arg); break; } } } - try { - final Object result = invocation.proceed(); - return result; - } catch (Throwable e) { - throw e; - } + return invocation.proceed(); + } + + private void captureException(final @NotNull Throwable throwable) { + final Mechanism mechanism = new Mechanism(); + mechanism.setType(MECHANISM_TYPE); + mechanism.setHandled(true); + final Throwable mechanismException = + new ExceptionMechanismException(mechanism, throwable, Thread.currentThread()); + hub.captureException(mechanismException); } } diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionConfiguration.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionConfiguration.java new file mode 100644 index 0000000000..5a1ac1cad8 --- /dev/null +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionConfiguration.java @@ -0,0 +1,17 @@ +package io.sentry.spring.jakarta.tracing; + +import com.jakewharton.nopen.annotation.Open; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +/** + * Provides infrastructure beans for capturing exceptions passed to bean methods annotated with + * {@link SentryCaptureException}. + */ +@Configuration +@Import({ + SentryExceptionAdviceConfiguration.class, + SentryCaptureExceptionPointcutConfiguration.class +}) +@Open +public class SentryCaptureExceptionConfiguration {} diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryExceptionAdviceConfiguration.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryExceptionAdviceConfiguration.java new file mode 100644 index 0000000000..2f360fa097 --- /dev/null +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryExceptionAdviceConfiguration.java @@ -0,0 +1,32 @@ +package io.sentry.spring.jakarta.tracing; + +import com.jakewharton.nopen.annotation.Open; +import io.sentry.IHub; +import org.aopalliance.aop.Advice; +import org.jetbrains.annotations.NotNull; +import org.springframework.aop.Advisor; +import org.springframework.aop.Pointcut; +import org.springframework.aop.support.DefaultPointcutAdvisor; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** Creates advice infrastructure for {@link SentryCaptureException}. */ +@Configuration(proxyBeanMethods = false) +@Open +public class SentryExceptionAdviceConfiguration { + + @Bean + public @NotNull Advice sentryCaptureExceptionAdvice(final @NotNull IHub hub) { + return new SentryCaptureExceptionAdvice(hub); + } + + @Bean + public @NotNull Advisor sentryCaptureExceptionAdvisor( + final @NotNull @Qualifier("sentryCaptureExceptionPointcut") Pointcut + sentryCaptureExceptionPointcut, + final @NotNull @Qualifier("sentryCaptureExceptionAdvice") Advice + sentryCaptureExceptionAdvice) { + return new DefaultPointcutAdvisor(sentryCaptureExceptionPointcut, sentryCaptureExceptionAdvice); + } +} diff --git a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt index ab0e521f4e..60ff42a5dc 100644 --- a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt +++ b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt @@ -14,6 +14,8 @@ import io.sentry.spring.jakarta.SentryTaskDecorator import io.sentry.spring.jakarta.SentryUserFilter import io.sentry.spring.jakarta.SentryUserProvider import io.sentry.spring.jakarta.SpringSecuritySentryUserProvider +import io.sentry.spring.jakarta.tracing.SentryCaptureException +import io.sentry.spring.jakarta.tracing.SentryCaptureExceptionConfiguration import io.sentry.spring.jakarta.tracing.SentrySpanClientWebRequestFilter import io.sentry.spring.jakarta.tracing.SentryTracingConfiguration import io.sentry.spring.jakarta.tracing.SentryTracingFilter @@ -97,6 +99,9 @@ class SentrySpringIntegrationTest { @Autowired lateinit var someService: SomeService + @Autowired + lateinit var anotherService: AnotherService + @Autowired lateinit var hub: IHub @@ -214,6 +219,30 @@ class SentrySpringIntegrationTest { } } + @Test + fun `calling a method annotated with @SentryCaptureException captures exception`() { + val exception = java.lang.RuntimeException("test exception") + anotherService.aMethodThatTakesAnException(exception) + verify(transport).send( + checkEvent { + assertThat(it.exceptions!!.first().value).isEqualTo(exception.message) + }, + anyOrNull() + ) + } + + @Test + fun `calling a method annotated with @SentryCaptureException captures exception in later param`() { + val exception = java.lang.RuntimeException("test exception") + anotherService.aMethodThatTakesAnExceptionAsLaterParam("a", "b", exception) + verify(transport).send( + checkEvent { + assertThat(it.exceptions!!.first().value).isEqualTo(exception.message) + }, + anyOrNull() + ) + } + @Test fun `calling a method annotated with @SentryTransaction creates transaction`() { someService.aMethod() @@ -317,7 +346,7 @@ class SentrySpringIntegrationTest { @SpringBootApplication @EnableSentry(dsn = "http://key@localhost/proj", sendDefaultPii = true, maxRequestBodySize = SentryOptions.RequestSize.MEDIUM) -@Import(SentryTracingConfiguration::class) +@Import(SentryTracingConfiguration::class, SentryCaptureExceptionConfiguration::class) open class App { @Bean @@ -370,6 +399,15 @@ open class App { } } +@Service +open class AnotherService { + @SentryCaptureException + open fun aMethodThatTakesAnException(e: Exception) {} + + @SentryCaptureException + open fun aMethodThatTakesAnExceptionAsLaterParam(a: String, b: String, e: Exception) {} +} + @Service open class SomeService { diff --git a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdviceTest.kt b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdviceTest.kt new file mode 100644 index 0000000000..55edfa2bea --- /dev/null +++ b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdviceTest.kt @@ -0,0 +1,68 @@ +package io.sentry.spring.jakarta.tracing + +import io.sentry.IHub +import io.sentry.exception.ExceptionMechanismException +import org.junit.runner.RunWith +import org.mockito.kotlin.check +import org.mockito.kotlin.mock +import org.mockito.kotlin.reset +import org.mockito.kotlin.verify +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.EnableAspectJAutoProxy +import org.springframework.context.annotation.Import +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig +import org.springframework.test.context.junit4.SpringRunner +import kotlin.test.BeforeTest +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +@RunWith(SpringRunner::class) +@SpringJUnitConfig(SentryCaptureExceptionAdviceTest.Config::class) +class SentryCaptureExceptionAdviceTest { + + @Autowired + lateinit var sampleService: SampleService + + @Autowired + lateinit var hub: IHub + + @BeforeTest + fun setup() { + reset(hub) + } + + @Test + fun `captures exception passed to method annotated with @SentryCaptureException`() { + val exception = RuntimeException("test exception") + sampleService.methodTakingAnException(exception) + verify(hub).captureException( + check { + assertTrue(it is ExceptionMechanismException) + val mechanismException = it as ExceptionMechanismException + assertEquals(exception, mechanismException.throwable) + assertEquals("SentrySpring6CaptureExceptionAdvice", mechanismException.exceptionMechanism.type) + } + ) + } + + @Configuration + @EnableAspectJAutoProxy(proxyTargetClass = true) + @Import(SentryCaptureExceptionConfiguration::class) + open class Config { + + @Bean + open fun sampleService() = SampleService() + + @Bean + open fun hub() = mock() + } + + open class SampleService { + + @SentryCaptureException + open fun methodTakingAnException(e: Exception) = Unit + } +} From 7e356cc26664b35f70eb25c477e148cc3161f447 Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Thu, 5 Oct 2023 15:56:16 +0200 Subject: [PATCH 3/7] Rename annotation to SentryCaptureExceptionParameter and conditional on AOT compat --- .../boot/jakarta/SentryAutoConfiguration.java | 16 +++++---- .../jakarta/SentryAutoConfigurationTest.kt | 24 +++++++------- .../api/sentry-spring-jakarta.api | 16 ++++----- ...a => SentryCaptureExceptionParameter.java} | 2 +- ...entryCaptureExceptionParameterAdvice.java} | 17 ++++++---- ...ptureExceptionParameterConfiguration.java} | 8 ++--- ...eptionParameterPointcutConfiguration.java} | 13 ++++---- .../SentryExceptionAdviceConfiguration.java | 32 ------------------ ...ExceptionParameterAdviceConfiguration.java | 33 +++++++++++++++++++ .../mvc/SentrySpringIntegrationTest.kt | 10 +++--- ...tryCaptureExceptionParameterAdviceTest.kt} | 10 +++--- 11 files changed, 95 insertions(+), 86 deletions(-) rename sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/{SentryCaptureException.java => SentryCaptureExceptionParameter.java} (90%) rename sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/{SentryCaptureExceptionAdvice.java => SentryCaptureExceptionParameterAdvice.java} (78%) rename sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/{SentryCaptureExceptionConfiguration.java => SentryCaptureExceptionParameterConfiguration.java} (61%) rename sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/{SentryCaptureExceptionPointcutConfiguration.java => SentryCaptureExceptionParameterPointcutConfiguration.java} (66%) delete mode 100644 sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryExceptionAdviceConfiguration.java create mode 100644 sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryExceptionParameterAdviceConfiguration.java rename sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/tracing/{SentryCaptureExceptionAdviceTest.kt => SentryCaptureExceptionParameterAdviceTest.kt} (84%) diff --git a/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryAutoConfiguration.java b/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryAutoConfiguration.java index a1c1c9dff0..acdc9b0552 100644 --- a/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryAutoConfiguration.java +++ b/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryAutoConfiguration.java @@ -27,8 +27,8 @@ import io.sentry.spring.jakarta.checkin.SentryQuartzConfiguration; import io.sentry.spring.jakarta.graphql.SentryGraphqlConfiguration; import io.sentry.spring.jakarta.tracing.SentryAdviceConfiguration; -import io.sentry.spring.jakarta.tracing.SentryCaptureExceptionPointcutConfiguration; -import io.sentry.spring.jakarta.tracing.SentryExceptionAdviceConfiguration; +import io.sentry.spring.jakarta.tracing.SentryCaptureExceptionParameterPointcutConfiguration; +import io.sentry.spring.jakarta.tracing.SentryExceptionParameterAdviceConfiguration; import io.sentry.spring.jakarta.tracing.SentrySpanPointcutConfiguration; import io.sentry.spring.jakarta.tracing.SentryTracingFilter; import io.sentry.spring.jakarta.tracing.SentryTransactionPointcutConfiguration; @@ -308,14 +308,18 @@ public FilterRegistrationBean sentryTracingFilter( @Configuration(proxyBeanMethods = false) @ConditionalOnClass(ProceedingJoinPoint.class) - @Import(SentryExceptionAdviceConfiguration.class) + @ConditionalOnProperty( + value = "sentry.enable-aot-compatibility", + havingValue = "false", + matchIfMissing = true) + @Import(SentryExceptionParameterAdviceConfiguration.class) @Open static class SentryErrorAspectsConfiguration { @Configuration(proxyBeanMethods = false) - @ConditionalOnMissingBean(name = "sentryCaptureExceptionPointcut") - @Import(SentryCaptureExceptionPointcutConfiguration.class) + @ConditionalOnMissingBean(name = "sentryCaptureExceptionParameterPointcut") + @Import(SentryCaptureExceptionParameterPointcutConfiguration.class) @Open - static class SentryCaptureExceptionPointcutAutoConfiguration {} + static class SentryCaptureExceptionParameterPointcutAutoConfiguration {} } @Configuration(proxyBeanMethods = false) diff --git a/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt b/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt index 229305c6b8..8e5221203f 100644 --- a/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt +++ b/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt @@ -492,19 +492,19 @@ class SentryAutoConfigurationTest { } @Test - fun `creates AOP beans to support @SentryCaptureException`() { + fun `creates AOP beans to support @SentryCaptureExceptionParameter`() { contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj") .run { - assertThat(it).hasSentryExceptionAdviceBeans() + assertThat(it).hasSentryExceptionParameterAdviceBeans() } } @Test - fun `does not create AOP beans to support @SentryCaptureException if AOP class is missing`() { + fun `does not create AOP beans to support @SentryCaptureExceptionParameter if AOP class is missing`() { contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj") .withClassLoader(FilteredClassLoader(ProceedingJoinPoint::class.java)) .run { - assertThat(it).doesNotHaveSentryExceptionAdviceBeans() + assertThat(it).doesNotHaveSentryExceptionParameterAdviceBeans() } } @@ -974,17 +974,17 @@ class SentryAutoConfigurationTest { return this } - private fun ApplicationContextAssert.hasSentryExceptionAdviceBeans(): ApplicationContextAssert { - this.hasBean("sentryCaptureExceptionPointcut") - this.hasBean("sentryCaptureExceptionAdvice") - this.hasBean("sentryCaptureExceptionAdvisor") + private fun ApplicationContextAssert.hasSentryExceptionParameterAdviceBeans(): ApplicationContextAssert { + this.hasBean("sentryCaptureExceptionParameterPointcut") + this.hasBean("sentryCaptureExceptionParameterAdvice") + this.hasBean("sentryCaptureExceptionParameterAdvisor") return this } - private fun ApplicationContextAssert.doesNotHaveSentryExceptionAdviceBeans(): ApplicationContextAssert { - this.doesNotHaveBean("sentryCaptureExceptionPointcut") - this.doesNotHaveBean("sentryCaptureExceptionAdvice") - this.doesNotHaveBean("sentryCaptureExceptionAdvisor") + private fun ApplicationContextAssert.doesNotHaveSentryExceptionParameterAdviceBeans(): ApplicationContextAssert { + this.doesNotHaveBean("sentryCaptureExceptionParameterPointcut") + this.doesNotHaveBean("sentryCaptureExceptionParameterAdvice") + this.doesNotHaveBean("sentryCaptureExceptionParameterAdvisor") return this } diff --git a/sentry-spring-jakarta/api/sentry-spring-jakarta.api b/sentry-spring-jakarta/api/sentry-spring-jakarta.api index 2cc62e0a00..702a59d5b6 100644 --- a/sentry-spring-jakarta/api/sentry-spring-jakarta.api +++ b/sentry-spring-jakarta/api/sentry-spring-jakarta.api @@ -172,27 +172,27 @@ public class io/sentry/spring/jakarta/tracing/SentryAdviceConfiguration { public fun sentryTransactionAdvisor (Lorg/springframework/aop/Pointcut;Lorg/aopalliance/aop/Advice;)Lorg/springframework/aop/Advisor; } -public abstract interface annotation class io/sentry/spring/jakarta/tracing/SentryCaptureException : java/lang/annotation/Annotation { +public abstract interface annotation class io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameter : java/lang/annotation/Annotation { } -public class io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdvice : org/aopalliance/intercept/MethodInterceptor { +public class io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterAdvice : org/aopalliance/intercept/MethodInterceptor { public fun (Lio/sentry/IHub;)V public fun invoke (Lorg/aopalliance/intercept/MethodInvocation;)Ljava/lang/Object; } -public class io/sentry/spring/jakarta/tracing/SentryCaptureExceptionConfiguration { +public class io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterConfiguration { public fun ()V } -public class io/sentry/spring/jakarta/tracing/SentryCaptureExceptionPointcutConfiguration { +public class io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterPointcutConfiguration { public fun ()V - public fun sentryCaptureExceptionPointcut ()Lorg/springframework/aop/Pointcut; + public fun sentryCaptureExceptionParameterPointcut ()Lorg/springframework/aop/Pointcut; } -public class io/sentry/spring/jakarta/tracing/SentryExceptionAdviceConfiguration { +public class io/sentry/spring/jakarta/tracing/SentryExceptionParameterAdviceConfiguration { public fun ()V - public fun sentryCaptureExceptionAdvice (Lio/sentry/IHub;)Lorg/aopalliance/aop/Advice; - public fun sentryCaptureExceptionAdvisor (Lorg/springframework/aop/Pointcut;Lorg/aopalliance/aop/Advice;)Lorg/springframework/aop/Advisor; + public fun sentryCaptureExceptionParameterAdvice (Lio/sentry/IHub;)Lorg/aopalliance/aop/Advice; + public fun sentryCaptureExceptionParameterAdvisor (Lorg/springframework/aop/Pointcut;Lorg/aopalliance/aop/Advice;)Lorg/springframework/aop/Advisor; } public abstract interface annotation class io/sentry/spring/jakarta/tracing/SentrySpan : java/lang/annotation/Annotation { diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureException.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameter.java similarity index 90% rename from sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureException.java rename to sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameter.java index 1578b4ea07..2069ebf5f7 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureException.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameter.java @@ -12,4 +12,4 @@ */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) -public @interface SentryCaptureException {} +public @interface SentryCaptureExceptionParameter {} diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdvice.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterAdvice.java similarity index 78% rename from sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdvice.java rename to sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterAdvice.java index 0aa015c4b9..70433e6228 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdvice.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterAdvice.java @@ -13,14 +13,17 @@ import org.springframework.aop.support.AopUtils; import org.springframework.core.annotation.AnnotationUtils; -/** Captures an exception passed to a bean method annotated with {@link SentryCaptureException}. */ +/** + * Captures an exception passed to a bean method annotated with {@link + * SentryCaptureExceptionParameter}. + */ @ApiStatus.Internal @Open -public class SentryCaptureExceptionAdvice implements MethodInterceptor { - private static final String MECHANISM_TYPE = "SentrySpring6CaptureExceptionAdvice"; +public class SentryCaptureExceptionParameterAdvice implements MethodInterceptor { + private static final String MECHANISM_TYPE = "SentrySpring6CaptureExceptionParameterAdvice"; private final @NotNull IHub hub; - public SentryCaptureExceptionAdvice(final @NotNull IHub hub) { + public SentryCaptureExceptionParameterAdvice(final @NotNull IHub hub) { this.hub = Objects.requireNonNull(hub, "hub is required"); } @@ -28,10 +31,10 @@ public SentryCaptureExceptionAdvice(final @NotNull IHub hub) { public Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { final Method mostSpecificMethod = AopUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass()); - SentryCaptureException sentryCaptureException = - AnnotationUtils.findAnnotation(mostSpecificMethod, SentryCaptureException.class); + SentryCaptureExceptionParameter sentryCaptureExceptionParameter = + AnnotationUtils.findAnnotation(mostSpecificMethod, SentryCaptureExceptionParameter.class); - if (sentryCaptureException != null) { + if (sentryCaptureExceptionParameter != null) { Object[] args = invocation.getArguments(); for (Object arg : args) { if (arg instanceof Exception) { diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionConfiguration.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterConfiguration.java similarity index 61% rename from sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionConfiguration.java rename to sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterConfiguration.java index 5a1ac1cad8..9b675b05dc 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionConfiguration.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterConfiguration.java @@ -6,12 +6,12 @@ /** * Provides infrastructure beans for capturing exceptions passed to bean methods annotated with - * {@link SentryCaptureException}. + * {@link SentryCaptureExceptionParameter}. */ @Configuration @Import({ - SentryExceptionAdviceConfiguration.class, - SentryCaptureExceptionPointcutConfiguration.class + SentryExceptionParameterAdviceConfiguration.class, + SentryCaptureExceptionParameterPointcutConfiguration.class }) @Open -public class SentryCaptureExceptionConfiguration {} +public class SentryCaptureExceptionParameterConfiguration {} diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionPointcutConfiguration.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterPointcutConfiguration.java similarity index 66% rename from sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionPointcutConfiguration.java rename to sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterPointcutConfiguration.java index 2c29e66edb..946df6b474 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionPointcutConfiguration.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterPointcutConfiguration.java @@ -9,19 +9,20 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -/** AOP pointcut configuration for {@link SentryCaptureException}. */ +/** AOP pointcut configuration for {@link SentryCaptureExceptionParameter}. */ @Configuration(proxyBeanMethods = false) @Open -public class SentryCaptureExceptionPointcutConfiguration { +public class SentryCaptureExceptionParameterPointcutConfiguration { /** * Pointcut around which spans are created. * - * @return pointcut used by {@link SentryCaptureExceptionAdvice}. + * @return pointcut used by {@link SentryCaptureExceptionParameterAdvice}. */ @Bean - public @NotNull Pointcut sentryCaptureExceptionPointcut() { - return new ComposablePointcut(new AnnotationClassFilter(SentryCaptureException.class, true)) - .union(new AnnotationMatchingPointcut(null, SentryCaptureException.class)); + public @NotNull Pointcut sentryCaptureExceptionParameterPointcut() { + return new ComposablePointcut( + new AnnotationClassFilter(SentryCaptureExceptionParameter.class, true)) + .union(new AnnotationMatchingPointcut(null, SentryCaptureExceptionParameter.class)); } } diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryExceptionAdviceConfiguration.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryExceptionAdviceConfiguration.java deleted file mode 100644 index 2f360fa097..0000000000 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryExceptionAdviceConfiguration.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.sentry.spring.jakarta.tracing; - -import com.jakewharton.nopen.annotation.Open; -import io.sentry.IHub; -import org.aopalliance.aop.Advice; -import org.jetbrains.annotations.NotNull; -import org.springframework.aop.Advisor; -import org.springframework.aop.Pointcut; -import org.springframework.aop.support.DefaultPointcutAdvisor; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** Creates advice infrastructure for {@link SentryCaptureException}. */ -@Configuration(proxyBeanMethods = false) -@Open -public class SentryExceptionAdviceConfiguration { - - @Bean - public @NotNull Advice sentryCaptureExceptionAdvice(final @NotNull IHub hub) { - return new SentryCaptureExceptionAdvice(hub); - } - - @Bean - public @NotNull Advisor sentryCaptureExceptionAdvisor( - final @NotNull @Qualifier("sentryCaptureExceptionPointcut") Pointcut - sentryCaptureExceptionPointcut, - final @NotNull @Qualifier("sentryCaptureExceptionAdvice") Advice - sentryCaptureExceptionAdvice) { - return new DefaultPointcutAdvisor(sentryCaptureExceptionPointcut, sentryCaptureExceptionAdvice); - } -} diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryExceptionParameterAdviceConfiguration.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryExceptionParameterAdviceConfiguration.java new file mode 100644 index 0000000000..b3a3ddab3b --- /dev/null +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryExceptionParameterAdviceConfiguration.java @@ -0,0 +1,33 @@ +package io.sentry.spring.jakarta.tracing; + +import com.jakewharton.nopen.annotation.Open; +import io.sentry.IHub; +import org.aopalliance.aop.Advice; +import org.jetbrains.annotations.NotNull; +import org.springframework.aop.Advisor; +import org.springframework.aop.Pointcut; +import org.springframework.aop.support.DefaultPointcutAdvisor; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** Creates advice infrastructure for {@link SentryCaptureExceptionParameter}. */ +@Configuration(proxyBeanMethods = false) +@Open +public class SentryExceptionParameterAdviceConfiguration { + + @Bean + public @NotNull Advice sentryCaptureExceptionParameterAdvice(final @NotNull IHub hub) { + return new SentryCaptureExceptionParameterAdvice(hub); + } + + @Bean + public @NotNull Advisor sentryCaptureExceptionParameterAdvisor( + final @NotNull @Qualifier("sentryCaptureExceptionParameterPointcut") Pointcut + sentryCaptureExceptionParameterPointcut, + final @NotNull @Qualifier("sentryCaptureExceptionParameterAdvice") Advice + sentryCaptureExceptionParameterAdvice) { + return new DefaultPointcutAdvisor( + sentryCaptureExceptionParameterPointcut, sentryCaptureExceptionParameterAdvice); + } +} diff --git a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt index 5f8b37f830..51fb1abfd3 100644 --- a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt +++ b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt @@ -15,8 +15,8 @@ import io.sentry.spring.jakarta.SentryTaskDecorator import io.sentry.spring.jakarta.SentryUserFilter import io.sentry.spring.jakarta.SentryUserProvider import io.sentry.spring.jakarta.SpringSecuritySentryUserProvider -import io.sentry.spring.jakarta.tracing.SentryCaptureException -import io.sentry.spring.jakarta.tracing.SentryCaptureExceptionConfiguration +import io.sentry.spring.jakarta.tracing.SentryCaptureExceptionParameter +import io.sentry.spring.jakarta.tracing.SentryCaptureExceptionParameterConfiguration import io.sentry.spring.jakarta.tracing.SentrySpanClientWebRequestFilter import io.sentry.spring.jakarta.tracing.SentryTracingConfiguration import io.sentry.spring.jakarta.tracing.SentryTracingFilter @@ -348,7 +348,7 @@ class SentrySpringIntegrationTest { @SpringBootApplication @EnableSentry(dsn = "http://key@localhost/proj", sendDefaultPii = true, maxRequestBodySize = SentryOptions.RequestSize.MEDIUM) -@Import(SentryTracingConfiguration::class, SentryCaptureExceptionConfiguration::class) +@Import(SentryTracingConfiguration::class, SentryCaptureExceptionParameterConfiguration::class) open class App { @Bean @@ -403,10 +403,10 @@ open class App { @Service open class AnotherService { - @SentryCaptureException + @SentryCaptureExceptionParameter open fun aMethodThatTakesAnException(e: Exception) {} - @SentryCaptureException + @SentryCaptureExceptionParameter open fun aMethodThatTakesAnExceptionAsLaterParam(a: String, b: String, e: Exception) {} } diff --git a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdviceTest.kt b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterAdviceTest.kt similarity index 84% rename from sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdviceTest.kt rename to sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterAdviceTest.kt index 55edfa2bea..58908a5531 100644 --- a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionAdviceTest.kt +++ b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterAdviceTest.kt @@ -20,8 +20,8 @@ import kotlin.test.assertEquals import kotlin.test.assertTrue @RunWith(SpringRunner::class) -@SpringJUnitConfig(SentryCaptureExceptionAdviceTest.Config::class) -class SentryCaptureExceptionAdviceTest { +@SpringJUnitConfig(SentryCaptureExceptionParameterAdviceTest.Config::class) +class SentryCaptureExceptionParameterAdviceTest { @Autowired lateinit var sampleService: SampleService @@ -43,14 +43,14 @@ class SentryCaptureExceptionAdviceTest { assertTrue(it is ExceptionMechanismException) val mechanismException = it as ExceptionMechanismException assertEquals(exception, mechanismException.throwable) - assertEquals("SentrySpring6CaptureExceptionAdvice", mechanismException.exceptionMechanism.type) + assertEquals("SentrySpring6CaptureExceptionParameterAdvice", mechanismException.exceptionMechanism.type) } ) } @Configuration @EnableAspectJAutoProxy(proxyTargetClass = true) - @Import(SentryCaptureExceptionConfiguration::class) + @Import(SentryCaptureExceptionParameterConfiguration::class) open class Config { @Bean @@ -62,7 +62,7 @@ class SentryCaptureExceptionAdviceTest { open class SampleService { - @SentryCaptureException + @SentryCaptureExceptionParameter open fun methodTakingAnException(e: Exception) = Unit } } From 73b3debb341051eae53fbc9cf09b02979bd1ef9e Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Thu, 5 Oct 2023 16:47:56 +0200 Subject: [PATCH 4/7] move into separate package --- .../boot/jakarta/SentryAutoConfiguration.java | 4 +- .../api/sentry-spring-jakarta.api | 46 +++++++++---------- .../SentryCaptureExceptionParameter.java | 2 +- ...SentryCaptureExceptionParameterAdvice.java | 2 +- ...aptureExceptionParameterConfiguration.java | 2 +- ...ceptionParameterPointcutConfiguration.java | 2 +- ...ExceptionParameterAdviceConfiguration.java | 2 +- .../mvc/SentrySpringIntegrationTest.kt | 4 +- ...ntryCaptureExceptionParameterAdviceTest.kt | 2 + 9 files changed, 34 insertions(+), 32 deletions(-) rename sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/{tracing => exception}/SentryCaptureExceptionParameter.java (91%) rename sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/{tracing => exception}/SentryCaptureExceptionParameterAdvice.java (97%) rename sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/{tracing => exception}/SentryCaptureExceptionParameterConfiguration.java (92%) rename sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/{tracing => exception}/SentryCaptureExceptionParameterPointcutConfiguration.java (96%) rename sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/{tracing => exception}/SentryExceptionParameterAdviceConfiguration.java (96%) diff --git a/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryAutoConfiguration.java b/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryAutoConfiguration.java index acdc9b0552..69cb159359 100644 --- a/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryAutoConfiguration.java +++ b/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryAutoConfiguration.java @@ -25,10 +25,10 @@ import io.sentry.spring.jakarta.checkin.SentryCheckInAdviceConfiguration; import io.sentry.spring.jakarta.checkin.SentryCheckInPointcutConfiguration; import io.sentry.spring.jakarta.checkin.SentryQuartzConfiguration; +import io.sentry.spring.jakarta.exception.SentryCaptureExceptionParameterPointcutConfiguration; +import io.sentry.spring.jakarta.exception.SentryExceptionParameterAdviceConfiguration; import io.sentry.spring.jakarta.graphql.SentryGraphqlConfiguration; import io.sentry.spring.jakarta.tracing.SentryAdviceConfiguration; -import io.sentry.spring.jakarta.tracing.SentryCaptureExceptionParameterPointcutConfiguration; -import io.sentry.spring.jakarta.tracing.SentryExceptionParameterAdviceConfiguration; import io.sentry.spring.jakarta.tracing.SentrySpanPointcutConfiguration; import io.sentry.spring.jakarta.tracing.SentryTracingFilter; import io.sentry.spring.jakarta.tracing.SentryTransactionPointcutConfiguration; diff --git a/sentry-spring-jakarta/api/sentry-spring-jakarta.api b/sentry-spring-jakarta/api/sentry-spring-jakarta.api index 702a59d5b6..3cf41ef269 100644 --- a/sentry-spring-jakarta/api/sentry-spring-jakarta.api +++ b/sentry-spring-jakarta/api/sentry-spring-jakarta.api @@ -120,6 +120,29 @@ public final class io/sentry/spring/jakarta/checkin/SentrySchedulerFactoryBeanCu public fun customize (Lorg/springframework/scheduling/quartz/SchedulerFactoryBean;)V } +public abstract interface annotation class io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameter : java/lang/annotation/Annotation { +} + +public class io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdvice : org/aopalliance/intercept/MethodInterceptor { + public fun (Lio/sentry/IHub;)V + public fun invoke (Lorg/aopalliance/intercept/MethodInvocation;)Ljava/lang/Object; +} + +public class io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterConfiguration { + public fun ()V +} + +public class io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterPointcutConfiguration { + public fun ()V + public fun sentryCaptureExceptionParameterPointcut ()Lorg/springframework/aop/Pointcut; +} + +public class io/sentry/spring/jakarta/exception/SentryExceptionParameterAdviceConfiguration { + public fun ()V + public fun sentryCaptureExceptionParameterAdvice (Lio/sentry/IHub;)Lorg/aopalliance/aop/Advice; + public fun sentryCaptureExceptionParameterAdvisor (Lorg/springframework/aop/Pointcut;Lorg/aopalliance/aop/Advice;)Lorg/springframework/aop/Advisor; +} + public final class io/sentry/spring/jakarta/graphql/SentryBatchLoaderRegistry : org/springframework/graphql/execution/BatchLoaderRegistry { public fun forName (Ljava/lang/String;)Lorg/springframework/graphql/execution/BatchLoaderRegistry$RegistrationSpec; public fun forTypePair (Ljava/lang/Class;Ljava/lang/Class;)Lorg/springframework/graphql/execution/BatchLoaderRegistry$RegistrationSpec; @@ -172,29 +195,6 @@ public class io/sentry/spring/jakarta/tracing/SentryAdviceConfiguration { public fun sentryTransactionAdvisor (Lorg/springframework/aop/Pointcut;Lorg/aopalliance/aop/Advice;)Lorg/springframework/aop/Advisor; } -public abstract interface annotation class io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameter : java/lang/annotation/Annotation { -} - -public class io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterAdvice : org/aopalliance/intercept/MethodInterceptor { - public fun (Lio/sentry/IHub;)V - public fun invoke (Lorg/aopalliance/intercept/MethodInvocation;)Ljava/lang/Object; -} - -public class io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterConfiguration { - public fun ()V -} - -public class io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterPointcutConfiguration { - public fun ()V - public fun sentryCaptureExceptionParameterPointcut ()Lorg/springframework/aop/Pointcut; -} - -public class io/sentry/spring/jakarta/tracing/SentryExceptionParameterAdviceConfiguration { - public fun ()V - public fun sentryCaptureExceptionParameterAdvice (Lio/sentry/IHub;)Lorg/aopalliance/aop/Advice; - public fun sentryCaptureExceptionParameterAdvisor (Lorg/springframework/aop/Pointcut;Lorg/aopalliance/aop/Advice;)Lorg/springframework/aop/Advisor; -} - public abstract interface annotation class io/sentry/spring/jakarta/tracing/SentrySpan : java/lang/annotation/Annotation { public abstract fun description ()Ljava/lang/String; public abstract fun operation ()Ljava/lang/String; diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameter.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameter.java similarity index 91% rename from sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameter.java rename to sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameter.java index 2069ebf5f7..4911419c0b 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameter.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameter.java @@ -1,4 +1,4 @@ -package io.sentry.spring.jakarta.tracing; +package io.sentry.spring.jakarta.exception; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterAdvice.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdvice.java similarity index 97% rename from sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterAdvice.java rename to sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdvice.java index 70433e6228..104726bb39 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterAdvice.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdvice.java @@ -1,4 +1,4 @@ -package io.sentry.spring.jakarta.tracing; +package io.sentry.spring.jakarta.exception; import com.jakewharton.nopen.annotation.Open; import io.sentry.IHub; diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterConfiguration.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterConfiguration.java similarity index 92% rename from sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterConfiguration.java rename to sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterConfiguration.java index 9b675b05dc..0d4f4274be 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterConfiguration.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterConfiguration.java @@ -1,4 +1,4 @@ -package io.sentry.spring.jakarta.tracing; +package io.sentry.spring.jakarta.exception; import com.jakewharton.nopen.annotation.Open; import org.springframework.context.annotation.Configuration; diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterPointcutConfiguration.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterPointcutConfiguration.java similarity index 96% rename from sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterPointcutConfiguration.java rename to sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterPointcutConfiguration.java index 946df6b474..26dc0e225a 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterPointcutConfiguration.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterPointcutConfiguration.java @@ -1,4 +1,4 @@ -package io.sentry.spring.jakarta.tracing; +package io.sentry.spring.jakarta.exception; import com.jakewharton.nopen.annotation.Open; import org.jetbrains.annotations.NotNull; diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryExceptionParameterAdviceConfiguration.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryExceptionParameterAdviceConfiguration.java similarity index 96% rename from sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryExceptionParameterAdviceConfiguration.java rename to sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryExceptionParameterAdviceConfiguration.java index b3a3ddab3b..8ffb813731 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryExceptionParameterAdviceConfiguration.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryExceptionParameterAdviceConfiguration.java @@ -1,4 +1,4 @@ -package io.sentry.spring.jakarta.tracing; +package io.sentry.spring.jakarta.exception; import com.jakewharton.nopen.annotation.Open; import io.sentry.IHub; diff --git a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt index 51fb1abfd3..f472a75a65 100644 --- a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt +++ b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt @@ -15,8 +15,8 @@ import io.sentry.spring.jakarta.SentryTaskDecorator import io.sentry.spring.jakarta.SentryUserFilter import io.sentry.spring.jakarta.SentryUserProvider import io.sentry.spring.jakarta.SpringSecuritySentryUserProvider -import io.sentry.spring.jakarta.tracing.SentryCaptureExceptionParameter -import io.sentry.spring.jakarta.tracing.SentryCaptureExceptionParameterConfiguration +import io.sentry.spring.jakarta.exception.SentryCaptureExceptionParameter +import io.sentry.spring.jakarta.exception.SentryCaptureExceptionParameterConfiguration import io.sentry.spring.jakarta.tracing.SentrySpanClientWebRequestFilter import io.sentry.spring.jakarta.tracing.SentryTracingConfiguration import io.sentry.spring.jakarta.tracing.SentryTracingFilter diff --git a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterAdviceTest.kt b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterAdviceTest.kt index 58908a5531..34d31bd311 100644 --- a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterAdviceTest.kt +++ b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterAdviceTest.kt @@ -2,6 +2,8 @@ package io.sentry.spring.jakarta.tracing import io.sentry.IHub import io.sentry.exception.ExceptionMechanismException +import io.sentry.spring.jakarta.exception.SentryCaptureExceptionParameter +import io.sentry.spring.jakarta.exception.SentryCaptureExceptionParameterConfiguration import org.junit.runner.RunWith import org.mockito.kotlin.check import org.mockito.kotlin.mock From 982523b93dae3c72342e43be67047855dbb7be4a Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Fri, 6 Oct 2023 10:02:38 +0200 Subject: [PATCH 5/7] duplicate for spring boot 2 --- .../spring/boot/SentryAutoConfiguration.java | 18 +++++ .../boot/SentryAutoConfigurationTest.kt | 31 +++++++++ ...ntryCaptureExceptionParameterAdviceTest.kt | 4 +- sentry-spring/api/sentry-spring.api | 23 +++++++ .../SentryCaptureExceptionParameter.java | 15 ++++ ...SentryCaptureExceptionParameterAdvice.java | 58 ++++++++++++++++ ...aptureExceptionParameterConfiguration.java | 17 +++++ ...ceptionParameterPointcutConfiguration.java | 28 ++++++++ ...ExceptionParameterAdviceConfiguration.java | 33 +++++++++ ...ntryCaptureExceptionParameterAdviceTest.kt | 68 +++++++++++++++++++ .../spring/mvc/SentrySpringIntegrationTest.kt | 40 ++++++++++- 11 files changed, 331 insertions(+), 4 deletions(-) rename sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/{tracing => exception}/SentryCaptureExceptionParameterAdviceTest.kt (91%) create mode 100644 sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameter.java create mode 100644 sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameterAdvice.java create mode 100644 sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameterConfiguration.java create mode 100644 sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameterPointcutConfiguration.java create mode 100644 sentry-spring/src/main/java/io/sentry/spring/exception/SentryExceptionParameterAdviceConfiguration.java create mode 100644 sentry-spring/src/test/kotlin/io/sentry/spring/exception/SentryCaptureExceptionParameterAdviceTest.kt diff --git a/sentry-spring-boot/src/main/java/io/sentry/spring/boot/SentryAutoConfiguration.java b/sentry-spring-boot/src/main/java/io/sentry/spring/boot/SentryAutoConfiguration.java index 131be4a1ec..7198eecbfd 100644 --- a/sentry-spring-boot/src/main/java/io/sentry/spring/boot/SentryAutoConfiguration.java +++ b/sentry-spring-boot/src/main/java/io/sentry/spring/boot/SentryAutoConfiguration.java @@ -25,6 +25,8 @@ import io.sentry.spring.checkin.SentryCheckInAdviceConfiguration; import io.sentry.spring.checkin.SentryCheckInPointcutConfiguration; import io.sentry.spring.checkin.SentryQuartzConfiguration; +import io.sentry.spring.exception.SentryCaptureExceptionParameterPointcutConfiguration; +import io.sentry.spring.exception.SentryExceptionParameterAdviceConfiguration; import io.sentry.spring.graphql.SentryGraphqlConfiguration; import io.sentry.spring.tracing.SentryAdviceConfiguration; import io.sentry.spring.tracing.SentrySpanPointcutConfiguration; @@ -304,6 +306,22 @@ public FilterRegistrationBean sentryTracingFilter( } } + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(ProceedingJoinPoint.class) + @ConditionalOnProperty( + value = "sentry.enable-aot-compatibility", + havingValue = "false", + matchIfMissing = true) + @Import(SentryExceptionParameterAdviceConfiguration.class) + @Open + static class SentryErrorAspectsConfiguration { + @Configuration(proxyBeanMethods = false) + @ConditionalOnMissingBean(name = "sentryCaptureExceptionParameterPointcut") + @Import(SentryCaptureExceptionParameterPointcutConfiguration.class) + @Open + static class SentryCaptureExceptionParameterPointcutAutoConfiguration {} + } + @Configuration(proxyBeanMethods = false) @Conditional(SentryTracingCondition.class) @ConditionalOnClass(ProceedingJoinPoint.class) diff --git a/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt b/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt index 44f280e6cb..71369d6f2d 100644 --- a/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt +++ b/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt @@ -491,6 +491,23 @@ class SentryAutoConfigurationTest { } } + @Test + fun `creates AOP beans to support @SentryCaptureExceptionParameter`() { + contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj") + .run { + assertThat(it).hasSentryExceptionParameterAdviceBeans() + } + } + + @Test + fun `does not create AOP beans to support @SentryCaptureExceptionParameter if AOP class is missing`() { + contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj") + .withClassLoader(FilteredClassLoader(ProceedingJoinPoint::class.java)) + .run { + assertThat(it).doesNotHaveSentryExceptionParameterAdviceBeans() + } + } + @Test fun `when tracing is enabled creates AOP beans to support @SentryTransaction`() { contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj", "sentry.traces-sample-rate=1.0") @@ -957,6 +974,20 @@ class SentryAutoConfigurationTest { return this } + private fun ApplicationContextAssert.hasSentryExceptionParameterAdviceBeans(): ApplicationContextAssert { + this.hasBean("sentryCaptureExceptionParameterPointcut") + this.hasBean("sentryCaptureExceptionParameterAdvice") + this.hasBean("sentryCaptureExceptionParameterAdvisor") + return this + } + + private fun ApplicationContextAssert.doesNotHaveSentryExceptionParameterAdviceBeans(): ApplicationContextAssert { + this.doesNotHaveBean("sentryCaptureExceptionParameterPointcut") + this.doesNotHaveBean("sentryCaptureExceptionParameterAdvice") + this.doesNotHaveBean("sentryCaptureExceptionParameterAdvisor") + return this + } + private fun ApplicationContext.getSentryUserProviders(): List { val userFilter = this.getBean("sentryUserFilter", FilterRegistrationBean::class.java).filter as SentryUserFilter return userFilter.sentryUserProviders diff --git a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterAdviceTest.kt b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdviceTest.kt similarity index 91% rename from sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterAdviceTest.kt rename to sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdviceTest.kt index 34d31bd311..a98bca0606 100644 --- a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/tracing/SentryCaptureExceptionParameterAdviceTest.kt +++ b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdviceTest.kt @@ -1,9 +1,7 @@ -package io.sentry.spring.jakarta.tracing +package io.sentry.spring.jakarta.exception import io.sentry.IHub import io.sentry.exception.ExceptionMechanismException -import io.sentry.spring.jakarta.exception.SentryCaptureExceptionParameter -import io.sentry.spring.jakarta.exception.SentryCaptureExceptionParameterConfiguration import org.junit.runner.RunWith import org.mockito.kotlin.check import org.mockito.kotlin.mock diff --git a/sentry-spring/api/sentry-spring.api b/sentry-spring/api/sentry-spring.api index ac4111e208..952330f8a9 100644 --- a/sentry-spring/api/sentry-spring.api +++ b/sentry-spring/api/sentry-spring.api @@ -120,6 +120,29 @@ public final class io/sentry/spring/checkin/SentrySchedulerFactoryBeanCustomizer public fun customize (Lorg/springframework/scheduling/quartz/SchedulerFactoryBean;)V } +public abstract interface annotation class io/sentry/spring/exception/SentryCaptureExceptionParameter : java/lang/annotation/Annotation { +} + +public class io/sentry/spring/exception/SentryCaptureExceptionParameterAdvice : org/aopalliance/intercept/MethodInterceptor { + public fun (Lio/sentry/IHub;)V + public fun invoke (Lorg/aopalliance/intercept/MethodInvocation;)Ljava/lang/Object; +} + +public class io/sentry/spring/exception/SentryCaptureExceptionParameterConfiguration { + public fun ()V +} + +public class io/sentry/spring/exception/SentryCaptureExceptionParameterPointcutConfiguration { + public fun ()V + public fun sentryCaptureExceptionParameterPointcut ()Lorg/springframework/aop/Pointcut; +} + +public class io/sentry/spring/exception/SentryExceptionParameterAdviceConfiguration { + public fun ()V + public fun sentryCaptureExceptionParameterAdvice (Lio/sentry/IHub;)Lorg/aopalliance/aop/Advice; + public fun sentryCaptureExceptionParameterAdvisor (Lorg/springframework/aop/Pointcut;Lorg/aopalliance/aop/Advice;)Lorg/springframework/aop/Advisor; +} + public final class io/sentry/spring/graphql/SentryBatchLoaderRegistry : org/springframework/graphql/execution/BatchLoaderRegistry { public fun forName (Ljava/lang/String;)Lorg/springframework/graphql/execution/BatchLoaderRegistry$RegistrationSpec; public fun forTypePair (Ljava/lang/Class;Ljava/lang/Class;)Lorg/springframework/graphql/execution/BatchLoaderRegistry$RegistrationSpec; diff --git a/sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameter.java b/sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameter.java new file mode 100644 index 0000000000..88f9fef8bd --- /dev/null +++ b/sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameter.java @@ -0,0 +1,15 @@ +package io.sentry.spring.exception; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Captures an exception passed to an annotated method. Can be used to capture exceptions from your + * {@link org.springframework.web.bind.annotation.ExceptionHandler} but can also be used on other + * methods. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD}) +public @interface SentryCaptureExceptionParameter {} diff --git a/sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameterAdvice.java b/sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameterAdvice.java new file mode 100644 index 0000000000..5cca2550d7 --- /dev/null +++ b/sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameterAdvice.java @@ -0,0 +1,58 @@ +package io.sentry.spring.exception; + +import com.jakewharton.nopen.annotation.Open; +import io.sentry.IHub; +import io.sentry.exception.ExceptionMechanismException; +import io.sentry.protocol.Mechanism; +import io.sentry.util.Objects; +import java.lang.reflect.Method; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.springframework.aop.support.AopUtils; +import org.springframework.core.annotation.AnnotationUtils; + +/** + * Captures an exception passed to a bean method annotated with {@link + * SentryCaptureExceptionParameter}. + */ +@ApiStatus.Internal +@Open +public class SentryCaptureExceptionParameterAdvice implements MethodInterceptor { + private static final String MECHANISM_TYPE = "SentrySpring6CaptureExceptionParameterAdvice"; + private final @NotNull IHub hub; + + public SentryCaptureExceptionParameterAdvice(final @NotNull IHub hub) { + this.hub = Objects.requireNonNull(hub, "hub is required"); + } + + @Override + public Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { + final Method mostSpecificMethod = + AopUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass()); + SentryCaptureExceptionParameter sentryCaptureExceptionParameter = + AnnotationUtils.findAnnotation(mostSpecificMethod, SentryCaptureExceptionParameter.class); + + if (sentryCaptureExceptionParameter != null) { + Object[] args = invocation.getArguments(); + for (Object arg : args) { + if (arg instanceof Exception) { + captureException((Exception) arg); + break; + } + } + } + + return invocation.proceed(); + } + + private void captureException(final @NotNull Throwable throwable) { + final Mechanism mechanism = new Mechanism(); + mechanism.setType(MECHANISM_TYPE); + mechanism.setHandled(true); + final Throwable mechanismException = + new ExceptionMechanismException(mechanism, throwable, Thread.currentThread()); + hub.captureException(mechanismException); + } +} diff --git a/sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameterConfiguration.java b/sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameterConfiguration.java new file mode 100644 index 0000000000..8b331da6b0 --- /dev/null +++ b/sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameterConfiguration.java @@ -0,0 +1,17 @@ +package io.sentry.spring.exception; + +import com.jakewharton.nopen.annotation.Open; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +/** + * Provides infrastructure beans for capturing exceptions passed to bean methods annotated with + * {@link SentryCaptureExceptionParameter}. + */ +@Configuration +@Import({ + SentryExceptionParameterAdviceConfiguration.class, + SentryCaptureExceptionParameterPointcutConfiguration.class +}) +@Open +public class SentryCaptureExceptionParameterConfiguration {} diff --git a/sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameterPointcutConfiguration.java b/sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameterPointcutConfiguration.java new file mode 100644 index 0000000000..cd43f6c03b --- /dev/null +++ b/sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameterPointcutConfiguration.java @@ -0,0 +1,28 @@ +package io.sentry.spring.exception; + +import com.jakewharton.nopen.annotation.Open; +import org.jetbrains.annotations.NotNull; +import org.springframework.aop.Pointcut; +import org.springframework.aop.support.ComposablePointcut; +import org.springframework.aop.support.annotation.AnnotationClassFilter; +import org.springframework.aop.support.annotation.AnnotationMatchingPointcut; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** AOP pointcut configuration for {@link SentryCaptureExceptionParameter}. */ +@Configuration(proxyBeanMethods = false) +@Open +public class SentryCaptureExceptionParameterPointcutConfiguration { + + /** + * Pointcut around which spans are created. + * + * @return pointcut used by {@link SentryCaptureExceptionParameterAdvice}. + */ + @Bean + public @NotNull Pointcut sentryCaptureExceptionParameterPointcut() { + return new ComposablePointcut( + new AnnotationClassFilter(SentryCaptureExceptionParameter.class, true)) + .union(new AnnotationMatchingPointcut(null, SentryCaptureExceptionParameter.class)); + } +} diff --git a/sentry-spring/src/main/java/io/sentry/spring/exception/SentryExceptionParameterAdviceConfiguration.java b/sentry-spring/src/main/java/io/sentry/spring/exception/SentryExceptionParameterAdviceConfiguration.java new file mode 100644 index 0000000000..7d98914f35 --- /dev/null +++ b/sentry-spring/src/main/java/io/sentry/spring/exception/SentryExceptionParameterAdviceConfiguration.java @@ -0,0 +1,33 @@ +package io.sentry.spring.exception; + +import com.jakewharton.nopen.annotation.Open; +import io.sentry.IHub; +import org.aopalliance.aop.Advice; +import org.jetbrains.annotations.NotNull; +import org.springframework.aop.Advisor; +import org.springframework.aop.Pointcut; +import org.springframework.aop.support.DefaultPointcutAdvisor; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** Creates advice infrastructure for {@link SentryCaptureExceptionParameter}. */ +@Configuration(proxyBeanMethods = false) +@Open +public class SentryExceptionParameterAdviceConfiguration { + + @Bean + public @NotNull Advice sentryCaptureExceptionParameterAdvice(final @NotNull IHub hub) { + return new SentryCaptureExceptionParameterAdvice(hub); + } + + @Bean + public @NotNull Advisor sentryCaptureExceptionParameterAdvisor( + final @NotNull @Qualifier("sentryCaptureExceptionParameterPointcut") Pointcut + sentryCaptureExceptionParameterPointcut, + final @NotNull @Qualifier("sentryCaptureExceptionParameterAdvice") Advice + sentryCaptureExceptionParameterAdvice) { + return new DefaultPointcutAdvisor( + sentryCaptureExceptionParameterPointcut, sentryCaptureExceptionParameterAdvice); + } +} diff --git a/sentry-spring/src/test/kotlin/io/sentry/spring/exception/SentryCaptureExceptionParameterAdviceTest.kt b/sentry-spring/src/test/kotlin/io/sentry/spring/exception/SentryCaptureExceptionParameterAdviceTest.kt new file mode 100644 index 0000000000..e1c8a29b91 --- /dev/null +++ b/sentry-spring/src/test/kotlin/io/sentry/spring/exception/SentryCaptureExceptionParameterAdviceTest.kt @@ -0,0 +1,68 @@ +package io.sentry.spring.exception + +import io.sentry.IHub +import io.sentry.exception.ExceptionMechanismException +import org.junit.runner.RunWith +import org.mockito.kotlin.check +import org.mockito.kotlin.mock +import org.mockito.kotlin.reset +import org.mockito.kotlin.verify +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.EnableAspectJAutoProxy +import org.springframework.context.annotation.Import +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig +import org.springframework.test.context.junit4.SpringRunner +import kotlin.test.BeforeTest +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +@RunWith(SpringRunner::class) +@SpringJUnitConfig(SentryCaptureExceptionParameterAdviceTest.Config::class) +class SentryCaptureExceptionParameterAdviceTest { + + @Autowired + lateinit var sampleService: SampleService + + @Autowired + lateinit var hub: IHub + + @BeforeTest + fun setup() { + reset(hub) + } + + @Test + fun `captures exception passed to method annotated with @SentryCaptureException`() { + val exception = RuntimeException("test exception") + sampleService.methodTakingAnException(exception) + verify(hub).captureException( + check { + assertTrue(it is ExceptionMechanismException) + val mechanismException = it as ExceptionMechanismException + assertEquals(exception, mechanismException.throwable) + assertEquals("SentrySpring6CaptureExceptionParameterAdvice", mechanismException.exceptionMechanism.type) + } + ) + } + + @Configuration + @EnableAspectJAutoProxy(proxyTargetClass = true) + @Import(SentryCaptureExceptionParameterConfiguration::class) + open class Config { + + @Bean + open fun sampleService() = SampleService() + + @Bean + open fun hub() = mock() + } + + open class SampleService { + + @SentryCaptureExceptionParameter + open fun methodTakingAnException(e: Exception) = Unit + } +} diff --git a/sentry-spring/src/test/kotlin/io/sentry/spring/mvc/SentrySpringIntegrationTest.kt b/sentry-spring/src/test/kotlin/io/sentry/spring/mvc/SentrySpringIntegrationTest.kt index 58ce6906e5..998b27c7e8 100644 --- a/sentry-spring/src/test/kotlin/io/sentry/spring/mvc/SentrySpringIntegrationTest.kt +++ b/sentry-spring/src/test/kotlin/io/sentry/spring/mvc/SentrySpringIntegrationTest.kt @@ -15,6 +15,8 @@ import io.sentry.spring.SentryTaskDecorator import io.sentry.spring.SentryUserFilter import io.sentry.spring.SentryUserProvider import io.sentry.spring.SpringSecuritySentryUserProvider +import io.sentry.spring.exception.SentryCaptureExceptionParameter +import io.sentry.spring.exception.SentryCaptureExceptionParameterConfiguration import io.sentry.spring.tracing.SentrySpanClientWebRequestFilter import io.sentry.spring.tracing.SentryTracingConfiguration import io.sentry.spring.tracing.SentryTracingFilter @@ -98,6 +100,9 @@ class SentrySpringIntegrationTest { @Autowired lateinit var someService: SomeService + @Autowired + lateinit var anotherService: AnotherService + @Autowired lateinit var hub: IHub @@ -215,6 +220,30 @@ class SentrySpringIntegrationTest { } } + @Test + fun `calling a method annotated with @SentryCaptureException captures exception`() { + val exception = java.lang.RuntimeException("test exception") + anotherService.aMethodThatTakesAnException(exception) + verify(transport).send( + checkEvent { + assertThat(it.exceptions!!.first().value).isEqualTo(exception.message) + }, + anyOrNull() + ) + } + + @Test + fun `calling a method annotated with @SentryCaptureException captures exception in later param`() { + val exception = java.lang.RuntimeException("test exception") + anotherService.aMethodThatTakesAnExceptionAsLaterParam("a", "b", exception) + verify(transport).send( + checkEvent { + assertThat(it.exceptions!!.first().value).isEqualTo(exception.message) + }, + anyOrNull() + ) + } + @Test fun `calling a method annotated with @SentryTransaction creates transaction`() { someService.aMethod() @@ -319,7 +348,7 @@ class SentrySpringIntegrationTest { @SpringBootApplication @EnableSentry(dsn = "http://key@localhost/proj", sendDefaultPii = true, maxRequestBodySize = SentryOptions.RequestSize.MEDIUM) -@Import(SentryTracingConfiguration::class) +@Import(SentryTracingConfiguration::class, SentryCaptureExceptionParameterConfiguration::class) open class App { @Bean @@ -372,6 +401,15 @@ open class App { } } +@Service +open class AnotherService { + @SentryCaptureExceptionParameter + open fun aMethodThatTakesAnException(e: Exception) {} + + @SentryCaptureExceptionParameter + open fun aMethodThatTakesAnExceptionAsLaterParam(a: String, b: String, e: Exception) {} +} + @Service open class SomeService { From a4c9aa75f331531624ace35c2cba20fa07b502b6 Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Fri, 6 Oct 2023 16:59:06 +0200 Subject: [PATCH 6/7] changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64bb70ad35..c3196d7ad3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ ### Features - Add `CheckInUtils.withCheckIn` which abstracts away some of the manual check-ins complexity ([#2959](https://github.com/getsentry/sentry-java/pull/2959)) +- Add `@SentryCaptureExceptionParameter` annotation which captures exceptions passed into an annotated method ([#2764](https://github.com/getsentry/sentry-java/pull/2764)) + - This can be used to replace `Sentry.captureException` calls in `@ExceptionHandler` of a `@ControllerAdvice` ## 6.30.0 From a7be4af11395090f665cf49d0c9e4f1e09fc58cc Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Mon, 9 Oct 2023 07:53:31 +0200 Subject: [PATCH 7/7] Fix spring version number --- .../spring/exception/SentryCaptureExceptionParameterAdvice.java | 2 +- .../exception/SentryCaptureExceptionParameterAdviceTest.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameterAdvice.java b/sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameterAdvice.java index 5cca2550d7..c3d9e8741a 100644 --- a/sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameterAdvice.java +++ b/sentry-spring/src/main/java/io/sentry/spring/exception/SentryCaptureExceptionParameterAdvice.java @@ -20,7 +20,7 @@ @ApiStatus.Internal @Open public class SentryCaptureExceptionParameterAdvice implements MethodInterceptor { - private static final String MECHANISM_TYPE = "SentrySpring6CaptureExceptionParameterAdvice"; + private static final String MECHANISM_TYPE = "SentrySpring5CaptureExceptionParameterAdvice"; private final @NotNull IHub hub; public SentryCaptureExceptionParameterAdvice(final @NotNull IHub hub) { diff --git a/sentry-spring/src/test/kotlin/io/sentry/spring/exception/SentryCaptureExceptionParameterAdviceTest.kt b/sentry-spring/src/test/kotlin/io/sentry/spring/exception/SentryCaptureExceptionParameterAdviceTest.kt index e1c8a29b91..af4232fedc 100644 --- a/sentry-spring/src/test/kotlin/io/sentry/spring/exception/SentryCaptureExceptionParameterAdviceTest.kt +++ b/sentry-spring/src/test/kotlin/io/sentry/spring/exception/SentryCaptureExceptionParameterAdviceTest.kt @@ -43,7 +43,7 @@ class SentryCaptureExceptionParameterAdviceTest { assertTrue(it is ExceptionMechanismException) val mechanismException = it as ExceptionMechanismException assertEquals(exception, mechanismException.throwable) - assertEquals("SentrySpring6CaptureExceptionParameterAdvice", mechanismException.exceptionMechanism.type) + assertEquals("SentrySpring5CaptureExceptionParameterAdvice", mechanismException.exceptionMechanism.type) } ) }