GraphQL Java - Instrumentation

Instrumentation攔截器

經過實現Instrumentation接口,能夠觀察一個query的執行,或修改運行期的行爲。java

最多見的用途是進行性能監控,和自定義日誌記錄,但它也能夠用於完成其餘任務。app

建立GraphQL對象時,能夠綁定相關的Instrumentation實現。ide

GraphQL.newGraphQL(schema)
                .instrumentation(new TracingInstrumentation())
                .build();

自定義Instrumentation攔截器

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);
        }
    }

鏈式Instrumentation攔截器

能夠使用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();

字段驗證Instrumentation

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();
相關文章
相關標籤/搜索