Instrumentation interceptor
By implementing Instrumentation interface, you can observe the execution of a query, or modify the behavior of runtime.
The most common use is for performance monitoring, and custom logging, but it can also be used for other tasks.
When you create a GraphQL object, you can bind the relevant Instrumentation achieved.
GraphQL.newGraphQL(schema)
.instrumentation(new TracingInstrumentation())
.build();
Custom Instrumentation interceptor
Instrumentation implementation class needs to implement the method at the beginning of the "begin". This method during query execution, was called before the beginning of each step.
Each callback method must return a non-null InstrumentationContext the object, the object will be called back when the execution is completed at this step, and tell whether the call was successful or an error (you can get Throwable object).
The following example, given a Instrumentation custom interceptor. It can be used to measure the overall execution time of the execution, and the result is stored in a state in which the object.
class CustomInstrumentationState implements InstrumentationState {
private Map<String, Object> anyStateYouLike = new HashMap<>();
void recordTiming(String key, long time) {
anyStateYouLike.put(key, time);
}
}
class CustomInstrumentation extends SimpleInstrumentation {
@Override
public InstrumentationState createState() {
//
// instrumentation state is passed during each invocation of an Instrumentation method
// and allows you to put stateful data away and reference it during the query execution
//
return new CustomInstrumentationState();
}
@Override
public InstrumentationContext<ExecutionResult> beginExecution(InstrumentationExecutionParameters parameters) {
long startNanos = System.nanoTime();
return new SimpleInstrumentationContext<ExecutionResult>() {
@Override
public void onCompleted(ExecutionResult result, Throwable t) {
CustomInstrumentationState state = parameters.getInstrumentationState();
state.recordTiming(parameters.getQuery(), System.nanoTime() - startNanos);
}
};
}
@Override
public DataFetcher<?> instrumentDataFetcher(DataFetcher<?> dataFetcher, InstrumentationFieldFetchParameters parameters) {
//
// this allows you to intercept the data fetcher used to fetch a field and provide another one, perhaps
// that enforces certain behaviours or has certain side effects on the data
//
return dataFetcher;
}
@Override
public CompletableFuture<ExecutionResult> instrumentExecutionResult(ExecutionResult executionResult, InstrumentationExecutionParameters parameters) {
//
// this allows you to instrument the execution result some how. For example the Tracing support uses this to put
// the `extensions` map of data in place
//
return CompletableFuture.completedFuture(executionResult);
}
}
Instrumentation interceptor chain
ChainedInstrumentation class may be used, a plurality of objects Instrumentation polymerization. Instrumentation class ChainedInstrumentation receiving a list of objects parameter, and sequentially in the order they are defined in the call.
List<Instrumentation> chainedList = new ArrayList<>();
chainedList.add(new FooInstrumentation());
chainedList.add(new BarInstrumentation());
ChainedInstrumentation chainedInstrumentation = new ChainedInstrumentation(chainedList);
GraphQL.newGraphQL(schema)
.instrumentation(chainedInstrumentation)
.build();
Field validation Instrumentation
FieldValidationInstrumentation interceptors, before you can execute a query, check fields and field parameters. If the check fails, then the execution will terminate, error information is added to the result of the query them.
It can be custom implementation FieldValidation or directly SimpleFieldValidation class to increase the validation rules for each field.
ExecutionPath fieldPath = ExecutionPath.parse("/user");
FieldValidation fieldValidation = new SimpleFieldValidation()
.addRule(fieldPath, new BiFunction<FieldAndArguments, FieldValidationEnvironment, Optional<GraphQLError>>() {
@Override
public Optional<GraphQLError> apply(FieldAndArguments fieldAndArguments, FieldValidationEnvironment environment) {
String nameArg = fieldAndArguments.getFieldArgument("name");
if (nameArg.length() > 255) {
return Optional.of(environment.mkError("Invalid user name", fieldAndArguments));
}
return Optional.empty();
}
});
FieldValidationInstrumentation instrumentation = new FieldValidationInstrumentation(
fieldValidation
);
GraphQL.newGraphQL(schema)
.instrumentation(instrumentation)
.build();