Add instrumentation for graphql 20 that does not use deprecated methods (#10779)
This commit is contained in:
parent
9db9661bc9
commit
a3a572540e
|
@ -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 {
|
||||
|
|
|
@ -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),<br>[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),<br>[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),<br>[opentelemetry-runtime-telemetry-java17](../instrumentation/runtime-telemetry/runtime-telemetry-java17/library),<br>[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] |
|
||||
|
|
|
@ -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"))
|
||||
}
|
|
@ -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<InstrumentationExecutionParameters, ExecutionResult> instrumenter;
|
||||
private final boolean sanitizeQuery;
|
||||
|
||||
GraphQLTelemetry(OpenTelemetry openTelemetry, boolean sanitizeQuery) {
|
||||
InstrumenterBuilder<InstrumentationExecutionParameters, ExecutionResult> builder =
|
||||
Instrumenter.<InstrumentationExecutionParameters, ExecutionResult>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);
|
||||
}
|
||||
}
|
|
@ -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.+")
|
||||
}
|
|
@ -17,7 +17,7 @@ import net.bytebuddy.asm.Advice;
|
|||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
public class GraphqlInstrumentation implements TypeInstrumentation {
|
||||
class GraphqlInstrumentation implements TypeInstrumentation {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
|
@ -5,11 +5,15 @@
|
|||
|
||||
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)
|
||||
|
@ -19,6 +23,13 @@ public class GraphqlInstrumentationModule extends InstrumentationModule {
|
|||
super("graphql-java", "graphql-java-12.0");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
|
||||
// added in 20.0
|
||||
return not(
|
||||
hasClassesNamed("graphql.execution.instrumentation.SimplePerformantInstrumentation"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TypeInstrumentation> typeInstrumentations() {
|
||||
return Collections.singletonList(new GraphqlInstrumentation());
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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/).
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
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"))
|
||||
|
||||
latestDepTestLibrary("com.graphql-java:graphql-java:19.+")
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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<ExecutionResult> beginExecution(
|
||||
InstrumentationExecutionParameters parameters) {
|
||||
OpenTelemetryInstrumentationState state = parameters.getInstrumentationState();
|
||||
return helper.beginExecution(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstrumentationContext<ExecutionResult> 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);
|
||||
}
|
||||
}
|
|
@ -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"))
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.graphql.v20_0;
|
||||
|
||||
import static io.opentelemetry.javaagent.instrumentation.graphql.v20_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<TypeDescription> 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.graphql.v20_0;
|
||||
|
||||
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
|
||||
|
||||
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-20.0");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
|
||||
// added in 20.0
|
||||
return hasClassesNamed("graphql.execution.instrumentation.SimplePerformantInstrumentation");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TypeInstrumentation> typeInstrumentations() {
|
||||
return Collections.singletonList(new GraphqlInstrumentation());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.graphql.v20_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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.graphql.v20_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) {}
|
||||
}
|
|
@ -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
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.opentelemetry.instrumentation</groupId>
|
||||
<artifactId>opentelemetry-graphql-java-20.0</artifactId>
|
||||
<version>OPENTELEMETRY_VERSION</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
|
||||
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());
|
||||
}
|
||||
```
|
|
@ -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"))
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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<ExecutionResult> beginExecution(
|
||||
InstrumentationExecutionParameters parameters, InstrumentationState rawState) {
|
||||
OpenTelemetryInstrumentationState state = ofState(rawState);
|
||||
return helper.beginExecution(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstrumentationContext<ExecutionResult> 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);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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")
|
||||
}
|
|
@ -4,6 +4,4 @@ plugins {
|
|||
|
||||
dependencies {
|
||||
library("com.graphql-java:graphql-java:12.0")
|
||||
|
||||
testImplementation(project(":instrumentation:graphql-java-12.0:testing"))
|
||||
}
|
|
@ -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 io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
|
|||
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<InstrumentationExecutionParameters, ExecutionResult> {
|
||||
implements AttributesExtractor<OpenTelemetryInstrumentationState, ExecutionResult> {
|
||||
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/database/graphql.md
|
||||
private static final AttributeKey<String> 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());
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
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();
|
||||
public static Instrumentation addInstrumentation(
|
||||
Instrumentation instrumentation, Instrumentation ourInstrumentation) {
|
||||
if (instrumentation == null) {
|
||||
return ourInstrumentation;
|
||||
}
|
||||
|
@ -47,4 +37,6 @@ public final class GraphqlSingletons {
|
|||
}
|
||||
return new ChainedInstrumentation(instrumentationList);
|
||||
}
|
||||
|
||||
private InstrumentationUtil() {}
|
||||
}
|
|
@ -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.NodeVisitor;
|
|||
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<InstrumentationExecutionParameters, ExecutionResult> instrumenter;
|
||||
private final Instrumenter<OpenTelemetryInstrumentationState, ExecutionResult> instrumenter;
|
||||
private final boolean sanitizeQuery;
|
||||
|
||||
OpenTelemetryInstrumentation(
|
||||
Instrumenter<InstrumentationExecutionParameters, ExecutionResult> instrumenter,
|
||||
private OpenTelemetryInstrumentationHelper(
|
||||
Instrumenter<OpenTelemetryInstrumentationState, ExecutionResult> 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<OpenTelemetryInstrumentationState, ExecutionResult> builder =
|
||||
Instrumenter.<OpenTelemetryInstrumentationState, ExecutionResult>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<ExecutionResult> 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 @@ final class OpenTelemetryInstrumentation extends SimpleInstrumentation {
|
|||
span.addEvent(SemanticAttributes.EXCEPTION_EVENT_NAME, attributes.build());
|
||||
}
|
||||
|
||||
instrumenter.end(context, parameters, result, throwable);
|
||||
instrumenter.end(context, state, result, throwable);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstrumentationContext<ExecutionResult> 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 @@ final class OpenTelemetryInstrumentation extends SimpleInstrumentation {
|
|||
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<Object>)
|
|
@ -3,13 +3,17 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.graphql.v12_0;
|
||||
package io.opentelemetry.instrumentation.graphql.internal;
|
||||
|
||||
import graphql.execution.instrumentation.InstrumentationState;
|
||||
import graphql.language.OperationDefinition.Operation;
|
||||
import io.opentelemetry.context.Context;
|
||||
|
||||
final class OpenTelemetryInstrumentationState implements InstrumentationState {
|
||||
/**
|
||||
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
|
||||
* any time.
|
||||
*/
|
||||
public final class OpenTelemetryInstrumentationState implements InstrumentationState {
|
||||
private Context context;
|
||||
private Operation operation;
|
||||
private String operationName;
|
|
@ -180,7 +180,7 @@ public abstract class AbstractGraphqlTest {
|
|||
equalTo(AttributeKey.stringKey("graphql.operation.type"), "query"),
|
||||
normalizedQueryEqualsTo(
|
||||
AttributeKey.stringKey("graphql.document"),
|
||||
"query { bookById(id: ?) { name } }")),
|
||||
"{ bookById(id: ?) { name } }")),
|
||||
span -> span.hasName("fetchBookById").hasParent(trace.getSpan(0))));
|
||||
}
|
||||
|
||||
|
@ -211,7 +211,8 @@ public abstract class AbstractGraphqlTest {
|
|||
satisfies(
|
||||
SemanticAttributes.EXCEPTION_MESSAGE,
|
||||
message ->
|
||||
message.startsWith("Invalid Syntax"))))));
|
||||
message.startsWithIgnoringCase(
|
||||
"Invalid Syntax"))))));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -252,8 +253,7 @@ public abstract class AbstractGraphqlTest {
|
|||
satisfies(
|
||||
SemanticAttributes.EXCEPTION_MESSAGE,
|
||||
message ->
|
||||
message.startsWith(
|
||||
"Validation error of type FieldUndefined"))))));
|
||||
message.startsWith("Validation error"))))));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -295,6 +295,9 @@ public abstract class AbstractGraphqlTest {
|
|||
stringAssert.satisfies(
|
||||
querySource -> {
|
||||
String normalized = querySource.replaceAll("(?s)\\s+", " ");
|
||||
if (normalized.startsWith("query {")) {
|
||||
normalized = normalized.substring("query ".length());
|
||||
}
|
||||
assertThat(normalized).isEqualTo(value);
|
||||
}));
|
||||
}
|
|
@ -191,9 +191,12 @@ include(":instrumentation:cassandra:cassandra-4.4:library")
|
|||
include(":instrumentation:cassandra:cassandra-4.4:testing")
|
||||
include(":instrumentation:cassandra:cassandra-4-common:testing")
|
||||
include(":instrumentation:cdi-testing")
|
||||
include(":instrumentation:graphql-java-12.0:javaagent")
|
||||
include(":instrumentation:graphql-java-12.0:library")
|
||||
include(":instrumentation:graphql-java-12.0:testing")
|
||||
include(":instrumentation:graphql-java:graphql-java-12.0:javaagent")
|
||||
include(":instrumentation:graphql-java:graphql-java-12.0:library")
|
||||
include(":instrumentation:graphql-java:graphql-java-20.0:javaagent")
|
||||
include(":instrumentation:graphql-java:graphql-java-20.0:library")
|
||||
include(":instrumentation:graphql-java:graphql-java-common:library")
|
||||
include(":instrumentation:graphql-java:graphql-java-common:testing")
|
||||
include(":instrumentation:internal:internal-application-logger:bootstrap")
|
||||
include(":instrumentation:internal:internal-application-logger:javaagent")
|
||||
include(":instrumentation:internal:internal-class-loader:javaagent")
|
||||
|
|
Loading…
Reference in New Issue