-
-
Notifications
You must be signed in to change notification settings - Fork 434
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package io.sentry.spring.checkin; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
import org.jetbrains.annotations.ApiStatus; | ||
import org.springframework.core.annotation.AliasFor; | ||
|
||
/** Sends a {@link io.sentry.CheckIn} for the annotated method. */ | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target({ElementType.METHOD, ElementType.TYPE}) | ||
@ApiStatus.Experimental | ||
public @interface SentryCheckIn { | ||
|
||
/** | ||
* Monitor slug. If not set, no check-in will be sent. | ||
* | ||
* @return monitor slug | ||
*/ | ||
@AliasFor("value") | ||
String monitorSlug() default ""; | ||
|
||
/** | ||
* Whether to send only send heartbeat events. | ||
* | ||
* <p>A hearbeat check-in means there's no separate IN_PROGRESS check-in at the start of the jobs | ||
* execution. Only the check-in after finishing the job will be sent. | ||
* | ||
* @return true if only heartbeat check-ins should be sent. | ||
*/ | ||
boolean heartbeat() default false; | ||
|
||
/** | ||
* Monitor slug. If not set, no check-in will be sent. | ||
* | ||
* @return monitor slug | ||
*/ | ||
@AliasFor("monitorSlug") | ||
String value() default ""; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package io.sentry.spring.checkin; | ||
|
||
import com.jakewharton.nopen.annotation.Open; | ||
import io.sentry.CheckIn; | ||
import io.sentry.CheckInStatus; | ||
import io.sentry.DateUtils; | ||
import io.sentry.IHub; | ||
import io.sentry.SentryLevel; | ||
import io.sentry.protocol.SentryId; | ||
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.jetbrains.annotations.Nullable; | ||
import org.springframework.aop.support.AopUtils; | ||
import org.springframework.core.annotation.AnnotationUtils; | ||
import org.springframework.util.ObjectUtils; | ||
|
||
/** | ||
* Reports execution of every bean method annotated with {@link SentryCheckIn} as a monitor | ||
* check-in. | ||
*/ | ||
@ApiStatus.Internal | ||
@ApiStatus.Experimental | ||
@Open | ||
public class SentryCheckInAdvice implements MethodInterceptor { | ||
private final @NotNull IHub hub; | ||
|
||
public SentryCheckInAdvice(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()); | ||
|
||
@Nullable | ||
SentryCheckIn checkInAnnotation = | ||
AnnotationUtils.findAnnotation(mostSpecificMethod, SentryCheckIn.class); | ||
if (checkInAnnotation == null) { | ||
return invocation.proceed(); | ||
} | ||
|
||
final boolean isHeartbeatOnly = checkInAnnotation.heartbeat(); | ||
final @Nullable String monitorSlug = checkInAnnotation.value(); | ||
|
||
if (ObjectUtils.isEmpty(monitorSlug)) { | ||
hub.getOptions() | ||
.getLogger() | ||
.log( | ||
SentryLevel.WARNING, | ||
"Not capturing check-in for method annotated with @SentryCheckIn because it does not specify a monitor slug."); | ||
return invocation.proceed(); | ||
} | ||
|
||
@Nullable SentryId checkInId = null; | ||
final long startTime = System.currentTimeMillis(); | ||
boolean didError = false; | ||
|
||
try { | ||
if (!isHeartbeatOnly) { | ||
checkInId = hub.captureCheckIn(new CheckIn(monitorSlug, CheckInStatus.IN_PROGRESS)); | ||
} | ||
return invocation.proceed(); | ||
} catch (Throwable e) { | ||
didError = true; | ||
throw e; | ||
} finally { | ||
final @NotNull CheckInStatus status = didError ? CheckInStatus.ERROR : CheckInStatus.OK; | ||
CheckIn checkIn = new CheckIn(checkInId, monitorSlug, status); | ||
checkIn.setDuration(DateUtils.millisToSeconds(System.currentTimeMillis() - startTime)); | ||
hub.captureCheckIn(checkIn); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package io.sentry.spring.checkin; | ||
|
||
import com.jakewharton.nopen.annotation.Open; | ||
import io.sentry.IHub; | ||
import org.aopalliance.aop.Advice; | ||
import org.jetbrains.annotations.ApiStatus; | ||
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; | ||
|
||
@Configuration(proxyBeanMethods = false) | ||
@Open | ||
@ApiStatus.Experimental | ||
public class SentryCheckInAdviceConfiguration { | ||
Check warning on line 18 in sentry-spring/src/main/java/io/sentry/spring/checkin/SentryCheckInAdviceConfiguration.java Codecov / codecov/patchsentry-spring/src/main/java/io/sentry/spring/checkin/SentryCheckInAdviceConfiguration.java#L18
|
||
|
||
@Bean | ||
public @NotNull Advice sentryCheckInAdvice(final @NotNull IHub hub) { | ||
return new SentryCheckInAdvice(hub); | ||
Check warning on line 22 in sentry-spring/src/main/java/io/sentry/spring/checkin/SentryCheckInAdviceConfiguration.java Codecov / codecov/patchsentry-spring/src/main/java/io/sentry/spring/checkin/SentryCheckInAdviceConfiguration.java#L22
|
||
} | ||
|
||
@Bean | ||
public @NotNull Advisor sentryCheckInAdvisor( | ||
final @NotNull @Qualifier("sentryCheckInPointcut") Pointcut sentryCheckInPointcut, | ||
final @NotNull @Qualifier("sentryCheckInAdvice") Advice sentryCheckInAdvice) { | ||
return new DefaultPointcutAdvisor(sentryCheckInPointcut, sentryCheckInAdvice); | ||
Check warning on line 29 in sentry-spring/src/main/java/io/sentry/spring/checkin/SentryCheckInAdviceConfiguration.java Codecov / codecov/patchsentry-spring/src/main/java/io/sentry/spring/checkin/SentryCheckInAdviceConfiguration.java#L29
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package io.sentry.spring.checkin; | ||
|
||
import com.jakewharton.nopen.annotation.Open; | ||
import org.jetbrains.annotations.ApiStatus; | ||
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 SentryCheckIn}. */ | ||
@Configuration(proxyBeanMethods = false) | ||
@Open | ||
@ApiStatus.Experimental | ||
public class SentryCheckInPointcutConfiguration { | ||
Check warning on line 17 in sentry-spring/src/main/java/io/sentry/spring/checkin/SentryCheckInPointcutConfiguration.java Codecov / codecov/patchsentry-spring/src/main/java/io/sentry/spring/checkin/SentryCheckInPointcutConfiguration.java#L17
|
||
|
||
/** | ||
* Pointcut around which check-ins are created. | ||
* | ||
* @return pointcut used by {@link SentryCheckInAdvice}. | ||
*/ | ||
@Bean | ||
public @NotNull Pointcut sentryCheckInPointcut() { | ||
return new ComposablePointcut(new AnnotationClassFilter(SentryCheckIn.class, true)) | ||
.union(new AnnotationMatchingPointcut(null, SentryCheckIn.class)); | ||
Check warning on line 27 in sentry-spring/src/main/java/io/sentry/spring/checkin/SentryCheckInPointcutConfiguration.java Codecov / codecov/patchsentry-spring/src/main/java/io/sentry/spring/checkin/SentryCheckInPointcutConfiguration.java#L26-L27
|
||
} | ||
} |