diff --git a/conventions/src/main/kotlin/io.opentelemetry.instrumentation.base.gradle.kts b/conventions/src/main/kotlin/io.opentelemetry.instrumentation.base.gradle.kts
index 01300ea7344f..95c3309afedd 100644
--- a/conventions/src/main/kotlin/io.opentelemetry.instrumentation.base.gradle.kts
+++ b/conventions/src/main/kotlin/io.opentelemetry.instrumentation.base.gradle.kts
@@ -34,17 +34,25 @@ extra["testLatestDeps"] = testLatestDeps
abstract class TestLatestDepsRule : ComponentMetadataRule {
override fun execute(context: ComponentMetadataContext) {
val version = context.details.id.version
- if (version.contains("-alpha", true) ||
- version.contains("-beta", true) ||
- version.contains("-rc", true) ||
- version.contains("-m", true) || // e.g. spring milestones are published to grails repo
- version.contains(".alpha", true) || // e.g. netty
- version.contains(".beta", true) || // e.g. hibernate
- version.contains(".cr", true) // e.g. hibernate
+ if (version.contains("-alpha", true)
+ || version.contains("-beta", true)
+ || version.contains("-rc", true)
+ || version.contains("-m", true) // e.g. spring milestones are published to grails repo
+ || version.contains(".alpha", true) // e.g. netty
+ || version.contains(".beta", true) // e.g. hibernate
+ || version.contains(".cr", true) // e.g. hibernate
+ || version.endsWith("-nf-execution") // graphql
+ || GIT_SHA_PATTERN.matches(version) // graphql
+ || DATETIME_PATTERN.matches(version) // graphql
) {
context.details.status = "milestone"
}
}
+
+ companion object {
+ private val GIT_SHA_PATTERN = Regex("^.*-[0-9a-f]{7,}$")
+ private val DATETIME_PATTERN = Regex("^\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}.*$")
+ }
}
configurations {
diff --git a/docs/supported-libraries.md b/docs/supported-libraries.md
index c7881b6a3a1f..5e080187caf3 100644
--- a/docs/supported-libraries.md
+++ b/docs/supported-libraries.md
@@ -64,7 +64,7 @@ These are the supported libraries and frameworks:
| [Geode Client](https://geode.apache.org/) | 1.4+ | N/A | [Database Client Spans] |
| [Google HTTP Client](https://github.com/googleapis/google-http-java-client) | 1.19+ | N/A | [HTTP Client Spans], [HTTP Client Metrics] |
| [Grails](https://grails.org/) | 3.0+ | N/A | Provides `http.route` [2], Controller Spans [3] |
-| [GraphQL Java](https://www.graphql-java.com/) | 12.0+ | [opentelemetry-graphql-java-12.0](../instrumentation/graphql-java-12.0/library) | [GraphQL Server Spans] |
+| [GraphQL Java](https://www.graphql-java.com/) | 12.0+ | [opentelemetry-graphql-java-12.0](../instrumentation/graphql-java/graphql-java-12.0/library),
[opentelemetry-graphql-java-20.0](../instrumentation/graphql-java/graphql-java-20.0/library) | [GraphQL Server Spans] |
| [gRPC](https://github.com/grpc/grpc-java) | 1.6+ | [opentelemetry-grpc-1.6](../instrumentation/grpc-1.6/library) | [RPC Client Spans], [RPC Client Metrics], [RPC Server Spans], [RPC Server Metrics] |
| [Guava ListenableFuture](https://guava.dev/releases/snapshot/api/docs/com/google/common/util/concurrent/ListenableFuture.html) | 10.0+ | [opentelemetry-guava-10.0](../instrumentation/guava-10.0/library) | Context propagation |
| [GWT](http://www.gwtproject.org/) | 2.0+ | N/A | [RPC Server Spans] |
@@ -76,7 +76,7 @@ These are the supported libraries and frameworks:
| [Java Executors](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html) | Java 8+ | N/A | Context propagation |
| [Java Http Client](https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/package-summary.html) | Java 11+ | [opentelemetry-java-http-client](../instrumentation/java-http-client/library) | [HTTP Client Spans], [HTTP Client Metrics] |
| [java.util.logging](https://docs.oracle.com/javase/8/docs/api/java/util/logging/package-summary.html) | Java 8+ | N/A | none |
-| [Java Platform](https://docs.oracle.com/javase/8/docs/api/java/lang/management/ManagementFactory.html) | Java 8+ | [opentelemetry-runtime-telemetry-java8](../instrumentation/runtime-telemetry/runtime-telemetry-java8/library),[opentelemetry-runtime-telemetry-java17](../instrumentation/runtime-telemetry/runtime-telemetry-java17/library),
[opentelemetry-resources](../instrumentation/resources/library) | [JVM Runtime Metrics] |
+| [Java Platform](https://docs.oracle.com/javase/8/docs/api/java/lang/management/ManagementFactory.html) | Java 8+ | [opentelemetry-runtime-telemetry-java8](../instrumentation/runtime-telemetry/runtime-telemetry-java8/library),
[opentelemetry-runtime-telemetry-java17](../instrumentation/runtime-telemetry/runtime-telemetry-java17/library),
[opentelemetry-resources](../instrumentation/resources/library) | [JVM Runtime Metrics] |
| [JAX-RS](https://javaee.github.io/javaee-spec/javadocs/javax/ws/rs/package-summary.html) | 0.5+ | N/A | Provides `http.route` [2], Controller Spans [3] |
| [JAX-RS Client](https://javaee.github.io/javaee-spec/javadocs/javax/ws/rs/client/package-summary.html) | 1.1+ | N/A | [HTTP Client Spans], [HTTP Client Metrics] |
| [JAX-WS](https://jakarta.ee/specifications/xml-web-services/2.3/apidocs/javax/xml/ws/package-summary.html) | 2.0+ (not including 3.x yet) | N/A | Provides `http.route` [2], Controller Spans [3] |
diff --git a/instrumentation/graphql-java-12.0/javaagent/build.gradle.kts b/instrumentation/graphql-java-12.0/javaagent/build.gradle.kts
deleted file mode 100644
index 699820cf67a6..000000000000
--- a/instrumentation/graphql-java-12.0/javaagent/build.gradle.kts
+++ /dev/null
@@ -1,21 +0,0 @@
-plugins {
- id("otel.javaagent-instrumentation")
-}
-
-muzzle {
- pass {
- group.set("com.graphql-java")
- module.set("graphql-java")
- versions.set("[12,)")
- skip("230521-nf-execution")
- assertInverse.set(true)
- }
-}
-
-dependencies {
- implementation(project(":instrumentation:graphql-java-12.0:library"))
-
- library("com.graphql-java:graphql-java:12.0")
-
- testImplementation(project(":instrumentation:graphql-java-12.0:testing"))
-}
diff --git a/instrumentation/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/GraphQLTelemetry.java b/instrumentation/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/GraphQLTelemetry.java
deleted file mode 100644
index 1f9b0eb47034..000000000000
--- a/instrumentation/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/GraphQLTelemetry.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.instrumentation.graphql.v12_0;
-
-import graphql.ExecutionResult;
-import graphql.execution.instrumentation.Instrumentation;
-import graphql.execution.instrumentation.parameters.InstrumentationExecutionParameters;
-import io.opentelemetry.api.OpenTelemetry;
-import io.opentelemetry.api.trace.StatusCode;
-import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
-import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
-import io.opentelemetry.instrumentation.api.instrumenter.SpanStatusExtractor;
-
-@SuppressWarnings("AbbreviationAsWordInName")
-public final class GraphQLTelemetry {
- private static final String INSTRUMENTATION_NAME = "io.opentelemetry.graphql-java-12.0";
-
- /** Returns a new {@link GraphQLTelemetry} configured with the given {@link OpenTelemetry}. */
- public static GraphQLTelemetry create(OpenTelemetry openTelemetry) {
- return builder(openTelemetry).build();
- }
-
- /**
- * Returns a new {@link GraphQLTelemetryBuilder} configured with the given {@link OpenTelemetry}.
- */
- public static GraphQLTelemetryBuilder builder(OpenTelemetry openTelemetry) {
- return new GraphQLTelemetryBuilder(openTelemetry);
- }
-
- private final Instrumenter instrumenter;
- private final boolean sanitizeQuery;
-
- GraphQLTelemetry(OpenTelemetry openTelemetry, boolean sanitizeQuery) {
- InstrumenterBuilder builder =
- Instrumenter.builder(
- openTelemetry, INSTRUMENTATION_NAME, ignored -> "GraphQL Operation")
- .setSpanStatusExtractor(
- (spanStatusBuilder, instrumentationExecutionParameters, executionResult, error) -> {
- if (!executionResult.getErrors().isEmpty()) {
- spanStatusBuilder.setStatus(StatusCode.ERROR);
- } else {
- SpanStatusExtractor.getDefault()
- .extract(
- spanStatusBuilder,
- instrumentationExecutionParameters,
- executionResult,
- error);
- }
- });
- builder.addAttributesExtractor(new GraphqlAttributesExtractor());
-
- this.instrumenter = builder.buildInstrumenter();
- this.sanitizeQuery = sanitizeQuery;
- }
-
- /**
- * Returns a new {@link Instrumentation} that generates telemetry for received GraphQL requests.
- */
- public Instrumentation newInstrumentation() {
- return new OpenTelemetryInstrumentation(instrumenter, sanitizeQuery);
- }
-}
diff --git a/instrumentation/graphql-java-12.0/javaagent/README.md b/instrumentation/graphql-java/README.md
similarity index 100%
rename from instrumentation/graphql-java-12.0/javaagent/README.md
rename to instrumentation/graphql-java/README.md
diff --git a/instrumentation/graphql-java/graphql-java-12.0/javaagent/build.gradle.kts b/instrumentation/graphql-java/graphql-java-12.0/javaagent/build.gradle.kts
new file mode 100644
index 000000000000..c7e0cff0920a
--- /dev/null
+++ b/instrumentation/graphql-java/graphql-java-12.0/javaagent/build.gradle.kts
@@ -0,0 +1,26 @@
+plugins {
+ id("otel.javaagent-instrumentation")
+}
+
+muzzle {
+ pass {
+ group.set("com.graphql-java")
+ module.set("graphql-java")
+ versions.set("[12,20)")
+ skip("230521-nf-execution")
+ assertInverse.set(true)
+ }
+}
+
+dependencies {
+ implementation(project(":instrumentation:graphql-java:graphql-java-12.0:library"))
+ implementation(project(":instrumentation:graphql-java:graphql-java-common:library"))
+
+ library("com.graphql-java:graphql-java:12.0")
+
+ testInstrumentation(project(":instrumentation:graphql-java:graphql-java-20.0:javaagent"))
+
+ testImplementation(project(":instrumentation:graphql-java:graphql-java-common:testing"))
+
+ latestDepTestLibrary("com.graphql-java:graphql-java:19.+")
+}
diff --git a/instrumentation/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlInstrumentation.java b/instrumentation/graphql-java/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlInstrumentation.java
similarity index 95%
rename from instrumentation/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlInstrumentation.java
rename to instrumentation/graphql-java/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlInstrumentation.java
index 70f13a49f656..543efefaab08 100644
--- a/instrumentation/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlInstrumentation.java
+++ b/instrumentation/graphql-java/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlInstrumentation.java
@@ -17,7 +17,7 @@
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
-public class GraphqlInstrumentation implements TypeInstrumentation {
+class GraphqlInstrumentation implements TypeInstrumentation {
@Override
public ElementMatcher typeMatcher() {
diff --git a/instrumentation/graphql-java/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlInstrumentationModule.java b/instrumentation/graphql-java/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlInstrumentationModule.java
new file mode 100644
index 000000000000..1df81f84334d
--- /dev/null
+++ b/instrumentation/graphql-java/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlInstrumentationModule.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.graphql.v12_0;
+
+import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
+import static net.bytebuddy.matcher.ElementMatchers.not;
+
+import com.google.auto.service.AutoService;
+import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
+import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
+import java.util.Collections;
+import java.util.List;
+import net.bytebuddy.matcher.ElementMatcher;
+
+@SuppressWarnings("unused")
+@AutoService(InstrumentationModule.class)
+public class GraphqlInstrumentationModule extends InstrumentationModule {
+
+ public GraphqlInstrumentationModule() {
+ super("graphql-java", "graphql-java-12.0");
+ }
+
+ @Override
+ public ElementMatcher.Junction classLoaderMatcher() {
+ // added in 20.0
+ return not(
+ hasClassesNamed("graphql.execution.instrumentation.SimplePerformantInstrumentation"));
+ }
+
+ @Override
+ public List typeInstrumentations() {
+ return Collections.singletonList(new GraphqlInstrumentation());
+ }
+}
diff --git a/instrumentation/graphql-java/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlSingletons.java b/instrumentation/graphql-java/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlSingletons.java
new file mode 100644
index 000000000000..41c64c6a6cc3
--- /dev/null
+++ b/instrumentation/graphql-java/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlSingletons.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.graphql.v12_0;
+
+import graphql.execution.instrumentation.Instrumentation;
+import io.opentelemetry.api.GlobalOpenTelemetry;
+import io.opentelemetry.instrumentation.graphql.internal.InstrumentationUtil;
+import io.opentelemetry.instrumentation.graphql.v12_0.GraphQLTelemetry;
+import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig;
+
+public final class GraphqlSingletons {
+
+ private static final boolean QUERY_SANITIZATION_ENABLED =
+ InstrumentationConfig.get()
+ .getBoolean("otel.instrumentation.graphql.query-sanitizer.enabled", true);
+
+ private static final GraphQLTelemetry TELEMETRY =
+ GraphQLTelemetry.builder(GlobalOpenTelemetry.get())
+ .setSanitizeQuery(QUERY_SANITIZATION_ENABLED)
+ .build();
+
+ private GraphqlSingletons() {}
+
+ public static Instrumentation addInstrumentation(Instrumentation instrumentation) {
+ Instrumentation ourInstrumentation = TELEMETRY.newInstrumentation();
+ return InstrumentationUtil.addInstrumentation(instrumentation, ourInstrumentation);
+ }
+}
diff --git a/instrumentation/graphql-java-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlTest.java b/instrumentation/graphql-java/graphql-java-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlTest.java
similarity index 100%
rename from instrumentation/graphql-java-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlTest.java
rename to instrumentation/graphql-java/graphql-java-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlTest.java
diff --git a/instrumentation/graphql-java-12.0/library/README.md b/instrumentation/graphql-java/graphql-java-12.0/library/README.md
similarity index 94%
rename from instrumentation/graphql-java-12.0/library/README.md
rename to instrumentation/graphql-java/graphql-java-12.0/library/README.md
index 40ef49479d3c..447473d1df20 100644
--- a/instrumentation/graphql-java-12.0/library/README.md
+++ b/instrumentation/graphql-java/graphql-java-12.0/library/README.md
@@ -1,4 +1,4 @@
-# Library Instrumentation for GraphQL Java version 12.0 and higher
+# Library Instrumentation for GraphQL Java version 12.0 to 20.0
Provides OpenTelemetry instrumentation for [GraphQL Java](https://www.graphql-java.com/).
diff --git a/instrumentation/graphql-java/graphql-java-12.0/library/build.gradle.kts b/instrumentation/graphql-java/graphql-java-12.0/library/build.gradle.kts
new file mode 100644
index 000000000000..1387dfbacf6c
--- /dev/null
+++ b/instrumentation/graphql-java/graphql-java-12.0/library/build.gradle.kts
@@ -0,0 +1,10 @@
+plugins {
+ id("otel.library-instrumentation")
+}
+
+dependencies {
+ library("com.graphql-java:graphql-java:12.0")
+ implementation(project(":instrumentation:graphql-java:graphql-java-common:library"))
+
+ testImplementation(project(":instrumentation:graphql-java:graphql-java-common:testing"))
+}
diff --git a/instrumentation/graphql-java/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/GraphQLTelemetry.java b/instrumentation/graphql-java/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/GraphQLTelemetry.java
new file mode 100644
index 000000000000..4671cce91cfb
--- /dev/null
+++ b/instrumentation/graphql-java/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/GraphQLTelemetry.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.graphql.v12_0;
+
+import graphql.execution.instrumentation.Instrumentation;
+import io.opentelemetry.api.OpenTelemetry;
+import io.opentelemetry.instrumentation.graphql.internal.OpenTelemetryInstrumentationHelper;
+
+@SuppressWarnings("AbbreviationAsWordInName")
+public final class GraphQLTelemetry {
+ private static final String INSTRUMENTATION_NAME = "io.opentelemetry.graphql-java-12.0";
+
+ /** Returns a new {@link GraphQLTelemetry} configured with the given {@link OpenTelemetry}. */
+ public static GraphQLTelemetry create(OpenTelemetry openTelemetry) {
+ return builder(openTelemetry).build();
+ }
+
+ /**
+ * Returns a new {@link GraphQLTelemetryBuilder} configured with the given {@link OpenTelemetry}.
+ */
+ public static GraphQLTelemetryBuilder builder(OpenTelemetry openTelemetry) {
+ return new GraphQLTelemetryBuilder(openTelemetry);
+ }
+
+ private final OpenTelemetryInstrumentationHelper helper;
+
+ GraphQLTelemetry(OpenTelemetry openTelemetry, boolean sanitizeQuery) {
+ helper =
+ OpenTelemetryInstrumentationHelper.create(
+ openTelemetry, INSTRUMENTATION_NAME, sanitizeQuery);
+ }
+
+ /**
+ * Returns a new {@link Instrumentation} that generates telemetry for received GraphQL requests.
+ */
+ public Instrumentation newInstrumentation() {
+ return new OpenTelemetryInstrumentation(helper);
+ }
+}
diff --git a/instrumentation/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/GraphQLTelemetryBuilder.java b/instrumentation/graphql-java/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/GraphQLTelemetryBuilder.java
similarity index 100%
rename from instrumentation/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/GraphQLTelemetryBuilder.java
rename to instrumentation/graphql-java/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/GraphQLTelemetryBuilder.java
diff --git a/instrumentation/graphql-java/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/OpenTelemetryInstrumentation.java b/instrumentation/graphql-java/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/OpenTelemetryInstrumentation.java
new file mode 100644
index 000000000000..01a784a96c17
--- /dev/null
+++ b/instrumentation/graphql-java/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/OpenTelemetryInstrumentation.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.graphql.v12_0;
+
+import graphql.ExecutionResult;
+import graphql.execution.instrumentation.InstrumentationContext;
+import graphql.execution.instrumentation.InstrumentationState;
+import graphql.execution.instrumentation.SimpleInstrumentation;
+import graphql.execution.instrumentation.parameters.InstrumentationExecuteOperationParameters;
+import graphql.execution.instrumentation.parameters.InstrumentationExecutionParameters;
+import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters;
+import graphql.schema.DataFetcher;
+import io.opentelemetry.instrumentation.graphql.internal.OpenTelemetryInstrumentationHelper;
+import io.opentelemetry.instrumentation.graphql.internal.OpenTelemetryInstrumentationState;
+
+final class OpenTelemetryInstrumentation extends SimpleInstrumentation {
+ private final OpenTelemetryInstrumentationHelper helper;
+
+ OpenTelemetryInstrumentation(OpenTelemetryInstrumentationHelper helper) {
+ this.helper = helper;
+ }
+
+ @Override
+ public InstrumentationState createState() {
+ return new OpenTelemetryInstrumentationState();
+ }
+
+ @Override
+ public InstrumentationContext beginExecution(
+ InstrumentationExecutionParameters parameters) {
+ OpenTelemetryInstrumentationState state = parameters.getInstrumentationState();
+ return helper.beginExecution(state);
+ }
+
+ @Override
+ public InstrumentationContext beginExecuteOperation(
+ InstrumentationExecuteOperationParameters parameters) {
+ OpenTelemetryInstrumentationState state = parameters.getInstrumentationState();
+ return helper.beginExecuteOperation(parameters, state);
+ }
+
+ @Override
+ public DataFetcher> instrumentDataFetcher(
+ DataFetcher> dataFetcher, InstrumentationFieldFetchParameters parameters) {
+ OpenTelemetryInstrumentationState state = parameters.getInstrumentationState();
+ return helper.instrumentDataFetcher(dataFetcher, state);
+ }
+}
diff --git a/instrumentation/graphql-java-12.0/library/src/test/java/io/opentelemetry/instrumentation/graphql/v12_0/GraphqlTest.java b/instrumentation/graphql-java/graphql-java-12.0/library/src/test/java/io/opentelemetry/instrumentation/graphql/v12_0/GraphqlTest.java
similarity index 100%
rename from instrumentation/graphql-java-12.0/library/src/test/java/io/opentelemetry/instrumentation/graphql/v12_0/GraphqlTest.java
rename to instrumentation/graphql-java/graphql-java-12.0/library/src/test/java/io/opentelemetry/instrumentation/graphql/v12_0/GraphqlTest.java
diff --git a/instrumentation/graphql-java/graphql-java-20.0/javaagent/build.gradle.kts b/instrumentation/graphql-java/graphql-java-20.0/javaagent/build.gradle.kts
new file mode 100644
index 000000000000..72b8aa95c2f7
--- /dev/null
+++ b/instrumentation/graphql-java/graphql-java-20.0/javaagent/build.gradle.kts
@@ -0,0 +1,24 @@
+plugins {
+ id("otel.javaagent-instrumentation")
+}
+
+muzzle {
+ pass {
+ group.set("com.graphql-java")
+ module.set("graphql-java")
+ versions.set("[20,)")
+ skip("230521-nf-execution")
+ assertInverse.set(true)
+ }
+}
+
+dependencies {
+ implementation(project(":instrumentation:graphql-java:graphql-java-20.0:library"))
+ implementation(project(":instrumentation:graphql-java:graphql-java-common:library"))
+
+ library("com.graphql-java:graphql-java:20.0")
+
+ testInstrumentation(project(":instrumentation:graphql-java:graphql-java-12.0:javaagent"))
+
+ testImplementation(project(":instrumentation:graphql-java:graphql-java-common:testing"))
+}
diff --git a/instrumentation/graphql-java/graphql-java-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlInstrumentation.java b/instrumentation/graphql-java/graphql-java-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlInstrumentation.java
new file mode 100644
index 000000000000..543efefaab08
--- /dev/null
+++ b/instrumentation/graphql-java/graphql-java-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlInstrumentation.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.graphql.v12_0;
+
+import static io.opentelemetry.javaagent.instrumentation.graphql.v12_0.GraphqlSingletons.addInstrumentation;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
+import static net.bytebuddy.matcher.ElementMatchers.returns;
+
+import graphql.execution.instrumentation.Instrumentation;
+import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
+import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
+import net.bytebuddy.asm.Advice;
+import net.bytebuddy.description.type.TypeDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+
+class GraphqlInstrumentation implements TypeInstrumentation {
+
+ @Override
+ public ElementMatcher typeMatcher() {
+ return named("graphql.GraphQL");
+ }
+
+ @Override
+ public void transform(TypeTransformer transformer) {
+ transformer.applyAdviceToMethod(
+ namedOneOf("checkInstrumentationDefaultState", "checkInstrumentation")
+ .and(returns(named("graphql.execution.instrumentation.Instrumentation"))),
+ this.getClass().getName() + "$AddInstrumentationAdvice");
+ }
+
+ @SuppressWarnings("unused")
+ public static class AddInstrumentationAdvice {
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ public static void onExit(@Advice.Return(readOnly = false) Instrumentation instrumentation) {
+ instrumentation = addInstrumentation(instrumentation);
+ }
+ }
+}
diff --git a/instrumentation/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlInstrumentationModule.java b/instrumentation/graphql-java/graphql-java-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlInstrumentationModule.java
similarity index 100%
rename from instrumentation/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlInstrumentationModule.java
rename to instrumentation/graphql-java/graphql-java-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlInstrumentationModule.java
diff --git a/instrumentation/graphql-java/graphql-java-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlSingletons.java b/instrumentation/graphql-java/graphql-java-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlSingletons.java
new file mode 100644
index 000000000000..f608b03932e2
--- /dev/null
+++ b/instrumentation/graphql-java/graphql-java-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlSingletons.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.graphql.v12_0;
+
+import graphql.execution.instrumentation.Instrumentation;
+import io.opentelemetry.api.GlobalOpenTelemetry;
+import io.opentelemetry.instrumentation.graphql.internal.InstrumentationUtil;
+import io.opentelemetry.instrumentation.graphql.v20_0.GraphQLTelemetry;
+import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig;
+
+public final class GraphqlSingletons {
+
+ private static final boolean QUERY_SANITIZATION_ENABLED =
+ InstrumentationConfig.get()
+ .getBoolean("otel.instrumentation.graphql.query-sanitizer.enabled", true);
+
+ private static final GraphQLTelemetry TELEMETRY =
+ GraphQLTelemetry.builder(GlobalOpenTelemetry.get())
+ .setSanitizeQuery(QUERY_SANITIZATION_ENABLED)
+ .build();
+
+ private GraphqlSingletons() {}
+
+ public static Instrumentation addInstrumentation(Instrumentation instrumentation) {
+ Instrumentation ourInstrumentation = TELEMETRY.newInstrumentation();
+ return InstrumentationUtil.addInstrumentation(instrumentation, ourInstrumentation);
+ }
+}
diff --git a/instrumentation/graphql-java/graphql-java-20.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlTest.java b/instrumentation/graphql-java/graphql-java-20.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlTest.java
new file mode 100644
index 000000000000..f960ec7c4726
--- /dev/null
+++ b/instrumentation/graphql-java/graphql-java-20.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlTest.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.graphql.v12_0;
+
+import graphql.GraphQL;
+import io.opentelemetry.instrumentation.graphql.AbstractGraphqlTest;
+import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+public class GraphqlTest extends AbstractGraphqlTest {
+
+ @RegisterExtension
+ private static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
+
+ @Override
+ protected InstrumentationExtension getTesting() {
+ return testing;
+ }
+
+ @Override
+ protected void configure(GraphQL.Builder builder) {}
+}
diff --git a/instrumentation/graphql-java/graphql-java-20.0/library/README.md b/instrumentation/graphql-java/graphql-java-20.0/library/README.md
new file mode 100644
index 000000000000..2482e76ee8d9
--- /dev/null
+++ b/instrumentation/graphql-java/graphql-java-20.0/library/README.md
@@ -0,0 +1,40 @@
+# Library Instrumentation for GraphQL Java version 20.0 and higher
+
+Provides OpenTelemetry instrumentation for [GraphQL Java](https://www.graphql-java.com/).
+
+## Quickstart
+
+### Add these dependencies to your project
+
+Replace `OPENTELEMETRY_VERSION` with the [latest
+release](https://search.maven.org/search?q=g:io.opentelemetry.instrumentation%20AND%20a:opentelemetry-graphql-java-12.0).
+
+For Maven, add to your `pom.xml` dependencies:
+
+```xml
+
+
+ io.opentelemetry.instrumentation
+ opentelemetry-graphql-java-20.0
+ OPENTELEMETRY_VERSION
+
+
+```
+
+For Gradle, add to your dependencies:
+
+```groovy
+implementation("io.opentelemetry.instrumentation:opentelemetry-graphql-java-20.0:OPENTELEMETRY_VERSION")
+```
+
+### Usage
+
+The instrumentation library provides a GraphQL Java `Instrumentation` implementation that can be
+added to an instance of the `GraphQL` to provide OpenTelemetry-based spans.
+
+```java
+void configure(OpenTelemetry openTelemetry, GraphQL.Builder builder) {
+ GraphQLTelemetry telemetry = GraphQLTelemetry.builder(openTelemetry).build();
+ builder.instrumentation(telemetry.newInstrumentation());
+}
+```
diff --git a/instrumentation/graphql-java/graphql-java-20.0/library/build.gradle.kts b/instrumentation/graphql-java/graphql-java-20.0/library/build.gradle.kts
new file mode 100644
index 000000000000..6537286f62c2
--- /dev/null
+++ b/instrumentation/graphql-java/graphql-java-20.0/library/build.gradle.kts
@@ -0,0 +1,10 @@
+plugins {
+ id("otel.library-instrumentation")
+}
+
+dependencies {
+ library("com.graphql-java:graphql-java:20.0")
+ implementation(project(":instrumentation:graphql-java:graphql-java-common:library"))
+
+ testImplementation(project(":instrumentation:graphql-java:graphql-java-common:testing"))
+}
diff --git a/instrumentation/graphql-java/graphql-java-20.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v20_0/GraphQLTelemetry.java b/instrumentation/graphql-java/graphql-java-20.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v20_0/GraphQLTelemetry.java
new file mode 100644
index 000000000000..761a54e55ceb
--- /dev/null
+++ b/instrumentation/graphql-java/graphql-java-20.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v20_0/GraphQLTelemetry.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.graphql.v20_0;
+
+import graphql.execution.instrumentation.Instrumentation;
+import io.opentelemetry.api.OpenTelemetry;
+import io.opentelemetry.instrumentation.graphql.internal.OpenTelemetryInstrumentationHelper;
+
+@SuppressWarnings("AbbreviationAsWordInName")
+public final class GraphQLTelemetry {
+ private static final String INSTRUMENTATION_NAME = "io.opentelemetry.graphql-java-20.0";
+
+ /** Returns a new {@link GraphQLTelemetry} configured with the given {@link OpenTelemetry}. */
+ public static GraphQLTelemetry create(OpenTelemetry openTelemetry) {
+ return builder(openTelemetry).build();
+ }
+
+ /**
+ * Returns a new {@link GraphQLTelemetryBuilder} configured with the given {@link OpenTelemetry}.
+ */
+ public static GraphQLTelemetryBuilder builder(OpenTelemetry openTelemetry) {
+ return new GraphQLTelemetryBuilder(openTelemetry);
+ }
+
+ private final OpenTelemetryInstrumentationHelper helper;
+
+ GraphQLTelemetry(OpenTelemetry openTelemetry, boolean sanitizeQuery) {
+ helper =
+ OpenTelemetryInstrumentationHelper.create(
+ openTelemetry, INSTRUMENTATION_NAME, sanitizeQuery);
+ }
+
+ /**
+ * Returns a new {@link Instrumentation} that generates telemetry for received GraphQL requests.
+ */
+ public Instrumentation newInstrumentation() {
+ return new OpenTelemetryInstrumentation(helper);
+ }
+}
diff --git a/instrumentation/graphql-java/graphql-java-20.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v20_0/GraphQLTelemetryBuilder.java b/instrumentation/graphql-java/graphql-java-20.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v20_0/GraphQLTelemetryBuilder.java
new file mode 100644
index 000000000000..24c9c9b63e99
--- /dev/null
+++ b/instrumentation/graphql-java/graphql-java-20.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v20_0/GraphQLTelemetryBuilder.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.graphql.v20_0;
+
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import io.opentelemetry.api.OpenTelemetry;
+
+/** A builder of {@link GraphQLTelemetry}. */
+@SuppressWarnings("AbbreviationAsWordInName")
+public final class GraphQLTelemetryBuilder {
+
+ private final OpenTelemetry openTelemetry;
+
+ private boolean sanitizeQuery = true;
+
+ GraphQLTelemetryBuilder(OpenTelemetry openTelemetry) {
+ this.openTelemetry = openTelemetry;
+ }
+
+ /** Sets whether sensitive information should be removed from queries. Default is {@code true}. */
+ @CanIgnoreReturnValue
+ public GraphQLTelemetryBuilder setSanitizeQuery(boolean sanitizeQuery) {
+ this.sanitizeQuery = sanitizeQuery;
+ return this;
+ }
+
+ /**
+ * Returns a new {@link GraphQLTelemetry} with the settings of this {@link
+ * GraphQLTelemetryBuilder}.
+ */
+ public GraphQLTelemetry build() {
+ return new GraphQLTelemetry(openTelemetry, sanitizeQuery);
+ }
+}
diff --git a/instrumentation/graphql-java/graphql-java-20.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v20_0/OpenTelemetryInstrumentation.java b/instrumentation/graphql-java/graphql-java-20.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v20_0/OpenTelemetryInstrumentation.java
new file mode 100644
index 000000000000..965a61e5a8f0
--- /dev/null
+++ b/instrumentation/graphql-java/graphql-java-20.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v20_0/OpenTelemetryInstrumentation.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.graphql.v20_0;
+
+import static graphql.execution.instrumentation.InstrumentationState.ofState;
+
+import graphql.ExecutionResult;
+import graphql.execution.instrumentation.InstrumentationContext;
+import graphql.execution.instrumentation.InstrumentationState;
+import graphql.execution.instrumentation.SimplePerformantInstrumentation;
+import graphql.execution.instrumentation.parameters.InstrumentationCreateStateParameters;
+import graphql.execution.instrumentation.parameters.InstrumentationExecuteOperationParameters;
+import graphql.execution.instrumentation.parameters.InstrumentationExecutionParameters;
+import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters;
+import graphql.schema.DataFetcher;
+import io.opentelemetry.instrumentation.graphql.internal.OpenTelemetryInstrumentationHelper;
+import io.opentelemetry.instrumentation.graphql.internal.OpenTelemetryInstrumentationState;
+
+final class OpenTelemetryInstrumentation extends SimplePerformantInstrumentation {
+ private final OpenTelemetryInstrumentationHelper helper;
+
+ OpenTelemetryInstrumentation(OpenTelemetryInstrumentationHelper helper) {
+ this.helper = helper;
+ }
+
+ @Override
+ public InstrumentationState createState(InstrumentationCreateStateParameters parameters) {
+ return new OpenTelemetryInstrumentationState();
+ }
+
+ @Override
+ public InstrumentationContext beginExecution(
+ InstrumentationExecutionParameters parameters, InstrumentationState rawState) {
+ OpenTelemetryInstrumentationState state = ofState(rawState);
+ return helper.beginExecution(state);
+ }
+
+ @Override
+ public InstrumentationContext beginExecuteOperation(
+ InstrumentationExecuteOperationParameters parameters, InstrumentationState rawState) {
+ OpenTelemetryInstrumentationState state = ofState(rawState);
+ return helper.beginExecuteOperation(parameters, state);
+ }
+
+ @Override
+ public DataFetcher> instrumentDataFetcher(
+ DataFetcher> dataFetcher,
+ InstrumentationFieldFetchParameters parameters,
+ InstrumentationState rawState) {
+ OpenTelemetryInstrumentationState state = ofState(rawState);
+ return helper.instrumentDataFetcher(dataFetcher, state);
+ }
+}
diff --git a/instrumentation/graphql-java/graphql-java-20.0/library/src/test/java/io/opentelemetry/instrumentation/graphql/v20_0/GraphqlTest.java b/instrumentation/graphql-java/graphql-java-20.0/library/src/test/java/io/opentelemetry/instrumentation/graphql/v20_0/GraphqlTest.java
new file mode 100644
index 000000000000..4c7ee40b9f9a
--- /dev/null
+++ b/instrumentation/graphql-java/graphql-java-20.0/library/src/test/java/io/opentelemetry/instrumentation/graphql/v20_0/GraphqlTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.graphql.v20_0;
+
+import graphql.GraphQL;
+import io.opentelemetry.instrumentation.graphql.AbstractGraphqlTest;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+public class GraphqlTest extends AbstractGraphqlTest {
+
+ @RegisterExtension
+ private static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
+
+ @Override
+ protected InstrumentationExtension getTesting() {
+ return testing;
+ }
+
+ @Override
+ protected void configure(GraphQL.Builder builder) {
+ GraphQLTelemetry telemetry = GraphQLTelemetry.builder(testing.getOpenTelemetry()).build();
+ builder.instrumentation(telemetry.newInstrumentation());
+ }
+}
diff --git a/instrumentation/graphql-java/graphql-java-common/javaagent/build.gradle.kts b/instrumentation/graphql-java/graphql-java-common/javaagent/build.gradle.kts
new file mode 100644
index 000000000000..09b7a2ee7f2f
--- /dev/null
+++ b/instrumentation/graphql-java/graphql-java-common/javaagent/build.gradle.kts
@@ -0,0 +1,9 @@
+plugins {
+ id("otel.javaagent-instrumentation")
+}
+
+dependencies {
+ implementation(project(":instrumentation:graphql-java:graphql-java-common:library"))
+
+ library("com.graphql-java:graphql-java:12.0")
+}
diff --git a/instrumentation/graphql-java-12.0/library/build.gradle.kts b/instrumentation/graphql-java/graphql-java-common/library/build.gradle.kts
similarity index 59%
rename from instrumentation/graphql-java-12.0/library/build.gradle.kts
rename to instrumentation/graphql-java/graphql-java-common/library/build.gradle.kts
index 5674a1bdb25b..9e5a30f72f68 100644
--- a/instrumentation/graphql-java-12.0/library/build.gradle.kts
+++ b/instrumentation/graphql-java/graphql-java-common/library/build.gradle.kts
@@ -4,6 +4,4 @@ plugins {
dependencies {
library("com.graphql-java:graphql-java:12.0")
-
- testImplementation(project(":instrumentation:graphql-java-12.0:testing"))
}
diff --git a/instrumentation/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/GraphqlAttributesExtractor.java b/instrumentation/graphql-java/graphql-java-common/library/src/main/java/io/opentelemetry/instrumentation/graphql/internal/GraphqlAttributesExtractor.java
similarity index 63%
rename from instrumentation/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/GraphqlAttributesExtractor.java
rename to instrumentation/graphql-java/graphql-java-common/library/src/main/java/io/opentelemetry/instrumentation/graphql/internal/GraphqlAttributesExtractor.java
index 952f10c5f339..3b7cdc735283 100644
--- a/instrumentation/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/GraphqlAttributesExtractor.java
+++ b/instrumentation/graphql-java/graphql-java-common/library/src/main/java/io/opentelemetry/instrumentation/graphql/internal/GraphqlAttributesExtractor.java
@@ -3,10 +3,9 @@
* SPDX-License-Identifier: Apache-2.0
*/
-package io.opentelemetry.instrumentation.graphql.v12_0;
+package io.opentelemetry.instrumentation.graphql.internal;
import graphql.ExecutionResult;
-import graphql.execution.instrumentation.parameters.InstrumentationExecutionParameters;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.context.Context;
@@ -14,8 +13,12 @@
import java.util.Locale;
import javax.annotation.Nullable;
+/**
+ * This class is internal and is hence not for public use. Its APIs are unstable and can change at
+ * any time.
+ */
final class GraphqlAttributesExtractor
- implements AttributesExtractor {
+ implements AttributesExtractor {
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/database/graphql.md
private static final AttributeKey OPERATION_NAME =
AttributeKey.stringKey("graphql.operation.name");
@@ -28,20 +31,19 @@ final class GraphqlAttributesExtractor
public void onStart(
AttributesBuilder attributes,
Context parentContext,
- InstrumentationExecutionParameters request) {}
+ OpenTelemetryInstrumentationState request) {}
@Override
public void onEnd(
AttributesBuilder attributes,
Context context,
- InstrumentationExecutionParameters request,
+ OpenTelemetryInstrumentationState request,
@Nullable ExecutionResult response,
@Nullable Throwable error) {
- OpenTelemetryInstrumentationState state = request.getInstrumentationState();
- attributes.put(OPERATION_NAME, state.getOperationName());
- if (state.getOperation() != null) {
- attributes.put(OPERATION_TYPE, state.getOperation().name().toLowerCase(Locale.ROOT));
+ attributes.put(OPERATION_NAME, request.getOperationName());
+ if (request.getOperation() != null) {
+ attributes.put(OPERATION_TYPE, request.getOperation().name().toLowerCase(Locale.ROOT));
}
- attributes.put(GRAPHQL_DOCUMENT, state.getQuery());
+ attributes.put(GRAPHQL_DOCUMENT, request.getQuery());
}
}
diff --git a/instrumentation/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlSingletons.java b/instrumentation/graphql-java/graphql-java-common/library/src/main/java/io/opentelemetry/instrumentation/graphql/internal/InstrumentationUtil.java
similarity index 54%
rename from instrumentation/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlSingletons.java
rename to instrumentation/graphql-java/graphql-java-common/library/src/main/java/io/opentelemetry/instrumentation/graphql/internal/InstrumentationUtil.java
index 74beb880b454..572b166d2969 100644
--- a/instrumentation/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlSingletons.java
+++ b/instrumentation/graphql-java/graphql-java-common/library/src/main/java/io/opentelemetry/instrumentation/graphql/internal/InstrumentationUtil.java
@@ -3,31 +3,21 @@
* SPDX-License-Identifier: Apache-2.0
*/
-package io.opentelemetry.javaagent.instrumentation.graphql.v12_0;
+package io.opentelemetry.instrumentation.graphql.internal;
import graphql.execution.instrumentation.ChainedInstrumentation;
import graphql.execution.instrumentation.Instrumentation;
-import io.opentelemetry.api.GlobalOpenTelemetry;
-import io.opentelemetry.instrumentation.graphql.v12_0.GraphQLTelemetry;
-import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig;
import java.util.ArrayList;
import java.util.List;
-public final class GraphqlSingletons {
-
- private static final boolean QUERY_SANITIZATION_ENABLED =
- InstrumentationConfig.get()
- .getBoolean("otel.instrumentation.graphql.query-sanitizer.enabled", true);
-
- private static final GraphQLTelemetry TELEMETRY =
- GraphQLTelemetry.builder(GlobalOpenTelemetry.get())
- .setSanitizeQuery(QUERY_SANITIZATION_ENABLED)
- .build();
-
- private GraphqlSingletons() {}
+/**
+ * This class is internal and is hence not for public use. Its APIs are unstable and can change at
+ * any time.
+ */
+public final class InstrumentationUtil {
- public static Instrumentation addInstrumentation(Instrumentation instrumentation) {
- Instrumentation ourInstrumentation = TELEMETRY.newInstrumentation();
+ public static Instrumentation addInstrumentation(
+ Instrumentation instrumentation, Instrumentation ourInstrumentation) {
if (instrumentation == null) {
return ourInstrumentation;
}
@@ -47,4 +37,6 @@ public static Instrumentation addInstrumentation(Instrumentation instrumentation
}
return new ChainedInstrumentation(instrumentationList);
}
+
+ private InstrumentationUtil() {}
}
diff --git a/instrumentation/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/OpenTelemetryInstrumentation.java b/instrumentation/graphql-java/graphql-java-common/library/src/main/java/io/opentelemetry/instrumentation/graphql/internal/OpenTelemetryInstrumentationHelper.java
similarity index 65%
rename from instrumentation/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/OpenTelemetryInstrumentation.java
rename to instrumentation/graphql-java/graphql-java-common/library/src/main/java/io/opentelemetry/instrumentation/graphql/internal/OpenTelemetryInstrumentationHelper.java
index e93748551b04..46b66fd72ca1 100644
--- a/instrumentation/graphql-java-12.0/library/src/main/java/io/opentelemetry/instrumentation/graphql/v12_0/OpenTelemetryInstrumentation.java
+++ b/instrumentation/graphql-java/graphql-java-common/library/src/main/java/io/opentelemetry/instrumentation/graphql/internal/OpenTelemetryInstrumentationHelper.java
@@ -3,17 +3,13 @@
* SPDX-License-Identifier: Apache-2.0
*/
-package io.opentelemetry.instrumentation.graphql.v12_0;
+package io.opentelemetry.instrumentation.graphql.internal;
import graphql.ExecutionResult;
import graphql.GraphQLError;
import graphql.execution.instrumentation.InstrumentationContext;
-import graphql.execution.instrumentation.InstrumentationState;
-import graphql.execution.instrumentation.SimpleInstrumentation;
import graphql.execution.instrumentation.SimpleInstrumentationContext;
import graphql.execution.instrumentation.parameters.InstrumentationExecuteOperationParameters;
-import graphql.execution.instrumentation.parameters.InstrumentationExecutionParameters;
-import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters;
import graphql.language.AstPrinter;
import graphql.language.AstTransformer;
import graphql.language.BooleanValue;
@@ -23,52 +19,75 @@
import graphql.language.NodeVisitorStub;
import graphql.language.NullValue;
import graphql.language.OperationDefinition;
-import graphql.language.OperationDefinition.Operation;
import graphql.language.Value;
import graphql.language.VariableReference;
import graphql.schema.DataFetcher;
import graphql.util.TraversalControl;
import graphql.util.TraverserContext;
import graphql.util.TreeTransformerUtil;
+import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.api.trace.Span;
+import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
+import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
+import io.opentelemetry.instrumentation.api.instrumenter.SpanStatusExtractor;
import io.opentelemetry.semconv.SemanticAttributes;
import java.util.Locale;
-final class OpenTelemetryInstrumentation extends SimpleInstrumentation {
+/**
+ * This class is internal and is hence not for public use. Its APIs are unstable and can change at
+ * any time.
+ */
+public final class OpenTelemetryInstrumentationHelper {
private static final NodeVisitor sanitizingVisitor = new SanitizingVisitor();
private static final AstTransformer astTransformer = new AstTransformer();
- private final Instrumenter instrumenter;
+ private final Instrumenter instrumenter;
private final boolean sanitizeQuery;
- OpenTelemetryInstrumentation(
- Instrumenter instrumenter,
+ private OpenTelemetryInstrumentationHelper(
+ Instrumenter instrumenter,
boolean sanitizeQuery) {
this.instrumenter = instrumenter;
this.sanitizeQuery = sanitizeQuery;
}
- @Override
- public InstrumentationState createState() {
- return new OpenTelemetryInstrumentationState();
+ public static OpenTelemetryInstrumentationHelper create(
+ OpenTelemetry openTelemetry, String instrumentationName, boolean sanitizeQuery) {
+ InstrumenterBuilder builder =
+ Instrumenter.builder(
+ openTelemetry, instrumentationName, ignored -> "GraphQL Operation")
+ .setSpanStatusExtractor(
+ (spanStatusBuilder, instrumentationExecutionParameters, executionResult, error) -> {
+ if (!executionResult.getErrors().isEmpty()) {
+ spanStatusBuilder.setStatus(StatusCode.ERROR);
+ } else {
+ SpanStatusExtractor.getDefault()
+ .extract(
+ spanStatusBuilder,
+ instrumentationExecutionParameters,
+ executionResult,
+ error);
+ }
+ });
+ builder.addAttributesExtractor(new GraphqlAttributesExtractor());
+
+ return new OpenTelemetryInstrumentationHelper(builder.buildInstrumenter(), sanitizeQuery);
}
- @Override
public InstrumentationContext beginExecution(
- InstrumentationExecutionParameters parameters) {
+ OpenTelemetryInstrumentationState state) {
Context parentContext = Context.current();
- if (!instrumenter.shouldStart(parentContext, parameters)) {
+ if (!instrumenter.shouldStart(parentContext, state)) {
return SimpleInstrumentationContext.noOp();
}
- Context context = instrumenter.start(parentContext, parameters);
- OpenTelemetryInstrumentationState state = parameters.getInstrumentationState();
+ Context context = instrumenter.start(parentContext, state);
state.setContext(context);
return SimpleInstrumentationContext.whenCompleted(
@@ -82,20 +101,18 @@ public InstrumentationContext beginExecution(
span.addEvent(SemanticAttributes.EXCEPTION_EVENT_NAME, attributes.build());
}
- instrumenter.end(context, parameters, result, throwable);
+ instrumenter.end(context, state, result, throwable);
});
}
- @Override
public InstrumentationContext beginExecuteOperation(
- InstrumentationExecuteOperationParameters parameters) {
-
- OpenTelemetryInstrumentationState state = parameters.getInstrumentationState();
+ InstrumentationExecuteOperationParameters parameters,
+ OpenTelemetryInstrumentationState state) {
Span span = Span.fromContext(state.getContext());
OperationDefinition operationDefinition =
parameters.getExecutionContext().getOperationDefinition();
- Operation operation = operationDefinition.getOperation();
+ OperationDefinition.Operation operation = operationDefinition.getOperation();
String operationType = operation.name().toLowerCase(Locale.ROOT);
String operationName = operationDefinition.getName();
@@ -117,10 +134,8 @@ public InstrumentationContext beginExecuteOperation(
return SimpleInstrumentationContext.noOp();
}
- @Override
public DataFetcher> instrumentDataFetcher(
- DataFetcher> dataFetcher, InstrumentationFieldFetchParameters parameters) {
- OpenTelemetryInstrumentationState state = parameters.getInstrumentationState();
+ DataFetcher> dataFetcher, OpenTelemetryInstrumentationState state) {
Context context = state.getContext();
return (DataFetcher