Graphql Instrumentation

钮出野
2023-12-01

Instrumentation 包括系统默认及自定义两部分,如果是kickstart的boot实现,默认Instrumentation,可以参考GraphQLInstrumentationAutoConfiguration类,以下是这个类的代码:

@Configuration
@ConditionalOnClass(MetricsAutoConfiguration.class)
@AutoConfigureAfter({MetricsAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class,
    GraphQLWebsocketAutoConfiguration.class})
@ConditionalOnProperty(value = "graphql.servlet.enabled", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties({GraphQLServletProperties.class})
public class GraphQLInstrumentationAutoConfiguration {

  @Value("${graphql.servlet.maxQueryComplexity:#{null}}")
  private Integer maxQueryComplexity;

  @Value("${graphql.servlet.maxQueryDepth:#{null}}")
  private Integer maxQueryDepth;

  @Value("${graphql.servlet.tracing-enabled:'false'}")
  private String tracingEnabled;

  @Bean
  @ConditionalOnMissingBean({TracingInstrumentation.class, MetricsInstrumentation.class})
  @ConditionalOnExpression("${graphql.servlet.tracing-enabled:'false'}.equals('metrics-only')"
      + "|| ${graphql.servlet.tracing-enabled:'false'}.equals(true)")
  public TracingInstrumentation tracingInstrumentation() {
    return new TracingInstrumentation();
  }

  @Bean
  @ConditionalOnMissingBean
  @ConditionalOnExpression("${graphql.servlet.actuator-metrics:false}"
      + "&& ${graphql.servlet.tracing-enabled:'false'}.toString().equals('false')")
  public TracingNoResolversInstrumentation tracingNoResolversInstrumentation() {
    return new TracingNoResolversInstrumentation();
  }

  @Bean
  @ConditionalOnMissingBean
  @ConditionalOnProperty(value = "graphql.servlet.max-query-complexity")
  public MaxQueryComplexityInstrumentation maxQueryComplexityInstrumentation() {
    return new MaxQueryComplexityInstrumentation(maxQueryComplexity);
  }

  @Bean
  @ConditionalOnMissingBean
  @ConditionalOnProperty(value = "graphql.servlet.max-query-depth")
  public MaxQueryDepthInstrumentation maxQueryDepthInstrumentation() {
    return new MaxQueryDepthInstrumentation(maxQueryDepth);
  }

  @Bean
  @ConditionalOnProperty(value = "graphql.servlet.actuator-metrics", havingValue = "true")
  @ConditionalOnBean({MeterRegistry.class, TracingInstrumentation.class})
  @ConditionalOnMissingBean
  public MetricsInstrumentation metricsInstrumentation(MeterRegistry meterRegistry) {
    return new MetricsInstrumentation(meterRegistry, Boolean.TRUE.toString().equals(tracingEnabled));
  }

  @Bean
  @ConditionalOnProperty(value = "graphql.servlet.actuator-metrics", havingValue = "true")
  @ConditionalOnBean({MeterRegistry.class, GraphQLWebsocketServlet.class})
  @ConditionalOnMissingBean
  public WebsocketMetrics websocketMetrics(MeterRegistry meterRegistry, GraphQLWebsocketServlet websocketServlet) {
    return new WebsocketMetrics(meterRegistry, websocketServlet);
  }

}

自定义一般包括extends SimpleInstrumentation及implements InstrumentationState

implements InstrumentationState的代码如下:

public class CustomInstrumentationState implements InstrumentationState { 
	 private Map<String, Object> anyStateYouLike = new HashMap<>();

     void recordTiming(String key, long time) {
         anyStateYouLike.put(key, time);
     }
}

extends SimpleInstrumentation代码如下

@Component
public 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);
				System.out.println(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
		//

		System.out.println("instrumentExecutionResult-beginFieldComplete:" + parameters.getField().toString());

		GraphQLFieldDefinition field = parameters.getField();
		System.out.println("GraphQLFieldDefinition...." + field.getName());

		// SchemaDirectiveWiringEnvironment<GraphQLFieldDefinition> environment;

		// DataFetcher originalDataFetcher =
		// environment.getCodeRegistry().getDataFetcher(parentType, field);

		// DataFetcher originalDataFetcher = field. field.getDataFetcher();
		DataFetcher authDataFetcher = new DataFetcher() {

			@Override
			public Object get(DataFetchingEnvironment environment) throws Exception {
				GraphQLType parentType = environment.getParentType();
				//
				// build a data fetcher that first checks authorisation roles before then
				// calling the original data fetcher
				//
				// DataFetcher originalDataFetcher =
				// environment.getCodeRegistry().getDataFetcher(parentType, field);
				// TODO Auto-generated method stub

				Object obj = dataFetcher.get(environment);
				if (obj instanceof String) {
					return "field:"+field.getName()+"be"+(String) obj + "masked";
				}
				return obj;

				// return dataFetcher.get(environment);
			}
		};
		// {
		// @Override
		// public Object get(DataFetchingEnvironment dataFetchingEnvironment) throws
		// Exception {
		// Map<String, Object> contextMap = dataFetchingEnvironment.getContext();
		//
//                     Object obj = originalDataFetcher.get(dataFetchingEnvironment);
//                     if (obj instanceof String) {
//                    	 return (String)obj+"masked";
//                     }
//                     return obj;

//            }
		// };

		field.transform(builder -> builder.dataFetcher(authDataFetcher));

		return authDataFetcher;
	}

	@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
		//
		Map<String, Object> w = executionResult.toSpecification();

		w.forEach((str, obj) -> {
			System.out.println("instrumentExecutionResult-" + str);
			System.out.println("instrumentExecutionResult-" + obj.toString());
			if (obj instanceof String) {

			}
		});
		System.out.println("instrumentExecutionResult-getOperation:" + parameters.getOperation());
		System.out.println("instrumentExecutionResult-getQuery:" + parameters.getQuery());

		return CompletableFuture.completedFuture(executionResult);
	}

	@Override
	public InstrumentationContext<ExecutionResult> beginField(InstrumentationFieldParameters parameters) {
		System.out.println("instrumentExecutionResult-beginField:" + parameters.getField().toString());

		return new SimpleInstrumentationContext<>();
	}

	@Override
	public InstrumentationContext<Object> beginFieldFetch(InstrumentationFieldFetchParameters parameters) {
		System.out.println("instrumentExecutionResult-beginFieldFetch:" + parameters.getField().toString());

		return new SimpleInstrumentationContext<>();
	}

	@Override
	public InstrumentationContext<ExecutionResult> beginFieldComplete(
			InstrumentationFieldCompleteParameters parameters) {

		//
		// now change the field definition to have the new authorising data fetcher
		System.out.println("GraphQLFieldDefinition...." + parameters.getFetchedValue().toString());

		System.out.println("GraphQLFieldDefinition...." + parameters.getFetchedValue().toString());

		return new SimpleInstrumentationContext<>();
	}

	@Override
	public InstrumentationContext<ExecutionResult> beginFieldListComplete(
			InstrumentationFieldCompleteParameters parameters) {
		System.out.println("instrumentExecutionResult-beginFieldListComplete:" + parameters.getField().toString());

		return new SimpleInstrumentationContext<>();
	}

}

上面的代码是一个修改输出的简单示意。

 类似资料:

相关阅读

相关文章

相关问答