# (*) Proactive Feedback
GraphQL servers usually do not offer good contextual information when running queries, because the GraphQL spec does not force them (or even suggest) to do so. This is evident concerning deprecations, where deprecation data is shown only through introspection, by querying fields isDeprecated
and deprecationReason
on the Field
and Enum
types:
{
__type(name: "Account") {
name
fields {
name
isDeprecated
deprecationReason
}
}
}
The response will be:
{
"data": {
"__type": {
"name": "Account",
"fields": [
{
"name": "id",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "surname",
"isDeprecated": true,
"deprecationReason": "Use `personSurname`"
},
{
"name": "personSurname",
"isDeprecated": false,
"deprecationReason": null
}
]
}
}
}
However, when running a query involving a deprecated field, like this one:
query GetSurname {
account(id: 1) {
surname
}
}
...the deprecation information will not appear in the response:
{
"data": {
"account": {
"surname": "Owens"
}
}
}
This means that the developer executing the query must actively execute introspection queries to find out if the schema was upgraded and any field deprecated. That may happen maybe once in a long while? Quite possibly never?
# Providing proactive feedback
GraphQL by PoP addresses this deficiency by making use of the wildcard top-level entry extensions
, which allows to extend the protocol as needed. Under this entry, when running any query, GraphQL by PoP may send data through the following feedback entries:
deprecations
warnings
logs
notices
traces
Because they are sent on the response to the query itself, and not just during introspection, this data is valuable to developers of the API-consuming application to understand how to better interact with the API.
Let's explore these entries.
# Deprecations
Deprecations are returned in the same query involving deprecated fields, and not only when doing introspection.
For instance, running this query:
query {
posts {
title
isPublished
}
}
...produces response:
{
"extensions": {
"deprecations": [
{
"message": "Use 'isStatus(status:published)' instead of 'isPublished'",
"extensions": {
...
}
}
]
},
"data": {
"posts": [
...
]
}
}
# Warnings
Warning are issues which can be considered non-blocking, i.e. they enhance the query but do not break it. While in standard GraphQL they would be considered errors, GraphQL by PoP takes a more lenient approach towards them, by ignoring their execution only, and not the whole query.
For instance, passing parameter limit
with the wrong type will not stop execution of the query, it will just ignore this parameter (hence, the response will bring more results that are needed, but that's not a breaking issue) and provide an appropriate warning
message.
Executing this query:
query {
posts(limit:3.5) {
title
}
}
...produces this response:
{
"extensions": {
"warnings": [
{
"message": "For field 'posts', casting value '3.5' for argument 'limit' to type 'int' failed, so it has been ignored",
"extensions": {
...
}
}
]
},
"data": {
"posts": [
...
]
}
}
# Logs
Any resolver (for fields and directives) can log any piece of information, as to provide the developer with useful information to debug the application.
Showing logs in the response
Logs are retrieved by passing parameter actions[]=show-logs
to the GraphQL endpoint /api/graphql/
.
In this query, directive @traceExecutionTime
informs the execution time of resolving the field through the log:
query {
post(id:1) {
title @traceExecutionTime
}
}
Showing logs in the response
This query calls the GraphiQL client with parameter show_logs=true
, and then GraphiQL sets actions[]=show-logs
on the endpoint.
View PQL query
/?
actions[]=show-logs&
postId=1&
query=
post(id:$postId).
title<traceExecutionTime>
# Notices
TODO
# Traces
TODO