Currently, with Spring Boot, all http requests are instrumented through Micrometer (https://docs.spring.io/spring-framework/reference/integration/observability.html). However, for GraphQL requests, the contextual name is the following: http post /graphql
. I would like to enhance this and add more information to it, such as the query and operation name, for example, http post /graphql query#testQuery
.
However, I'm unable to get the request body data as it seems to be empty, yet context.getCarrier().getContentLength()
is returning a non -1. Some advices how to proceed would be much appreciated.
CURL example
curl --location 'http://localhost:8080/graphql' \
--header 'Content-Type: application/json' \
--data '{"query":"{\n testQuery(id: 23) {\n result \n }\n}","variables":{}}'
Java code
package com.company.test;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.observation.DefaultServerRequestObservationConvention;
import org.springframework.http.server.observation.ServerRequestObservationContext;
@Configuration
public class CustomServerRequestObservationConvention
extends DefaultServerRequestObservationConvention {
@Override
public String getContextualName(ServerRequestObservationContext context) {
// Modify only /graphql ones
try {
StringBuilder requestBody = new StringBuilder();
InputStream inputStream = context.getCarrier().getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
requestBody.append(line);
}
// perform some string filtering here on requestBody
String operationName = "query#testQuery";
return "http post /graphql" + operationName;
} catch (Exception e) {
return "http post /graphql";
}
}
}
The HTTP observation is not the right place for that, as the HTTP instrumentation should not be aware of the type of request (GraphQL or anything else). As mentioned by Marten in the comments, to achieve this you would need to:
This has significant performance downsides and will make HTTP observations inconsistent or brittle. There is already a "graphql.request"
observation for this.
Note that a single HTTP request can send multiple queries/mutations so the HTTP request contextual name would be hard to derive here.