Files
spring-graphql/spring-graphql-docs/modules/ROOT/pages/observability.adoc
Brian Clozel 594c9dfc4f Add DataLoader observability support
Prior to this commit, the `GraphQlObservationInstrumentation` would
instrument the following operations:

* GraphQL requests
* GraphQL data fetching operations

In the case of batch loading operations, the instrumentation would
consider each load call as a separate data fetching operation. This
would significantly clutter recorded traces and would make it look like
"N+1 problems" would still be present.

This commit adds a new "graphql.dataloader" observation for such
operations and avoids recording data fetching observations when
`SelfDescribingDataFetcher` declare that they call batch loading
operations.

Closes gh-1034
2025-04-07 15:30:13 +02:00

110 lines
5.8 KiB
Plaintext

[[observability]]
= Observability
https://docs.micrometer.io/micrometer/reference/observation.html[Observability support with Micrometer] is directly instrumented in Spring for GraphQL.
This enables both metrics and traces for GraphQL requests and "non-trivial" data fetching operations.
Because the GraphQL engine operates on top of a transport layer, you should also {spring-framework-ref-docs}/integration/observability.html[expect observations from the transport], if supported in Spring Framework.
Observations are only published if an `ObservationRegistry` is configured in the application.
You can learn more about {spring-boot-ref-docs}/reference/actuator/metrics.html[configuring the observability infrastructure in Spring Boot].
If you would like to customize the metadata produced with the GraphQL observations, you can {spring-framework-ref-docs}/integration/observability.html#observability.config.conventions[configure a custom convention on the instrumentation directly].
If your application is using Spring Boot, contributing the custom convention as a bean is the preferred way.
[[observability.server.request]]
== Server Requests instrumentation
GraphQL Server Requests observations are created with the name `"graphql.request"` for traditional and Reactive applications and above all supported transports.
This instrumentation assumes that any parent observation must be set as the current one on the GraphQL context with the well-known `"micrometer.observation"` key.
For trace propagation across network boundaries, a separate instrumentation at the transport level must be in charge.
In the case of HTTP, Spring Framework {spring-framework-ref-docs}/integration/observability.html#observability.http-server[has dedicated instrumentation that takes care of trace propagation].
Applications need to configure the `org.springframework.graphql.observation.GraphQlObservationInstrumentation` instrumentation in their application.
It is using the `org.springframework.graphql.observation.DefaultExecutionRequestObservationConvention` by default, backed by the `ExecutionRequestObservationContext`.
By default, the following KeyValues are created:
.Low cardinality Keys
[cols="a,a"]
|===
|Name | Description
|`graphql.operation` _(required)_|GraphQL Operation name.
|`graphql.outcome` _(required)_|Outcome of the GraphQL request.
|===
The `graphql.operation` KeyValue will use the custom name of the provided query, or http://spec.graphql.org/draft/#sec-Language.Operations[the standard name for the operation] if none (`"query"`, `"mutation"` or `"subscription"`).
The `graphql.outcome` KeyValue will be:
* `"SUCCESS"` if a valid GraphQL response has been sent and it contains no errors
* `"REQUEST_ERROR"` if the request could not be parsed, or if the response contains errors (none of them being of type `org.springframework.graphql.execution.ErrorType.INTERNAL_ERROR`)
* `"INTERNAL_ERROR"` if no valid GraphQL response could be produced, or if the response contains at least one error of type `org.springframework.graphql.execution.ErrorType.INTERNAL_ERROR`
.High cardinality Keys
[cols="a,a"]
|===
|Name | Description
|`graphql.execution.id` _(required)_|`graphql.execution.ExecutionId` of the GraphQL request.
|===
Spring for GraphQL also contributes Events for Server Request Observations.
https://docs.micrometer.io/micrometer/reference/observation/components.html#micrometer-observation-events[Micrometer Observation Events] are usually handled as span annotations in traces.
This instrumentation records errors listed in the GraphQL response as events.
.Observation Events
[cols="a,a"]
|===
|Name | Contextual Name
|the GraphQL error type, e.g. `InvalidSyntax`|the full GraphQL error message, e.g. `"Invalid syntax with offending token 'invalid'..."`
|===
[[observability.server.datafetcher]]
== DataFetcher instrumentation
GraphQL DataFetcher observations are created with the name `"graphql.datafetcher"`, only for data fetching operations that are considered as "non trivial" (property fetching on a Java object is a trivial operation).
Applications need to configure the `org.springframework.graphql.observation.GraphQlObservationInstrumentation` instrumentation in their application.
It is using the `org.springframework.graphql.observation.DefaultDataFetcherObservationConvention` by default, backed by the `DataFetcherObservationContext`.
By default, the following KeyValues are created:
.Low cardinality Keys
[cols="a,a"]
|===
|Name | Description
|`graphql.error.type` _(required)_|Class name of the data fetching error
|`graphql.field.name` _(required)_|Name of the field being fetched.
|`graphql.outcome` _(required)_|Outcome of the GraphQL data fetching operation, "SUCCESS" or "ERROR".
|===
.High cardinality Keys
|===
|Name | Description
|`graphql.field.path` _(required)_|Path to the field being fetched (for example, "/bookById").
|===
[[observability.server.dataloader]]
== DataLoader instrumentation
GraphQL DataLoader observations are created with the name `"graphql.dataloader"`, observing calls to `@BatchMapping` controller methods and manually registered `DataLoader` instances.
Applications need to configure the `org.springframework.graphql.observation.GraphQlObservationInstrumentation` instrumentation in their application.
It is using the `org.springframework.graphql.observation.DefaultDataLoaderObservationConvention` by default, backed by the `DataLoaderObservationContext`.
By default, the following KeyValues are created:
.Low cardinality Keys
[cols="a,a"]
|===
|Name | Description
|`graphql.error.type` _(required)_|Class name of the data fetching error
|`graphql.loader.type` _(required)_|Class name of the elements being fetched.
|`graphql.outcome` _(required)_|Outcome of the GraphQL data fetching operation, "SUCCESS" or "ERROR".
|===
.High cardinality Keys
|===
|Name | Description
|`graphql.loader.size` _(required)_|Size of the list of loaded elements.
|===