New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Plugin didEncounterErrors should allow a way to add additional information from context #4351
Comments
|
Another Problem is: The error object in formatError contains additional data of the original error. This is completely missing in all ApolloServer plugin hooks. The error object there is already a stripped and formatted version by ApolloServer and so we cant use that for logging details of e.g. database errors. We simply need: formatError with context... this will solve all problems My current use case is: I want to use Sentry to log errors in Graphql resolvers. I want to put all the query details into the Sentry meta informations. This are only available during formatError, however i need the context to access request information to have them as well in the Sentry meta informations. So there is just no way around either fixing the Plugin hooks to expose the original error or adding context to formatError. |
|
There are use cases to propagate information with error, which is request-specific. This would be nice to have. Think about request traceability between multiple components, Apollo GW -> Apollo Server. HTTP header have transaction unique identifier ( |
|
I just write the plugin and it works properly: Edited: Warning!!!! Don't use the code below, I just keep it for documention purposes. see the new answer module.exports = {
requestDidStart: (reqCtx) => {
return {
didEncounterErrors: ({ errors, request, context }) => {
errors.forEach(({ extensions }) => {
extensions.request = request;
extensions.context = context;
})
},
}
},
}Note: delete formatError.js const handler = (error) => {
const context = error.extensions.context;
// do something with context...
delete error.extensions["context"];
return error;
} |
|
|
Unfortunately Yes! we can use the module.exports = {
requestDidStart: (reqCtx) => {
return {
didEncounterErrors: ({ errors, request, context }) => {
errors.forEach(error => {
const msg = error.message;
error.message = {
request,
context,
toString: () => msg,
}
})
},
}
},
}Then we can access additional info in formatError and change message to the default string format (for serializing purposes): const handler = (error) => {
const { message, locations, path, extensions = {} } = error;
const { request, context } = message;
error.message = message + "";
return error;
} |
|
This seems valuable but I'm going to remove it from AS3 blockers because I don't think fixing this needs to be a breaking change: we can start passing context as a second argument to It's tempting to just drop the |
|
The alternative is to allow the modification of extensions in the plugin. Which would be a good thing anyway IMO. |
|
The challenge is that extensions are readonly on the core GraphQLError, not something that's part of apollo-server... We could I suppose provide a mechanism for letting you replace specific errors in the list. Or just document it as "if you delete all the errors, you get to keep both pieces". |
|
Can I just do a plus one for adding the context to the error formater? I'm trying to get operationName and the variables on the error but this is very difficult currently. |
|
@IvanGoncharov I wonder if you have any thoughts on this? I know you've been thinking about how to simplify |
|
another question on this - why is the error type on didencountererrors and formatError 'GraphqlError' and not 'ApolloError'? Thrown apollo errors lose their codes and make defining them totally pointless? |
|
Would it be possible to have some/all plugins run after formatError? We are having the same issue of needing to log errors, but we do classification and tagging of the errors using information that is only available in the extensions field available in the formatError lifecycle. We considered moving a "formatError" plugin before the other plugins, but the errors available to plugings are readonly and sometimes lack the extensions or originalError fields. |
@glasser Sorry, lost it in my GH inbox.
In general: I think we need to overhaul error handling both in AS and graphql-js |
|
How are you supposed to decorate an error object in a plugin if they are readonly? +1 to overhauling error handling. This area feels very circular. You can transform in formatError but can't access the request context for logging/tracing, and in plugins you can do so but get the error before it is transformed and can't pipeline the data you need by adding fields |
|
Please add a context to |
|
@simlu Part of the challenge here is that formatError can be called both from within the "request pipeline" once the context is set up... or earlier because there's a problem recognizing the request at all. So it's challenging to consistently provide useful context to this function. But perhaps we could at least add the GraphQLRequest context as a parameter to the function when it is invoked from the request pipeline, and leave it null when invoked from "parsing the request"? @IvanGoncharov thoughts? |
|
We would also like a way to add to |
|
I put some effort into making modifying the errors array (as opposed to just mutating the errors in it) OK in #6927. But I reverted it in #6931. Allowing you to remove all the errors from the array led to weird cases when, eg, it was a parse or validation error: suddenly the request pipeline is trying to issue a parse error that has no errors? A valid option here would be to do the handling in |
As per other issues, the current recommended way to access the context when handling error in a plugin is to use the hook
didEncounterErrors. Something similar to:The problem is that those error are all
readonlyand cannot really be modified. For example, it is not possible to addextensionsif the caller did not define it as not null. Thus there is not reliable way to add information to the error that could be used byformatErrordown the line.A very common use case is adding a request ID to the extensions in case of an error so we can match the backend logs with the frontend error. My current work around is to add the information to the
originalError:And then read it back in the
formatErrorto add it to the extensions. But I realized recently thatoriginalErroris not always set, so my workaround fails sometimes. We also have to note that properties attached to theGraphQLErrorsent todidEncounterErrorsare not carried over informatErrorsfor some reason.For all those reasons, I think there should be an official way to deal with that problem since it was possible to do it with
Extensionsthat are now deprecated.The text was updated successfully, but these errors were encountered: