Skip to content

Commit 0e9b9e9

Browse files
committed
This is a refactor of the Instrumentation such that it now has 2 call backs
one for on `dispatched` and one for on `complete`
1 parent f3d2b8b commit 0e9b9e9

37 files changed

+371
-459
lines changed

docs/instrumentation.rst

Lines changed: 8 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ The following is a basic custom ``Instrumentation`` that measures overall execut
3636
}
3737
}
3838
39-
class CustomInstrumentation implements Instrumentation {
39+
class CustomInstrumentation extends SimpleInstrumentation {
4040
@Override
4141
public InstrumentationState createState() {
4242
//
@@ -49,51 +49,19 @@ The following is a basic custom ``Instrumentation`` that measures overall execut
4949
@Override
5050
public InstrumentationContext<ExecutionResult> beginExecution(InstrumentationExecutionParameters parameters) {
5151
long startNanos = System.nanoTime();
52-
return (result, throwable) -> {
53-
54-
CustomInstrumentationState state = parameters.getInstrumentationState();
55-
state.recordTiming(parameters.getQuery(), System.nanoTime() - startNanos);
52+
return new SimpleInstrumentationContext<ExecutionResult>() {
53+
@Override
54+
public void onCompleted(ExecutionResult result, Throwable t) {
55+
CustomInstrumentationState state = parameters.getInstrumentationState();
56+
state.recordTiming(parameters.getQuery(), System.nanoTime() - startNanos);
57+
}
5658
};
5759
}
5860
59-
@Override
60-
public InstrumentationContext<Document> beginParse(InstrumentationExecutionParameters parameters) {
61-
//
62-
// You MUST return a non null object but it does not have to do anything and hence
63-
// you use this class to return a no-op object
64-
//
65-
return new NoOpInstrumentation.NoOpInstrumentationContext<>();
66-
}
67-
68-
@Override
69-
public InstrumentationContext<List<ValidationError>> beginValidation(InstrumentationValidationParameters parameters) {
70-
return new NoOpInstrumentation.NoOpInstrumentationContext<>();
71-
}
72-
73-
@Override
74-
public InstrumentationContext<ExecutionResult> beginDataFetch(InstrumentationDataFetchParameters parameters) {
75-
return new NoOpInstrumentation.NoOpInstrumentationContext<>();
76-
}
77-
78-
@Override
79-
public InstrumentationContext<CompletableFuture<ExecutionResult>> beginExecutionStrategy(InstrumentationExecutionStrategyParameters parameters) {
80-
return new NoOpInstrumentation.NoOpInstrumentationContext<>();
81-
}
82-
83-
@Override
84-
public InstrumentationContext<ExecutionResult> beginField(InstrumentationFieldParameters parameters) {
85-
return new NoOpInstrumentation.NoOpInstrumentationContext<>();
86-
}
87-
88-
@Override
89-
public InstrumentationContext<Object> beginFieldFetch(InstrumentationFieldFetchParameters parameters) {
90-
return new NoOpInstrumentation.NoOpInstrumentationContext<>();
91-
}
92-
9361
@Override
9462
public DataFetcher<?> instrumentDataFetcher(DataFetcher<?> dataFetcher, InstrumentationFieldFetchParameters parameters) {
9563
//
96-
// this allows you to intercept the data fetcher used ot fetch a field and provide another one, perhaps
64+
// this allows you to intercept the data fetcher used to fetch a field and provide another one, perhaps
9765
// that enforces certain behaviours or has certain side effects on the data
9866
//
9967
return dataFetcher;

src/main/java/graphql/GraphQL.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import graphql.execution.instrumentation.Instrumentation;
1212
import graphql.execution.instrumentation.InstrumentationContext;
1313
import graphql.execution.instrumentation.InstrumentationState;
14-
import graphql.execution.instrumentation.NoOpInstrumentation;
14+
import graphql.execution.instrumentation.SimpleInstrumentation;
1515
import graphql.execution.instrumentation.parameters.InstrumentationExecutionParameters;
1616
import graphql.execution.instrumentation.parameters.InstrumentationValidationParameters;
1717
import graphql.execution.preparsed.NoOpPreparsedDocumentProvider;
@@ -127,7 +127,7 @@ public GraphQL(GraphQLSchema graphQLSchema, ExecutionStrategy queryStrategy) {
127127
*/
128128
@Internal
129129
public GraphQL(GraphQLSchema graphQLSchema, ExecutionStrategy queryStrategy, ExecutionStrategy mutationStrategy) {
130-
this(graphQLSchema, queryStrategy, mutationStrategy, null, DEFAULT_EXECUTION_ID_PROVIDER, NoOpInstrumentation.INSTANCE, NoOpPreparsedDocumentProvider.INSTANCE);
130+
this(graphQLSchema, queryStrategy, mutationStrategy, null, DEFAULT_EXECUTION_ID_PROVIDER, SimpleInstrumentation.INSTANCE, NoOpPreparsedDocumentProvider.INSTANCE);
131131
}
132132

133133
/**
@@ -142,7 +142,7 @@ public GraphQL(GraphQLSchema graphQLSchema, ExecutionStrategy queryStrategy, Exe
142142
*/
143143
@Internal
144144
public GraphQL(GraphQLSchema graphQLSchema, ExecutionStrategy queryStrategy, ExecutionStrategy mutationStrategy, ExecutionStrategy subscriptionStrategy) {
145-
this(graphQLSchema, queryStrategy, mutationStrategy, subscriptionStrategy, DEFAULT_EXECUTION_ID_PROVIDER, NoOpInstrumentation.INSTANCE, NoOpPreparsedDocumentProvider.INSTANCE);
145+
this(graphQLSchema, queryStrategy, mutationStrategy, subscriptionStrategy, DEFAULT_EXECUTION_ID_PROVIDER, SimpleInstrumentation.INSTANCE, NoOpPreparsedDocumentProvider.INSTANCE);
146146
}
147147

148148
private GraphQL(GraphQLSchema graphQLSchema, ExecutionStrategy queryStrategy, ExecutionStrategy mutationStrategy, ExecutionStrategy subscriptionStrategy, ExecutionIdProvider idProvider, Instrumentation instrumentation, PreparsedDocumentProvider preparsedDocumentProvider) {
@@ -200,7 +200,7 @@ public static class Builder {
200200
private ExecutionStrategy mutationExecutionStrategy = new AsyncSerialExecutionStrategy();
201201
private ExecutionStrategy subscriptionExecutionStrategy = new SubscriptionExecutionStrategy();
202202
private ExecutionIdProvider idProvider = DEFAULT_EXECUTION_ID_PROVIDER;
203-
private Instrumentation instrumentation = NoOpInstrumentation.INSTANCE;
203+
private Instrumentation instrumentation = SimpleInstrumentation.INSTANCE;
204204
private PreparsedDocumentProvider preparsedDocumentProvider = NoOpPreparsedDocumentProvider.INSTANCE;
205205

206206

@@ -463,7 +463,7 @@ public CompletableFuture<ExecutionResult> executeAsync(ExecutionInput executionI
463463
CompletableFuture<ExecutionResult> executionResult = parseValidateAndExecute(executionInput, graphQLSchema, instrumentationState);
464464
//
465465
// finish up instrumentation
466-
executionResult = executionResult.whenComplete(executionInstrumentation::onEnd);
466+
executionResult = executionResult.whenComplete(executionInstrumentation::onCompleted);
467467
//
468468
// allow instrumentation to tweak the result
469469
executionResult = executionResult.thenCompose(result -> instrumentation.instrumentExecutionResult(result, instrumentationParameters));
@@ -516,11 +516,11 @@ private ParseResult parse(ExecutionInput executionInput, GraphQLSchema graphQLSc
516516
try {
517517
document = parser.parseDocument(executionInput.getQuery());
518518
} catch (ParseCancellationException e) {
519-
parseInstrumentation.onEnd(null, e);
519+
parseInstrumentation.onCompleted(null, e);
520520
return ParseResult.ofError(e);
521521
}
522522

523-
parseInstrumentation.onEnd(document, null);
523+
parseInstrumentation.onCompleted(document, null);
524524
return ParseResult.of(document);
525525
}
526526

@@ -530,7 +530,7 @@ private List<ValidationError> validate(ExecutionInput executionInput, Document d
530530
Validator validator = new Validator();
531531
List<ValidationError> validationErrors = validator.validateDocument(graphQLSchema, document);
532532

533-
validationCtx.onEnd(validationErrors, null);
533+
validationCtx.onCompleted(validationErrors, null);
534534
return validationErrors;
535535
}
536536

src/main/java/graphql/analysis/MaxQueryComplexityInstrumentation.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import graphql.PublicApi;
44
import graphql.execution.AbortExecutionException;
55
import graphql.execution.instrumentation.InstrumentationContext;
6-
import graphql.execution.instrumentation.NoOpInstrumentation;
6+
import graphql.execution.instrumentation.SimpleInstrumentation;
77
import graphql.execution.instrumentation.parameters.InstrumentationValidationParameters;
88
import graphql.validation.ValidationError;
99

@@ -13,12 +13,13 @@
1313
import java.util.Map;
1414

1515
import static graphql.Assert.assertNotNull;
16+
import static graphql.execution.instrumentation.SimpleInstrumentationContext.whenCompleted;
1617

1718
/**
1819
* Prevents execution if the query complexity is greater than the specified maxComplexity
1920
*/
2021
@PublicApi
21-
public class MaxQueryComplexityInstrumentation extends NoOpInstrumentation {
22+
public class MaxQueryComplexityInstrumentation extends SimpleInstrumentation {
2223

2324

2425
private final int maxComplexity;
@@ -47,7 +48,7 @@ public MaxQueryComplexityInstrumentation(int maxComplexity, FieldComplexityCalcu
4748

4849
@Override
4950
public InstrumentationContext<List<ValidationError>> beginValidation(InstrumentationValidationParameters parameters) {
50-
return (errors, throwable) -> {
51+
return whenCompleted((errors, throwable) -> {
5152
if ((errors != null && errors.size() > 0) || throwable != null) {
5253
return;
5354
}
@@ -68,7 +69,7 @@ public InstrumentationContext<List<ValidationError>> beginValidation(Instrumenta
6869
if (totalComplexity > maxComplexity) {
6970
throw mkAbortException(totalComplexity, maxComplexity);
7071
}
71-
};
72+
});
7273
}
7374

7475
/**

src/main/java/graphql/analysis/MaxQueryDepthInstrumentation.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
import graphql.PublicApi;
44
import graphql.execution.AbortExecutionException;
55
import graphql.execution.instrumentation.InstrumentationContext;
6-
import graphql.execution.instrumentation.NoOpInstrumentation;
6+
import graphql.execution.instrumentation.SimpleInstrumentation;
7+
import graphql.execution.instrumentation.SimpleInstrumentationContext;
78
import graphql.execution.instrumentation.parameters.InstrumentationValidationParameters;
89
import graphql.validation.ValidationError;
910

@@ -13,7 +14,7 @@
1314
* Prevents execution if the query depth is greater than the specified maxDepth
1415
*/
1516
@PublicApi
16-
public class MaxQueryDepthInstrumentation extends NoOpInstrumentation {
17+
public class MaxQueryDepthInstrumentation extends SimpleInstrumentation {
1718

1819
private final int maxDepth;
1920

@@ -23,7 +24,7 @@ public MaxQueryDepthInstrumentation(int maxDepth) {
2324

2425
@Override
2526
public InstrumentationContext<List<ValidationError>> beginValidation(InstrumentationValidationParameters parameters) {
26-
return (errors, throwable) -> {
27+
return SimpleInstrumentationContext.whenCompleted((errors, throwable) -> {
2728
if ((errors != null && errors.size() > 0) || throwable != null) {
2829
return;
2930
}
@@ -32,7 +33,7 @@ public InstrumentationContext<List<ValidationError>> beginValidation(Instrumenta
3233
if (depth > maxDepth) {
3334
throw mkAbortException(depth, maxDepth);
3435
}
35-
};
36+
});
3637
}
3738

3839
/**

src/main/java/graphql/execution/AsyncExecutionStrategy.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,9 @@ public AsyncExecutionStrategy(DataFetcherExceptionHandler exceptionHandler) {
3636
public CompletableFuture<ExecutionResult> execute(ExecutionContext executionContext, ExecutionStrategyParameters parameters) throws NonNullableFieldWasNullException {
3737

3838
Instrumentation instrumentation = executionContext.getInstrumentation();
39-
InstrumentationExecutionStrategyParameters instrumentationParameters = new InstrumentationExecutionStrategyParameters(executionContext);
39+
InstrumentationExecutionStrategyParameters instrumentationParameters = new InstrumentationExecutionStrategyParameters(executionContext, parameters);
4040

41-
InstrumentationContext<CompletableFuture<ExecutionResult>> executionStrategyCtx = instrumentation.beginExecutionStrategy(instrumentationParameters);
42-
43-
InstrumentationContext<Map<String, List<Field>>> beginFieldsCtx = instrumentation.beginFields(instrumentationParameters);
41+
InstrumentationContext<ExecutionResult> executionStrategyCtx = instrumentation.beginExecutionStrategy(instrumentationParameters);
4442

4543
Map<String, List<Field>> fields = parameters.fields();
4644
List<String> fieldNames = new ArrayList<>(fields.keySet());
@@ -55,12 +53,13 @@ public CompletableFuture<ExecutionResult> execute(ExecutionContext executionCont
5553
CompletableFuture<ExecutionResult> future = resolveField(executionContext, newParameters);
5654
futures.add(future);
5755
}
58-
beginFieldsCtx.onEnd(fields, null);
5956

6057
CompletableFuture<ExecutionResult> overallResult = new CompletableFuture<>();
58+
executionStrategyCtx.onDispatched(overallResult);
59+
6160
Async.each(futures).whenComplete(handleResults(executionContext, fieldNames, overallResult));
6261

63-
executionStrategyCtx.onEnd(overallResult, null);
62+
overallResult.whenComplete(executionStrategyCtx::onCompleted);
6463
return overallResult;
6564
}
6665

src/main/java/graphql/execution/AsyncSerialExecutionStrategy.java

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import java.util.List;
1111
import java.util.Map;
1212
import java.util.concurrent.CompletableFuture;
13-
import java.util.function.BiConsumer;
1413

1514
/**
1615
* Async non-blocking execution, but serial: only one field at the the time will be resolved.
@@ -30,13 +29,11 @@ public AsyncSerialExecutionStrategy(DataFetcherExceptionHandler exceptionHandler
3029
public CompletableFuture<ExecutionResult> execute(ExecutionContext executionContext, ExecutionStrategyParameters parameters) throws NonNullableFieldWasNullException {
3130

3231
Instrumentation instrumentation = executionContext.getInstrumentation();
33-
InstrumentationExecutionStrategyParameters instrumentationParameters = new InstrumentationExecutionStrategyParameters(executionContext);
34-
InstrumentationContext<CompletableFuture<ExecutionResult>> executionStrategyCtx = instrumentation.beginExecutionStrategy(instrumentationParameters);
32+
InstrumentationExecutionStrategyParameters instrumentationParameters = new InstrumentationExecutionStrategyParameters(executionContext, parameters);
33+
InstrumentationContext<ExecutionResult> executionStrategyCtx = instrumentation.beginExecutionStrategy(instrumentationParameters);
3534
Map<String, List<Field>> fields = parameters.fields();
3635
List<String> fieldNames = new ArrayList<>(fields.keySet());
3736

38-
InstrumentationContext<Map<String, List<Field>>> beginFieldsCtx = instrumentation.beginFields(instrumentationParameters);
39-
4037
CompletableFuture<List<ExecutionResult>> resultsFuture = Async.eachSequentially(fieldNames, (fieldName, index, prevResults) -> {
4138
List<Field> currentField = fields.get(fieldName);
4239
ExecutionPath fieldPath = parameters.path().segment(fieldName);
@@ -45,13 +42,11 @@ public CompletableFuture<ExecutionResult> execute(ExecutionContext executionCont
4542
return resolveField(executionContext, newParameters);
4643
});
4744

48-
beginFieldsCtx.onEnd(fields, null);
49-
5045
CompletableFuture<ExecutionResult> overallResult = new CompletableFuture<>();
51-
BiConsumer<List<ExecutionResult>, Throwable> listThrowableBiConsumer = handleResults(executionContext, fieldNames, overallResult);
52-
resultsFuture.whenComplete(listThrowableBiConsumer);
46+
executionStrategyCtx.onDispatched(overallResult);
5347

54-
executionStrategyCtx.onEnd(overallResult, null);
48+
resultsFuture.whenComplete(handleResults(executionContext, fieldNames, overallResult));
49+
overallResult.whenComplete(executionStrategyCtx::onCompleted);
5550
return overallResult;
5651
}
5752

src/main/java/graphql/execution/Execution.java

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
11
package graphql.execution;
22

33

4-
import java.util.Collections;
5-
import java.util.List;
6-
import java.util.Map;
7-
import java.util.concurrent.CompletableFuture;
8-
import org.slf4j.Logger;
9-
import org.slf4j.LoggerFactory;
10-
114
import graphql.ExecutionInput;
125
import graphql.ExecutionResult;
136
import graphql.ExecutionResultImpl;
@@ -16,7 +9,7 @@
169
import graphql.execution.instrumentation.Instrumentation;
1710
import graphql.execution.instrumentation.InstrumentationContext;
1811
import graphql.execution.instrumentation.InstrumentationState;
19-
import graphql.execution.instrumentation.parameters.InstrumentationDataFetchParameters;
12+
import graphql.execution.instrumentation.parameters.InstrumentationExecuteOperationParameters;
2013
import graphql.execution.instrumentation.parameters.InstrumentationExecutionParameters;
2114
import graphql.language.Document;
2215
import graphql.language.Field;
@@ -26,6 +19,13 @@
2619
import graphql.language.VariableDefinition;
2720
import graphql.schema.GraphQLObjectType;
2821
import graphql.schema.GraphQLSchema;
22+
import org.slf4j.Logger;
23+
import org.slf4j.LoggerFactory;
24+
25+
import java.util.Collections;
26+
import java.util.List;
27+
import java.util.Map;
28+
import java.util.concurrent.CompletableFuture;
2929

3030
import static graphql.Assert.assertShouldNeverHappen;
3131
import static graphql.execution.ExecutionContextBuilder.newExecutionContextBuilder;
@@ -100,9 +100,8 @@ public CompletableFuture<ExecutionResult> execute(Document document, GraphQLSche
100100

101101
private CompletableFuture<ExecutionResult> executeOperation(ExecutionContext executionContext, InstrumentationExecutionParameters instrumentationExecutionParameters, Object root, OperationDefinition operationDefinition) {
102102

103-
InstrumentationDataFetchParameters dataFetchParameters = new InstrumentationDataFetchParameters(executionContext);
104-
InstrumentationContext<CompletableFuture<ExecutionResult>> executionDispatchCtx = instrumentation.beginDataFetchDispatch(dataFetchParameters);
105-
InstrumentationContext<ExecutionResult> dataFetchCtx = instrumentation.beginDataFetch(dataFetchParameters);
103+
InstrumentationExecuteOperationParameters instrumentationParams = new InstrumentationExecuteOperationParameters(executionContext);
104+
InstrumentationContext<ExecutionResult> executeOperationCtx = instrumentation.beginExecuteOperation(instrumentationParams);
106105

107106
OperationDefinition.Operation operation = operationDefinition.getOperation();
108107
GraphQLObjectType operationRootType;
@@ -111,8 +110,11 @@ private CompletableFuture<ExecutionResult> executeOperation(ExecutionContext exe
111110
operationRootType = getOperationRootType(executionContext.getGraphQLSchema(), operationDefinition);
112111
} catch (RuntimeException rte) {
113112
if (rte instanceof GraphQLError) {
114-
CompletableFuture<ExecutionResult> resultCompletableFuture = completedFuture(new ExecutionResultImpl(Collections.singletonList((GraphQLError) rte)));
115-
executionDispatchCtx.onEnd(resultCompletableFuture, null);
113+
ExecutionResult executionResult = new ExecutionResultImpl(Collections.singletonList((GraphQLError) rte));
114+
CompletableFuture<ExecutionResult> resultCompletableFuture = completedFuture(executionResult);
115+
116+
executeOperationCtx.onDispatched(resultCompletableFuture);
117+
executeOperationCtx.onCompleted(executionResult, rte);
116118
return resultCompletableFuture;
117119
}
118120
throw rte;
@@ -162,10 +164,10 @@ private CompletableFuture<ExecutionResult> executeOperation(ExecutionContext exe
162164
result = completedFuture(new ExecutionResultImpl(null, executionContext.getErrors()));
163165
}
164166

165-
result = result.whenComplete(dataFetchCtx::onEnd);
166-
167167
// note this happens NOW - not when the result completes
168-
executionDispatchCtx.onEnd(result, null);
168+
executeOperationCtx.onDispatched(result);
169+
170+
result = result.whenComplete(executeOperationCtx::onCompleted);
169171

170172
return result;
171173
}

0 commit comments

Comments
 (0)