3

I've been working on adding monitoring metrics in our GraphQL gateway recently.

We're using graphql-spring-boot starter for the gateway.

After reading the following documentations, I manage to send the basic graphql.timer.query.* metrics to Datadog

What I've achieved so far is, when I send a GraphQL query/mutation, I'd collect the request count and time accordingly. e.g. sending the query below

query HelloWorldQuery {
  greeting(
    name: "Bob"
  ) {
    message
  }
}

I'll see metrics graphql.timer.query.count / graphql.timer.query.sum with tags operationName=HelloWorldQuery

It works like perfectly, until I want to test a query with errors. I realise there is no metrics/tags related to a failed query. For example, if I the above query returns null data and some GraphQL errors, I'd still collect graphql.timer.query.count (operationName=HelloWorldQuery), but there's no additional tags for me to tell there is an error for that query.

In the gateway, I have implemented a custom GraphQLErrorHandler, so I was thinking maybe I should add error counter (via MeterRegistry) in that class, but I am unable to get the operationName simply from GraphQLError type. the best I can get is error.getPath() which gives the method name (e.g. greeting) rather than the custom query name (HelloWorldQuery - to be consistent with what graphql.timer.query.* provides).

My question is, how to solve the above problem? And generally what is the best way of collecting GraphQL query metrics (including errors)?

------------------- Update -------------------

2019-12-31 I read a bit more about GraphQL Instrumentation here and checked the MetricsInstrumentation implementation in graphql-spring-boot repo, the I have an idea of extending the MetricsInstrumentation class by adding error metrics there.

2020-01-02 I tried to ingest my CustomMetricsInstrumentation class, but with no luck. There is internal AutoConfiguration wiring, which I cannot insert my auto configuration in the middle.

xialin
  • 7,686
  • 9
  • 35
  • 66

1 Answers1

4

You can override the default TracingInstrumentation with your own implementation. It will be picked automatically due to the @ConditionalOnMissingBean annotation in the GraphQLInstrumentationAutoConfiguration class. Here is a simple example that adds two custom metrics: graphql.counter.query.success and graphql.counter.query.error:

@Component
public class CustomMetricsInstrumentation extends TracingInstrumentation {

    private static final String QUERY_STATUS_COUNTER_METRIC_NAME = "graphql.counter.query";
    private static final String OPERATION_NAME_TAG = "operationName";
    private static final String UNKNOWN_OPERATION_NAME = "unknown";

    private MeterRegistry meterRegistry;

    public CustomMetricsInstrumentation(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }

    @Override
    public CompletableFuture<ExecutionResult> instrumentExecutionResult(ExecutionResult executionResult,
                                                                        InstrumentationExecutionParameters parameters) {

        String status = CollectionUtils.isEmpty(executionResult.getErrors()) ? "success" : "error";
        String operation = parameters.getOperation() != null ? parameters.getOperation() : UNKNOWN_OPERATION_NAME;
        Collection<Tag> tags = Arrays.asList(Tag.of(OPERATION_NAME_TAG, operation));

        meterRegistry.counter(QUERY_STATUS_COUNTER_METRIC_NAME + "." + status, tags).increment();

        return super.instrumentExecutionResult(executionResult, parameters);
    }
}

My application.yaml, just in case:

graphql:
  servlet:
    tracing-enabled: true
    actuator-metrics: true
management:
  endpoint:
  metrics:
    enabled: true
  endpoints:
    web:
      exposure:
        include: health,metrics

I'm using spring-boot-starter-parent:2.2.2.RELEASE, graphql-spring-boot-starter:6.0.0

I hope it helps.

Mafor
  • 9,668
  • 2
  • 21
  • 36
  • Where does the management config section come from? Is it provided by any maven package and which one? Thanks. – Kok How Teh Jun 10 '20 at 00:07
  • 1
    @KokHowTeh It comes from the Spring Boot Actuator: https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html – Mafor Jun 10 '20 at 07:03
  • @Mafor I have done the same but in my case the operation name is always unknown? – Piyush Singh Apr 10 '23 at 14:49