Skip to content

Replace GraphQlSourceBuilderCustomizer with directly providing a SentryInstrumenter bean if missing #3744

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
- Support `graphql-java` v22 via a new module `sentry-graphql-22` ([#3740](https://github.com/getsentry/sentry-java/pull/3740))
- If you are using `graphql-java` v21 or earlier, you can use the `sentry-graphql` module
- For `graphql-java` v22 and newer please use the `sentry-graphql-22` module
- We now provide a `SentryInstrumenter` bean directly for Spring (Boot) if there is none yet instead of using `GraphQlSourceBuilderCustomizer` to add the instrumentation ([#3744](https://github.com/getsentry/sentry-java/pull/3744))
- It is now also possible to provide a bean of type `SentryGraphqlInstrumentation.BeforeSpanCallback` which is then used by `SentryInstrumenter`

### Fixes

Expand Down
1 change: 1 addition & 0 deletions sentry-graphql-22/api/sentry-graphql-22.api
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
public final class io/sentry/graphql22/BuildConfig {
public static final field SENTRY_GRAPHQL_SDK_NAME Ljava/lang/String;
public static final field SENTRY_GRAPHQL22_SDK_NAME Ljava/lang/String;
public static final field VERSION_NAME Ljava/lang/String;
}
Expand Down
12 changes: 10 additions & 2 deletions sentry-spring-boot-jakarta/api/sentry-spring-boot-jakarta.api
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,19 @@ public class io/sentry/spring/boot/jakarta/SentryWebfluxAutoConfiguration {
public fun sentryWebExceptionHandler (Lio/sentry/IScopes;)Lio/sentry/spring/jakarta/webflux/SentryWebExceptionHandler;
}

public class io/sentry/spring/boot/jakarta/graphql/SentryGraphql22AutoConfiguration {
public fun <init> ()V
public fun exceptionResolverAdapter ()Lio/sentry/spring/jakarta/graphql/SentryDataFetcherExceptionResolverAdapter;
public static fun graphqlBeanPostProcessor ()Lio/sentry/spring/jakarta/graphql/SentryGraphqlBeanPostProcessor;
public fun sentryInstrumentationWebMvc (Lio/sentry/spring/boot/jakarta/SentryProperties;Lorg/springframework/beans/factory/ObjectProvider;)Lio/sentry/graphql22/SentryInstrumentation;
public fun sentryInstrumentationWebflux (Lio/sentry/spring/boot/jakarta/SentryProperties;Lorg/springframework/beans/factory/ObjectProvider;)Lio/sentry/graphql22/SentryInstrumentation;
}

public class io/sentry/spring/boot/jakarta/graphql/SentryGraphqlAutoConfiguration {
public fun <init> ()V
public fun exceptionResolverAdapter ()Lio/sentry/spring/jakarta/graphql/SentryDataFetcherExceptionResolverAdapter;
public static fun graphqlBeanPostProcessor ()Lio/sentry/spring/jakarta/graphql/SentryGraphqlBeanPostProcessor;
public fun sourceBuilderCustomizerWebflux (Lio/sentry/spring/boot/jakarta/SentryProperties;)Lorg/springframework/boot/autoconfigure/graphql/GraphQlSourceBuilderCustomizer;
public fun sourceBuilderCustomizerWebmvc (Lio/sentry/spring/boot/jakarta/SentryProperties;)Lorg/springframework/boot/autoconfigure/graphql/GraphQlSourceBuilderCustomizer;
public fun sentryInstrumentationWebMvc (Lio/sentry/spring/boot/jakarta/SentryProperties;Lorg/springframework/beans/factory/ObjectProvider;)Lio/sentry/graphql/SentryInstrumentation;
public fun sentryInstrumentationWebflux (Lio/sentry/spring/boot/jakarta/SentryProperties;Lorg/springframework/beans/factory/ObjectProvider;)Lio/sentry/graphql/SentryInstrumentation;
}

Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@

import com.jakewharton.nopen.annotation.Open;
import io.sentry.SentryIntegrationPackageStorage;
import io.sentry.graphql.SentryGraphqlInstrumentation;
import io.sentry.graphql.SentryInstrumentation;
import io.sentry.spring.boot.jakarta.SentryProperties;
import io.sentry.spring.jakarta.graphql.SentryDataFetcherExceptionResolverAdapter;
import io.sentry.spring.jakarta.graphql.SentryGraphqlBeanPostProcessor;
import io.sentry.spring.jakarta.graphql.SentrySpringSubscriptionHandler;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.graphql.GraphQlSourceBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
Expand All @@ -19,37 +21,42 @@
@Open
public class SentryGraphqlAutoConfiguration {

@Bean
@Bean(name = "sentryInstrumentation")
@ConditionalOnMissingBean
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public GraphQlSourceBuilderCustomizer sourceBuilderCustomizerWebmvc(
final @NotNull SentryProperties sentryProperties) {
public SentryInstrumentation sentryInstrumentationWebMvc(
final @NotNull SentryProperties sentryProperties,
final @NotNull ObjectProvider<SentryGraphqlInstrumentation.BeforeSpanCallback>
beforeSpanCallback) {
SentryIntegrationPackageStorage.getInstance().addIntegration("Spring6GrahQLWebMVC");
return sourceBuilderCustomizer(sentryProperties, false);
return createInstrumentation(sentryProperties, beforeSpanCallback, false);
}

@Bean
@Bean(name = "sentryInstrumentation")
@ConditionalOnMissingBean
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
public GraphQlSourceBuilderCustomizer sourceBuilderCustomizerWebflux(
final @NotNull SentryProperties sentryProperties) {
public SentryInstrumentation sentryInstrumentationWebflux(
final @NotNull SentryProperties sentryProperties,
final @NotNull ObjectProvider<SentryGraphqlInstrumentation.BeforeSpanCallback>
beforeSpanCallback) {
SentryIntegrationPackageStorage.getInstance().addIntegration("Spring6GrahQLWebFlux");
return sourceBuilderCustomizer(sentryProperties, true);
return createInstrumentation(sentryProperties, beforeSpanCallback, true);
}

/**
* We're not setting defaultDataFetcherExceptionHandler here on purpose and instead use the
* resolver adapter below. This way Springs handler can still forward to other resolver adapters.
*/
private GraphQlSourceBuilderCustomizer sourceBuilderCustomizer(
final @NotNull SentryProperties sentryProperties, final boolean captureRequestBody) {
return (builder) ->
builder.configureGraphQl(
graphQlBuilder ->
graphQlBuilder.instrumentation(
new SentryInstrumentation(
null,
new SentrySpringSubscriptionHandler(),
captureRequestBody,
sentryProperties.getGraphql().getIgnoredErrorTypes())));
private SentryInstrumentation createInstrumentation(
final @NotNull SentryProperties sentryProperties,
final @NotNull ObjectProvider<SentryGraphqlInstrumentation.BeforeSpanCallback>
beforeSpanCallback,
final boolean captureRequestBody) {
return new SentryInstrumentation(
beforeSpanCallback.getIfAvailable(),
new SentrySpringSubscriptionHandler(),
captureRequestBody,
sentryProperties.getGraphql().getIgnoredErrorTypes());
}

@Bean
Expand Down
4 changes: 2 additions & 2 deletions sentry-spring-boot/api/sentry-spring-boot.api
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public class io/sentry/spring/boot/graphql/SentryGraphqlAutoConfiguration {
public fun <init> ()V
public fun exceptionResolverAdapter ()Lio/sentry/spring/graphql/SentryDataFetcherExceptionResolverAdapter;
public static fun graphqlBeanPostProcessor ()Lio/sentry/spring/graphql/SentryGraphqlBeanPostProcessor;
public fun sourceBuilderCustomizerWebflux (Lio/sentry/spring/boot/SentryProperties;)Lorg/springframework/boot/autoconfigure/graphql/GraphQlSourceBuilderCustomizer;
public fun sourceBuilderCustomizerWebmvc (Lio/sentry/spring/boot/SentryProperties;)Lorg/springframework/boot/autoconfigure/graphql/GraphQlSourceBuilderCustomizer;
public fun sentryInstrumentationWebMvc (Lio/sentry/spring/boot/SentryProperties;Lorg/springframework/beans/factory/ObjectProvider;)Lio/sentry/graphql/SentryInstrumentation;
public fun sentryInstrumentationWebflux (Lio/sentry/spring/boot/SentryProperties;Lorg/springframework/beans/factory/ObjectProvider;)Lio/sentry/graphql/SentryInstrumentation;
}

Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@

import com.jakewharton.nopen.annotation.Open;
import io.sentry.SentryIntegrationPackageStorage;
import io.sentry.graphql.SentryGraphqlInstrumentation;
import io.sentry.graphql.SentryInstrumentation;
import io.sentry.spring.boot.SentryProperties;
import io.sentry.spring.graphql.SentryDataFetcherExceptionResolverAdapter;
import io.sentry.spring.graphql.SentryGraphqlBeanPostProcessor;
import io.sentry.spring.graphql.SentrySpringSubscriptionHandler;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.graphql.GraphQlSourceBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
Expand All @@ -19,37 +21,42 @@
@Open
public class SentryGraphqlAutoConfiguration {

@Bean
@Bean(name = "sentryInstrumentation")
@ConditionalOnMissingBean
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public GraphQlSourceBuilderCustomizer sourceBuilderCustomizerWebmvc(
final @NotNull SentryProperties sentryProperties) {
public SentryInstrumentation sentryInstrumentationWebMvc(
final @NotNull SentryProperties sentryProperties,
final @NotNull ObjectProvider<SentryGraphqlInstrumentation.BeforeSpanCallback>
beforeSpanCallback) {
SentryIntegrationPackageStorage.getInstance().addIntegration("Spring5GrahQLWebMVC");
return sourceBuilderCustomizer(sentryProperties, false);
return createInstrumentation(sentryProperties, beforeSpanCallback, false);
}

@Bean
@Bean(name = "sentryInstrumentation")
@ConditionalOnMissingBean
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
public GraphQlSourceBuilderCustomizer sourceBuilderCustomizerWebflux(
final @NotNull SentryProperties sentryProperties) {
public SentryInstrumentation sentryInstrumentationWebflux(
final @NotNull SentryProperties sentryProperties,
final @NotNull ObjectProvider<SentryGraphqlInstrumentation.BeforeSpanCallback>
beforeSpanCallback) {
SentryIntegrationPackageStorage.getInstance().addIntegration("Spring5GrahQLWebFlux");
return sourceBuilderCustomizer(sentryProperties, true);
return createInstrumentation(sentryProperties, beforeSpanCallback, true);
}

/**
* We're not setting defaultDataFetcherExceptionHandler here on purpose and instead use the
* resolver adapter below. This way Springs handler can still forward to other resolver adapters.
*/
private GraphQlSourceBuilderCustomizer sourceBuilderCustomizer(
final @NotNull SentryProperties sentryProperties, final boolean captureRequestBody) {
return (builder) ->
builder.configureGraphQl(
graphQlBuilder ->
graphQlBuilder.instrumentation(
new SentryInstrumentation(
null,
new SentrySpringSubscriptionHandler(),
captureRequestBody,
sentryProperties.getGraphql().getIgnoredErrorTypes())));
private SentryInstrumentation createInstrumentation(
final @NotNull SentryProperties sentryProperties,
final @NotNull ObjectProvider<SentryGraphqlInstrumentation.BeforeSpanCallback>
beforeSpanCallback,
final boolean captureRequestBody) {
return new SentryInstrumentation(
beforeSpanCallback.getIfAvailable(),
new SentrySpringSubscriptionHandler(),
captureRequestBody,
sentryProperties.getGraphql().getIgnoredErrorTypes());
}

@Bean
Expand Down
4 changes: 2 additions & 2 deletions sentry-spring-jakarta/api/sentry-spring-jakarta.api
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,8 @@ public class io/sentry/spring/jakarta/graphql/SentryGraphqlConfiguration {
public fun <init> ()V
public fun exceptionResolverAdapter ()Lio/sentry/spring/jakarta/graphql/SentryDataFetcherExceptionResolverAdapter;
public fun graphqlBeanPostProcessor ()Lio/sentry/spring/jakarta/graphql/SentryGraphqlBeanPostProcessor;
public fun sourceBuilderCustomizerWebflux ()Lorg/springframework/boot/autoconfigure/graphql/GraphQlSourceBuilderCustomizer;
public fun sourceBuilderCustomizerWebmvc ()Lorg/springframework/boot/autoconfigure/graphql/GraphQlSourceBuilderCustomizer;
public fun sentryInstrumentationWebMvc (Lorg/springframework/beans/factory/ObjectProvider;)Lio/sentry/graphql/SentryInstrumentation;
public fun sentryInstrumentationWebflux (Lorg/springframework/beans/factory/ObjectProvider;)Lio/sentry/graphql/SentryInstrumentation;
}

public final class io/sentry/spring/jakarta/graphql/SentrySpringSubscriptionHandler : io/sentry/graphql/SentrySubscriptionHandler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

import com.jakewharton.nopen.annotation.Open;
import io.sentry.SentryIntegrationPackageStorage;
import io.sentry.graphql.SentryGraphqlInstrumentation;
import io.sentry.graphql.SentryInstrumentation;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.graphql.GraphQlSourceBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
Expand All @@ -14,31 +17,38 @@
@Open
public class SentryGraphqlConfiguration {

@Bean
@Bean(name = "sentryInstrumentation")
@ConditionalOnMissingBean
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public GraphQlSourceBuilderCustomizer sourceBuilderCustomizerWebmvc() {
public SentryInstrumentation sentryInstrumentationWebMvc(
final @NotNull ObjectProvider<SentryGraphqlInstrumentation.BeforeSpanCallback>
beforeSpanCallback) {
SentryIntegrationPackageStorage.getInstance().addIntegration("Spring6GrahQLWebMVC");
return sourceBuilderCustomizer(false);
return createInstrumentation(beforeSpanCallback, false);
}

@Bean
@Bean(name = "sentryInstrumentation")
@ConditionalOnMissingBean
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
public GraphQlSourceBuilderCustomizer sourceBuilderCustomizerWebflux() {
public SentryInstrumentation sentryInstrumentationWebflux(
final @NotNull ObjectProvider<SentryGraphqlInstrumentation.BeforeSpanCallback>
beforeSpanCallback) {
SentryIntegrationPackageStorage.getInstance().addIntegration("Spring6GrahQLWebFlux");
return sourceBuilderCustomizer(true);
return createInstrumentation(beforeSpanCallback, true);
}

/**
* We're not setting defaultDataFetcherExceptionHandler here on purpose and instead use the
* resolver adapter below. This way Springs handler can still forward to other resolver adapters.
*/
private GraphQlSourceBuilderCustomizer sourceBuilderCustomizer(final boolean captureRequestBody) {
return (builder) ->
builder.configureGraphQl(
graphQlBuilder ->
graphQlBuilder.instrumentation(
new SentryInstrumentation(
null, new SentrySpringSubscriptionHandler(), captureRequestBody)));
private SentryInstrumentation createInstrumentation(
final @NotNull ObjectProvider<SentryGraphqlInstrumentation.BeforeSpanCallback>
beforeSpanCallback,
final boolean captureRequestBody) {
return new SentryInstrumentation(
beforeSpanCallback.getIfAvailable(),
new SentrySpringSubscriptionHandler(),
captureRequestBody);
}

@Bean
Expand Down
4 changes: 2 additions & 2 deletions sentry-spring/api/sentry-spring.api
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,8 @@ public class io/sentry/spring/graphql/SentryGraphqlConfiguration {
public fun <init> ()V
public fun exceptionResolverAdapter ()Lio/sentry/spring/graphql/SentryDataFetcherExceptionResolverAdapter;
public fun graphqlBeanPostProcessor ()Lio/sentry/spring/graphql/SentryGraphqlBeanPostProcessor;
public fun sourceBuilderCustomizerWebflux ()Lorg/springframework/boot/autoconfigure/graphql/GraphQlSourceBuilderCustomizer;
public fun sourceBuilderCustomizerWebmvc ()Lorg/springframework/boot/autoconfigure/graphql/GraphQlSourceBuilderCustomizer;
public fun sentryInstrumentationWebMvc (Lorg/springframework/beans/factory/ObjectProvider;)Lio/sentry/graphql/SentryInstrumentation;
public fun sentryInstrumentationWebflux (Lorg/springframework/beans/factory/ObjectProvider;)Lio/sentry/graphql/SentryInstrumentation;
}

public final class io/sentry/spring/graphql/SentrySpringSubscriptionHandler : io/sentry/graphql/SentrySubscriptionHandler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

import com.jakewharton.nopen.annotation.Open;
import io.sentry.SentryIntegrationPackageStorage;
import io.sentry.graphql.SentryGraphqlInstrumentation;
import io.sentry.graphql.SentryInstrumentation;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.graphql.GraphQlSourceBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
Expand All @@ -14,31 +17,38 @@
@Open
public class SentryGraphqlConfiguration {

@Bean
@Bean(name = "sentryInstrumentation")
@ConditionalOnMissingBean
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public GraphQlSourceBuilderCustomizer sourceBuilderCustomizerWebmvc() {
public SentryInstrumentation sentryInstrumentationWebMvc(
final @NotNull ObjectProvider<SentryGraphqlInstrumentation.BeforeSpanCallback>
beforeSpanCallback) {
SentryIntegrationPackageStorage.getInstance().addIntegration("Spring5GrahQLWebMVC");
return sourceBuilderCustomizer(false);
return createInstrumentation(beforeSpanCallback, false);
}

@Bean
@Bean(name = "sentryInstrumentation")
@ConditionalOnMissingBean
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
public GraphQlSourceBuilderCustomizer sourceBuilderCustomizerWebflux() {
public SentryInstrumentation sentryInstrumentationWebflux(
final @NotNull ObjectProvider<SentryGraphqlInstrumentation.BeforeSpanCallback>
beforeSpanCallback) {
SentryIntegrationPackageStorage.getInstance().addIntegration("Spring5GrahQLWebFlux");
return sourceBuilderCustomizer(true);
return createInstrumentation(beforeSpanCallback, true);
}

/**
* We're not setting defaultDataFetcherExceptionHandler here on purpose and instead use the
* resolver adapter below. This way Springs handler can still forward to other resolver adapters.
*/
private GraphQlSourceBuilderCustomizer sourceBuilderCustomizer(final boolean captureRequestBody) {
return (builder) ->
builder.configureGraphQl(
graphQlBuilder ->
graphQlBuilder.instrumentation(
new SentryInstrumentation(
null, new SentrySpringSubscriptionHandler(), captureRequestBody)));
private SentryInstrumentation createInstrumentation(
final @NotNull ObjectProvider<SentryGraphqlInstrumentation.BeforeSpanCallback>
beforeSpanCallback,
final boolean captureRequestBody) {
return new SentryInstrumentation(
beforeSpanCallback.getIfAvailable(),
new SentrySpringSubscriptionHandler(),
captureRequestBody);
}

@Bean
Expand Down
Loading