Merge branch '1.1.x'
This commit is contained in:
@@ -2,7 +2,7 @@ description = "Spring for GraphQL"
|
||||
|
||||
ext {
|
||||
moduleProjects = [project(":spring-graphql"), project(":spring-graphql-test")]
|
||||
springFrameworkVersion = "6.0.3"
|
||||
springFrameworkVersion = "6.0.4"
|
||||
graphQlJavaVersion = "20.0"
|
||||
springBootVersion = "3.0.0"
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@ javaPlatform {
|
||||
|
||||
dependencies {
|
||||
api(platform("org.springframework:spring-framework-bom:${springFrameworkVersion}"))
|
||||
api(platform("com.fasterxml.jackson:jackson-bom:2.14.1"))
|
||||
api(platform("io.projectreactor:reactor-bom:2022.0.1"))
|
||||
api(platform("io.micrometer:micrometer-bom:1.10.2"))
|
||||
api(platform("io.micrometer:micrometer-tracing-bom:1.0.0"))
|
||||
api(platform("org.springframework.data:spring-data-bom:2022.0.0"))
|
||||
api(platform("com.fasterxml.jackson:jackson-bom:2.14.2"))
|
||||
api(platform("io.projectreactor:reactor-bom:2022.0.2"))
|
||||
api(platform("io.micrometer:micrometer-bom:1.10.4"))
|
||||
api(platform("io.micrometer:micrometer-tracing-bom:1.0.2"))
|
||||
api(platform("org.springframework.data:spring-data-bom:2022.0.1"))
|
||||
api(platform("org.springframework.security:spring-security-bom:6.0.1"))
|
||||
api(platform("com.querydsl:querydsl-bom:5.0.0"))
|
||||
api(platform("io.rsocket:rsocket-bom:1.1.3"))
|
||||
@@ -25,7 +25,7 @@ dependencies {
|
||||
|
||||
constraints {
|
||||
api("com.graphql-java:graphql-java:${graphQlJavaVersion}")
|
||||
api("io.micrometer:context-propagation:1.0.0")
|
||||
api("io.micrometer:context-propagation:1.0.2")
|
||||
|
||||
api("jakarta.annotation:jakarta.annotation-api:2.1.1")
|
||||
api("jakarta.servlet:jakarta.servlet-api:6.0.0")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2022 the original author or authors.
|
||||
* Copyright 2020-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.graphql.observation;
|
||||
import java.util.concurrent.CompletionStage;
|
||||
|
||||
import graphql.ExecutionResult;
|
||||
import graphql.GraphQLContext;
|
||||
import graphql.execution.instrumentation.InstrumentationContext;
|
||||
import graphql.execution.instrumentation.InstrumentationState;
|
||||
import graphql.execution.instrumentation.SimpleInstrumentationContext;
|
||||
@@ -100,20 +101,21 @@ public class GraphQlObservationInstrumentation extends SimplePerformantInstrumen
|
||||
InstrumentationState state) {
|
||||
if (state instanceof RequestObservationInstrumentationState instrumentationState) {
|
||||
ExecutionRequestObservationContext observationContext = new ExecutionRequestObservationContext(parameters.getExecutionInput());
|
||||
Observation parentObservation = parameters.getGraphQLContext().get(OBSERVATION_KEY);
|
||||
Observation requestObservation = instrumentationState.createRequestObservation(this.requestObservationConvention,
|
||||
observationContext, this.observationRegistry);
|
||||
requestObservation.parentObservation(parentObservation);
|
||||
parameters.getGraphQLContext().put(OBSERVATION_KEY, requestObservation);
|
||||
requestObservation.start();
|
||||
return new SimpleInstrumentationContext<>() {
|
||||
@Override
|
||||
public void onCompleted(ExecutionResult result, Throwable exc) {
|
||||
observationContext.setResponse(result);
|
||||
if (exc != null) {
|
||||
observationContext.setError(exc);
|
||||
requestObservation.error(exc);
|
||||
}
|
||||
else {
|
||||
requestObservation.stop();
|
||||
}
|
||||
requestObservation.stop();
|
||||
instrumentationState.restoreParentObservation(parameters.getGraphQLContext(), parentObservation);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -126,58 +128,66 @@ public class GraphQlObservationInstrumentation extends SimplePerformantInstrumen
|
||||
if (!parameters.isTrivialDataFetcher()
|
||||
&& state instanceof RequestObservationInstrumentationState instrumentationState) {
|
||||
return (environment) -> {
|
||||
GraphQLContext graphQLContext = parameters.getExecutionContext().getGraphQLContext();
|
||||
Observation parentObservation = graphQLContext.get(OBSERVATION_KEY);
|
||||
DataFetcherObservationContext observationContext = new DataFetcherObservationContext(parameters.getEnvironment());
|
||||
Observation dataFetcherObservation = instrumentationState.createDataFetcherObservation(
|
||||
this.dataFetcherObservationConvention, observationContext, this.observationRegistry);
|
||||
parameters.getExecutionContext().getGraphQLContext().put(OBSERVATION_KEY, dataFetcherObservation);
|
||||
dataFetcherObservation.parentObservation(parentObservation);
|
||||
graphQLContext.put(OBSERVATION_KEY, dataFetcherObservation);
|
||||
dataFetcherObservation.start();
|
||||
try {
|
||||
Object value = dataFetcher.get(environment);
|
||||
if (value instanceof CompletionStage<?> completion) {
|
||||
return completion.whenComplete((result, error) -> {
|
||||
observationContext.setValue(result);
|
||||
if (error != null) {
|
||||
dataFetcherObservation.error(error);
|
||||
}
|
||||
observationContext.setValue(result);
|
||||
dataFetcherObservation.stop();
|
||||
instrumentationState.restoreParentObservation(graphQLContext, parentObservation);
|
||||
});
|
||||
}
|
||||
else {
|
||||
observationContext.setValue(value);
|
||||
dataFetcherObservation.stop();
|
||||
instrumentationState.restoreParentObservation(graphQLContext, parentObservation);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
dataFetcherObservation.error(throwable);
|
||||
dataFetcherObservation.stop();
|
||||
instrumentationState.restoreParentObservation(graphQLContext, parentObservation);
|
||||
throw throwable;
|
||||
}
|
||||
};
|
||||
}
|
||||
return super.instrumentDataFetcher(dataFetcher, parameters, state);
|
||||
return dataFetcher;
|
||||
}
|
||||
|
||||
|
||||
static class RequestObservationInstrumentationState implements InstrumentationState {
|
||||
|
||||
private Observation requestObservation;
|
||||
|
||||
|
||||
Observation createRequestObservation(ExecutionRequestObservationConvention convention,
|
||||
ExecutionRequestObservationContext context, ObservationRegistry registry) {
|
||||
Observation observation = GraphQlObservationDocumentation.EXECUTION_REQUEST.observation(convention,
|
||||
return GraphQlObservationDocumentation.EXECUTION_REQUEST.observation(convention,
|
||||
DEFAULT_REQUEST_CONVENTION, () -> context, registry);
|
||||
this.requestObservation = observation;
|
||||
return observation;
|
||||
}
|
||||
|
||||
Observation createDataFetcherObservation(DataFetcherObservationConvention convention,
|
||||
DataFetcherObservationContext context, ObservationRegistry registry) {
|
||||
Observation dataFetcherObservation = GraphQlObservationDocumentation.DATA_FETCHER.observation(convention,
|
||||
return GraphQlObservationDocumentation.DATA_FETCHER.observation(convention,
|
||||
DEFAULT_DATA_FETCHER_CONVENTION, () -> context, registry);
|
||||
dataFetcherObservation.parentObservation(requestObservation);
|
||||
return dataFetcherObservation;
|
||||
}
|
||||
|
||||
void restoreParentObservation(GraphQLContext context, Observation parentObservation) {
|
||||
if (parentObservation != null) {
|
||||
context.put(OBSERVATION_KEY, parentObservation);
|
||||
}
|
||||
else {
|
||||
context.delete(OBSERVATION_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2022 the original author or authors.
|
||||
* Copyright 2020-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,6 +20,8 @@ import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import graphql.GraphqlErrorBuilder;
|
||||
import io.micrometer.observation.Observation;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import io.micrometer.observation.tck.TestObservationRegistry;
|
||||
import io.micrometer.observation.tck.TestObservationRegistryAssert;
|
||||
import io.micrometer.observation.transport.ReceiverContext;
|
||||
@@ -199,6 +201,30 @@ class GraphQlObservationInstrumentationTests {
|
||||
.hasParentObservationContextMatching(context -> context instanceof ExecutionRequestObservationContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
void setIncomingObservationAsParent() {
|
||||
String document = """
|
||||
{
|
||||
bookById(id: 1) {
|
||||
name
|
||||
}
|
||||
}
|
||||
""";
|
||||
ExecutionGraphQlRequest graphQlRequest = TestExecutionRequest.forDocument(document);
|
||||
Observation incoming = Observation.start("incoming", ObservationRegistry.create());
|
||||
graphQlRequest.configureExecutionInput((input, builder) ->
|
||||
builder.graphQLContext(contextBuilder -> contextBuilder.of("micrometer.observation", incoming)).build());
|
||||
Mono<ExecutionGraphQlResponse> responseMono = graphQlSetup
|
||||
.queryFetcher("bookById", env -> BookSource.getBookWithoutAuthor(1L))
|
||||
.toGraphQlService()
|
||||
.execute(graphQlRequest);
|
||||
ResponseHelper response = ResponseHelper.forResponse(responseMono);
|
||||
|
||||
TestObservationRegistryAssert.assertThat(this.observationRegistry).hasObservationWithNameEqualTo("graphql.request")
|
||||
.that().hasParentObservationEqualTo(incoming);
|
||||
incoming.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
void inboundTracingInformationIsPropagated() {
|
||||
SimpleTracer simpleTracer = new SimpleTracer();
|
||||
|
||||
Reference in New Issue
Block a user