Skip to content

Commit 2e40383

Browse files
committed
Merge branch '1.1.x'
2 parents 124aef9 + beafa43 commit 2e40383

File tree

4 files changed

+61
-25
lines changed

4 files changed

+61
-25
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ description = "Spring for GraphQL"
22

33
ext {
44
moduleProjects = [project(":spring-graphql"), project(":spring-graphql-test")]
5-
springFrameworkVersion = "6.0.3"
5+
springFrameworkVersion = "6.0.4"
66
graphQlJavaVersion = "20.0"
77
springBootVersion = "3.0.0"
88
}

platform/build.gradle

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ javaPlatform {
88

99
dependencies {
1010
api(platform("org.springframework:spring-framework-bom:${springFrameworkVersion}"))
11-
api(platform("com.fasterxml.jackson:jackson-bom:2.14.1"))
12-
api(platform("io.projectreactor:reactor-bom:2022.0.1"))
13-
api(platform("io.micrometer:micrometer-bom:1.10.2"))
14-
api(platform("io.micrometer:micrometer-tracing-bom:1.0.0"))
15-
api(platform("org.springframework.data:spring-data-bom:2022.0.0"))
11+
api(platform("com.fasterxml.jackson:jackson-bom:2.14.2"))
12+
api(platform("io.projectreactor:reactor-bom:2022.0.2"))
13+
api(platform("io.micrometer:micrometer-bom:1.10.4"))
14+
api(platform("io.micrometer:micrometer-tracing-bom:1.0.2"))
15+
api(platform("org.springframework.data:spring-data-bom:2022.0.1"))
1616
api(platform("org.springframework.security:spring-security-bom:6.0.1"))
1717
api(platform("com.querydsl:querydsl-bom:5.0.0"))
1818
api(platform("io.rsocket:rsocket-bom:1.1.3"))
@@ -25,7 +25,7 @@ dependencies {
2525

2626
constraints {
2727
api("com.graphql-java:graphql-java:${graphQlJavaVersion}")
28-
api("io.micrometer:context-propagation:1.0.0")
28+
api("io.micrometer:context-propagation:1.0.2")
2929

3030
api("jakarta.annotation:jakarta.annotation-api:2.1.1")
3131
api("jakarta.servlet:jakarta.servlet-api:6.0.0")

spring-graphql/src/main/java/org/springframework/graphql/observation/GraphQlObservationInstrumentation.java

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2022 the original author or authors.
2+
* Copyright 2020-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
1919
import java.util.concurrent.CompletionStage;
2020

2121
import graphql.ExecutionResult;
22+
import graphql.GraphQLContext;
2223
import graphql.execution.instrumentation.InstrumentationContext;
2324
import graphql.execution.instrumentation.InstrumentationState;
2425
import graphql.execution.instrumentation.SimpleInstrumentationContext;
@@ -100,20 +101,21 @@ public InstrumentationContext<ExecutionResult> beginExecution(InstrumentationExe
100101
InstrumentationState state) {
101102
if (state instanceof RequestObservationInstrumentationState instrumentationState) {
102103
ExecutionRequestObservationContext observationContext = new ExecutionRequestObservationContext(parameters.getExecutionInput());
104+
Observation parentObservation = parameters.getGraphQLContext().get(OBSERVATION_KEY);
103105
Observation requestObservation = instrumentationState.createRequestObservation(this.requestObservationConvention,
104106
observationContext, this.observationRegistry);
107+
requestObservation.parentObservation(parentObservation);
108+
parameters.getGraphQLContext().put(OBSERVATION_KEY, requestObservation);
105109
requestObservation.start();
106110
return new SimpleInstrumentationContext<>() {
107111
@Override
108112
public void onCompleted(ExecutionResult result, Throwable exc) {
109113
observationContext.setResponse(result);
110114
if (exc != null) {
111-
observationContext.setError(exc);
112115
requestObservation.error(exc);
113116
}
114-
else {
115-
requestObservation.stop();
116-
}
117+
requestObservation.stop();
118+
instrumentationState.restoreParentObservation(parameters.getGraphQLContext(), parentObservation);
117119
}
118120
};
119121
}
@@ -126,58 +128,66 @@ public DataFetcher<?> instrumentDataFetcher(DataFetcher<?> dataFetcher,
126128
if (!parameters.isTrivialDataFetcher()
127129
&& state instanceof RequestObservationInstrumentationState instrumentationState) {
128130
return (environment) -> {
131+
GraphQLContext graphQLContext = parameters.getExecutionContext().getGraphQLContext();
132+
Observation parentObservation = graphQLContext.get(OBSERVATION_KEY);
129133
DataFetcherObservationContext observationContext = new DataFetcherObservationContext(parameters.getEnvironment());
130134
Observation dataFetcherObservation = instrumentationState.createDataFetcherObservation(
131135
this.dataFetcherObservationConvention, observationContext, this.observationRegistry);
132-
parameters.getExecutionContext().getGraphQLContext().put(OBSERVATION_KEY, dataFetcherObservation);
136+
dataFetcherObservation.parentObservation(parentObservation);
137+
graphQLContext.put(OBSERVATION_KEY, dataFetcherObservation);
133138
dataFetcherObservation.start();
134139
try {
135140
Object value = dataFetcher.get(environment);
136141
if (value instanceof CompletionStage<?> completion) {
137142
return completion.whenComplete((result, error) -> {
143+
observationContext.setValue(result);
138144
if (error != null) {
139145
dataFetcherObservation.error(error);
140146
}
141-
observationContext.setValue(result);
142147
dataFetcherObservation.stop();
148+
instrumentationState.restoreParentObservation(graphQLContext, parentObservation);
143149
});
144150
}
145151
else {
146152
observationContext.setValue(value);
147153
dataFetcherObservation.stop();
154+
instrumentationState.restoreParentObservation(graphQLContext, parentObservation);
148155
return value;
149156
}
150157
}
151158
catch (Throwable throwable) {
152159
dataFetcherObservation.error(throwable);
153160
dataFetcherObservation.stop();
161+
instrumentationState.restoreParentObservation(graphQLContext, parentObservation);
154162
throw throwable;
155163
}
156164
};
157165
}
158-
return super.instrumentDataFetcher(dataFetcher, parameters, state);
166+
return dataFetcher;
159167
}
160168

161169

162170
static class RequestObservationInstrumentationState implements InstrumentationState {
163171

164-
private Observation requestObservation;
165-
166-
167172
Observation createRequestObservation(ExecutionRequestObservationConvention convention,
168173
ExecutionRequestObservationContext context, ObservationRegistry registry) {
169-
Observation observation = GraphQlObservationDocumentation.EXECUTION_REQUEST.observation(convention,
174+
return GraphQlObservationDocumentation.EXECUTION_REQUEST.observation(convention,
170175
DEFAULT_REQUEST_CONVENTION, () -> context, registry);
171-
this.requestObservation = observation;
172-
return observation;
173176
}
174177

175178
Observation createDataFetcherObservation(DataFetcherObservationConvention convention,
176179
DataFetcherObservationContext context, ObservationRegistry registry) {
177-
Observation dataFetcherObservation = GraphQlObservationDocumentation.DATA_FETCHER.observation(convention,
180+
return GraphQlObservationDocumentation.DATA_FETCHER.observation(convention,
178181
DEFAULT_DATA_FETCHER_CONVENTION, () -> context, registry);
179-
dataFetcherObservation.parentObservation(requestObservation);
180-
return dataFetcherObservation;
182+
}
183+
184+
void restoreParentObservation(GraphQLContext context, Observation parentObservation) {
185+
if (parentObservation != null) {
186+
context.put(OBSERVATION_KEY, parentObservation);
187+
}
188+
else {
189+
context.delete(OBSERVATION_KEY);
190+
}
181191
}
182192

183193
}

spring-graphql/src/test/java/org/springframework/graphql/observation/GraphQlObservationInstrumentationTests.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2022 the original author or authors.
2+
* Copyright 2020-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,6 +20,8 @@
2020
import java.util.concurrent.CompletableFuture;
2121

2222
import graphql.GraphqlErrorBuilder;
23+
import io.micrometer.observation.Observation;
24+
import io.micrometer.observation.ObservationRegistry;
2325
import io.micrometer.observation.tck.TestObservationRegistry;
2426
import io.micrometer.observation.tck.TestObservationRegistryAssert;
2527
import io.micrometer.observation.transport.ReceiverContext;
@@ -199,6 +201,30 @@ void propagatesContextBetweenObservations() {
199201
.hasParentObservationContextMatching(context -> context instanceof ExecutionRequestObservationContext);
200202
}
201203

204+
@Test
205+
void setIncomingObservationAsParent() {
206+
String document = """
207+
{
208+
bookById(id: 1) {
209+
name
210+
}
211+
}
212+
""";
213+
ExecutionGraphQlRequest graphQlRequest = TestExecutionRequest.forDocument(document);
214+
Observation incoming = Observation.start("incoming", ObservationRegistry.create());
215+
graphQlRequest.configureExecutionInput((input, builder) ->
216+
builder.graphQLContext(contextBuilder -> contextBuilder.of("micrometer.observation", incoming)).build());
217+
Mono<ExecutionGraphQlResponse> responseMono = graphQlSetup
218+
.queryFetcher("bookById", env -> BookSource.getBookWithoutAuthor(1L))
219+
.toGraphQlService()
220+
.execute(graphQlRequest);
221+
ResponseHelper response = ResponseHelper.forResponse(responseMono);
222+
223+
TestObservationRegistryAssert.assertThat(this.observationRegistry).hasObservationWithNameEqualTo("graphql.request")
224+
.that().hasParentObservationEqualTo(incoming);
225+
incoming.stop();
226+
}
227+
202228
@Test
203229
void inboundTracingInformationIsPropagated() {
204230
SimpleTracer simpleTracer = new SimpleTracer();

0 commit comments

Comments
 (0)