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
- https://www.baeldung.com/spring-boot-actuators
- https://docs.spring.io/spring-boot/docs/2.0.x/actuator-api/html/#metrics
- https://github.com/graphql-java-kickstart/graphql-spring-boot#tracing-and-metrics
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.