https://dreamylost.cn/
文档 version = 1.4 仅供参考
Instrumentation
这个词没找到好的中文对应。以下直接使用本单词。
graphql.execution.instrumentation.Instrumentation接口允许您注入代码,这可以观察一个查询的执行并且还可以更改运行时行为。
这样做的主要用例是支持性能监控和自定义日志记录,但是它也可以用于许多不同的目的。
构建Graphql对象时,可以指定要使用的Instrumentation(如果有的话)。
GraphQL.newGraphQL(schema).instrumentation(new TracingInstrumentation()).build();
Custom Instrumentation
即定制化的Instrumentation。Instrumentation的实现需要实现“begin”步骤方法,这些方法表示graphql查询的执行。
每个步骤都必须返回一个非null的graphql.execution.instrumentation.InstrumentationContext对象,该对象将在步骤完成时被调用,并且将被告知该对象成功或以Throwable失败。
以下是一个基本的自定义Instrumentation,它计算总体执行时间并将其放入有状态对象。
/*** 自定义的instrumentation实现,用以计算请求处理时间** @author 梦境迷离* @time 2020年03月31日14:22:24*/
class CustomInstrumentationState implements InstrumentationState {
private Map<String, Object> anyStateYouLike = new HashMap<>();void recordTiming(String key, long time) {
anyStateYouLike.put(key, time);}
}public class CustomInstrumentation extends SimpleInstrumentation {
@Overridepublic InstrumentationState createState() {
return new CustomInstrumentationState();}@Overridepublic InstrumentationContext<ExecutionResult> beginExecution(InstrumentationExecutionParameters parameters) {
long startNanos = System.nanoTime();return new SimpleInstrumentationContext<ExecutionResult>() {
@Overridepublic void onCompleted(ExecutionResult result, Throwable t) {
CustomInstrumentationState state = parameters.getInstrumentationState();state.recordTiming(parameters.getQuery(), System.nanoTime() - startNanos);}};}@Overridepublic DataFetcher<?> instrumentDataFetcher(DataFetcher<?> dataFetcher, InstrumentationFieldFetchParameters parameters) {
return dataFetcher;}@Overridepublic CompletableFuture<ExecutionResult> instrumentExecutionResult(ExecutionResult executionResult, InstrumentationExecutionParameters parameters) {
return CompletableFuture.completedFuture(executionResult);}
}
Chaining Instrumentation
您可以使用graphql.execution.instrumentation.ChainedInstrumentation类将多个Instrumentation对象组合在一起,该类接受Instrumentation对象的列表并按定义的顺序调用它们。
List<Instrumentation> chainedList = new ArrayList<>();
chainedList.add(new FooInstrumentation());
chainedList.add(new BarInstrumentation());
ChainedInstrumentation chainedInstrumentation = new ChainedInstrumentation(chainedList);GraphQL.newGraphQL(schema).instrumentation(chainedInstrumentation).build();
Apollo Tracing Instrumentation
graphql.execution.instrumentation.tracing.TracingInstrumentation是一种Instrumentation实现,用于创建有关正在执行的查询的跟踪信息。
它遵循在以下位置定义的Apollo建议的跟踪格式:https://github.com/apollographql/apollo-tracing https://github.com/apollographql/apollo-tracing_
将创建一个详细的跟踪视图,并将其放置在结果的扩展部分中。
有查询请求如下
{human(id:"1001") {idname}
}
返回详细信息,在extensions中有追踪信息
{
"data": {
"human": {
"id": "1001","name": "Darth Vader"}},"extensions": {
"tracing": {
"version": 1,"startTime": "2020-03-31T06:38:11.782Z","endTime": "2020-03-31T06:38:11.787Z","duration": 5009671,"parsing": {
"startOffset": 763392,"duration": 651573},"validation": {
"startOffset": 1075836,"duration": 271042},"execution": {
"resolvers": [{
"path": ["human"],"parentType": "Query","returnType": "Human","fieldName": "human","startOffset": 1676625,"duration": 803572},{
"path": ["human","id"],"parentType": "Human","returnType": "ID!","fieldName": "id","startOffset": 3789805,"duration": 752910},{
"path": ["human","name"],"parentType": "Human","returnType": "String!","fieldName": "name","startOffset": 4693376,"duration": 49369}]}},"dataloader": {
"overall-statistics": {
"loadCount": 2,"loadErrorCount": 0,"loadErrorRatio": 0.0,"batchInvokeCount": 2,"batchLoadCount": 2,"batchLoadRatio": 1.0,"batchLoadExceptionCount": 0,"batchLoadExceptionRatio": 0.0,"cacheHitCount": 0,"cacheHitRatio": 0.0},"individual-statistics": {
"characters": {
"loadCount": 2,"loadErrorCount": 0,"loadErrorRatio": 0.0,"batchInvokeCount": 2,"batchLoadCount": 2,"batchLoadRatio": 1.0,"batchLoadExceptionCount": 0,"batchLoadExceptionRatio": 0.0,"cacheHitCount": 0,"cacheHitRatio": 0.0}}}}
}
Field Validation Instrumentation
graphql.execution.instrumentation.fieldvalidation.FieldValidationInstrumentation是一种工具实现,可用于在执行查询之前验证字段及其参数。如果在此过程中返回错误,则查询执行将中止,并且错误将出现在查询结果中。
您可以使自己实现FieldValidation,也可以使用SimpleFieldValidation类添加简单的每个字段检查规则。
/*** @author 梦境迷离* @version 1.0, 2020/3/31*/
public class FieldValidationBuilder {
public static FieldValidationInstrumentation builder() {
//遇到是human的请求,强制验证id长度不能小于4ExecutionPath fieldPath = ExecutionPath.parse("/human");FieldValidation fieldValidation = new SimpleFieldValidation().addRule(fieldPath, (fieldAndArguments, environment) -> {
String nameArg = fieldAndArguments.getArgumentValue("id");if (nameArg.length() < 4) {
return Optional.of(environment.mkError("Invalid id length", fieldAndArguments));}return Optional.empty();});return new FieldValidationInstrumentation(fieldValidation);}
}
使用时只需要将FieldValidationBuilder放入ChainedInstrumentation中,如
Instrumentation instrumentation = new ChainedInstrumentation(asList(FieldValidationBuilder.builder(), new TracingInstrumentation(), new CustomInstrumentation()));
GraphQL graphQL = GraphQL.newGraphQL(graphQLSchema).instrumentation(instrumentation).build();
有查询如下
{human(id:"1") { #改成长度不小4的字符串,就会返回数据或nullidname}
}
返回完整信息
{
"errors": [{
"message": "Invalid id length","locations": [{
"line": 2,"column": 3}],"path": ["human"]}]
}
完整例子请参考 https://github.com/jxnu-liguobin/springboot-examples