GraphQL Java - Instrumentation

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

Guess you like

Origin www.cnblogs.com/pku-liuqiang/p/11529115.html