經過實現Instrumentation接口,能夠觀察一個query的執行,或修改運行期的行爲。java
最多見的用途是進行性能監控,和自定義日誌記錄,但它也能夠用於完成其餘任務。app
建立GraphQL對象時,能夠綁定相關的Instrumentation實現。ide
GraphQL.newGraphQL(schema) .instrumentation(new TracingInstrumentation()) .build();
Instrumentation實現類須要實現"begin"開頭的方法。這個方法會在查詢執行的過程當中,在每一個步驟開始以前被調用。性能
每一個回調方法都必須返回一個非空的InstrumentationContext對象,這個對象在本執行步驟完成時會被回調,並告知是否調用成功或是出錯(能夠獲取Throwable對象)。fetch
下面的示例中,給出了一個自定義的Instrumentation攔截器。能夠用來測量執行過程的總體執行時間,並將結果存入一個有狀態的對象當中。ui
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); } }
能夠使用ChainedInstrumentation類,將多個Instrumentation對象進行聚合。ChainedInstrumentation類接收一個Instrumentation對象列表參數,而後按照它們定義的順序依次調用。this
List<Instrumentation> chainedList = new ArrayList<>(); chainedList.add(new FooInstrumentation()); chainedList.add(new BarInstrumentation()); ChainedInstrumentation chainedInstrumentation = new ChainedInstrumentation(chainedList); GraphQL.newGraphQL(schema) .instrumentation(chainedInstrumentation) .build();
FieldValidationInstrumentation攔截器,能夠在執行查詢前,校驗字段和字段參數。若是校驗失敗,那麼執行過程將終止,error信息添加到查詢的result當中。日誌
能夠自定義FieldValidation的實現,或直接使用SimpleFieldValidation類來爲每一個字段增長校驗規則。code
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();