-
Notifications
You must be signed in to change notification settings - Fork 765
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
How to capture exceptions? #124
Comments
Hi @MrTin, There are few ways for catching the exceptions that class SentryMiddleware(object):
def on_error(self, error):
# report error to sentry
def resolve(self, next, root, args, context, info):
return next(root, args, context, info).catch(self.on_error) Here are the docs for Middleware in graphene: http://docs.graphene-python.org/en/latest/execution/middleware/ Hope this helps! |
Hi @syrusakbary Sorry for my late reply – thank you very much for taking the time to reply. If I understand this solution correct it requires me to add this middleware manually to each query? Or is there a way to set middlewares for all my queries in one place? |
@syrusakbary I gave this a go but catch was never actually called (I was just raising an exception in a resolve_ method) - it looked like the exceptions were just collected on the execution context. An alternative solution I found was to check
Thanks! |
I'm seeing the same issue as @sdcooke . Looking at this line: https://github.com/graphql-python/graphql-core/blob/master/graphql/execution/middleware.py#L57 def make_it_promise(next, *a, **b):
return Promise.resolve(next(*a, **b)) It runs the execution, then places the result in a promise. So if Changing it to the following allows the middleware to catch errors: def make_it_promise(next, *a, **b):
return Promise.promisify(lambda: next(*a, **b))() However that breaks down execution in other places. i.e. Some parts of the code and @syrusakbary above seem to assume |
I'm really struggling in catching exception on graphQL. The middelWare seems unhelpful as he is not triggered when there is an exception and the propagation stop before the middleware. (So it swallows all the client / server communication EVEN with a middleware) |
Unfortunately, I never got around trying this out and ended up with my original solution using a custom GraphQLView. You can grab the full solution and read why in my article on medium. Here's also the code if you just want the solution: # views.py
from graphene_django.views import GraphQLView
from raven.contrib.django.raven_compat.models import client as sentry_client
class SentryGraphQLView(GraphQLView):
def execute_graphql_request(self, *args, **kwargs):
"""Extract any exceptions and send them to Sentry"""
result = super().execute_graphql_request(*args, **kwargs)
if result.errors:
for error in result.errors:
try:
raise error.original_error
except Exception:
sentry_client.captureException()
return result
# urls.py
from .views import SentryGraphQLView
urlpatterns = [
url(r'^graphql', SentryGraphQLView.as_view(schema=schema)),
] |
Has this been resolved in graphene? I am seeing graphene exceptions in Sentry and I don't recall implementing any workarounds (with graphene==2.0.1, graphene-django==2.0.0, raven==6.6.0). Or is this a side-effect of using |
The @syrusakbary 's solution works well, actually, with the latest version of As a work-around, for previous versions of import sys
import logging
class SentryMiddleware(object):
def resolve(self, next, root, info, **args):
try:
return next(root, info, **args)
except:
err = sys.exc_info()
logging.error(err)
return err[1] |
Is it a good idea to add logging statements to |
The middleware solution does not catch exceptions in dataloaders; |
Here's @MrTin's solution updated to Sentry unified Python SDK: from sentry_sdk import capture_exception
class SentryGraphQLView(GraphQLView):
def execute_graphql_request(self, *args, **kwargs):
"""Extract any exceptions and send them to Sentry"""
result = super().execute_graphql_request(*args, **kwargs)
if result.errors:
for error in result.errors:
try:
raise error.original_error
except Exception as e:
capture_exception(e)
return result
# In routes:
path('graphql', csrf_exempt(SentryGraphQLView.as_view(graphiql=True))), |
After I updated to sentry_sdk, I started receiving the correct data exceptions in Sentry, without any addition changes to views or middleware. The errors were double-reported as GraphQLLocatedError errors, so I added a filter to remove them:
|
Closing since this issue is not specific to graphene-django |
In case this helps someone - the class based middleware didn't work for me, but this function based middleware did:
then in our settings:
|
Hi there, chiming in - if by chance you're seeing stuff like this: Check around for Your sentry may be set to listen to https://github.com/graphql-python/graphql-core/blob/v2.3.1/graphql/execution/utils.py#L155 To get around this, it may be necessary to ignore this logger through sentry: from sentry_sdk.integrations.logging import ignore_logger
ignore_logger("graphql.execution.utils") Credits go to @malthejorgensen if this is helpful to you |
Combining @tony's snippet with some previously posted snippets I'm using this config to properly log errors to sentry without changing anything in graphene. This config will log the errors only once in Sentry and they will have the full inspectable stacktrace. # Ignore this logger because it logs errors as strings instead of actual errors
# and we lose a lot of Sentry's features. Instead use SentryMiddleware.
from sentry_sdk.integrations.logging import ignore_logger
ignore_logger('graphql.execution.utils')
class SentryMiddleware(object):
"""
Properly capture errors during query execution and send them to Sentry.
Then raise the error again and let Graphene handle it.
"""
def on_error(self, error):
capture_exception(error)
raise error
def resolve(self, next, root, info, **args):
return next(root, info, **args).catch(self.on_error)
# In your settings.py:
GRAPHENE = {
'MIDDLEWARE': [
'core.schema.SentryMiddleware',
# Other middleware if any.
],
# Other graphene specific settings if any.
} Versions: |
Sure would be nice if middleware.on_error was in the docs! |
This doesn't work yet, but according to some Github issue it's the right direction: graphql-python/graphene-django#124
* [BACK-585] Add Sentry middleware to GraphQL This doesn't work yet, but according to some Github issue it's the right direction: graphql-python/graphene-django#124 * WIP local Sentry debugging * Fixed logging exceptions to Sentry * Ignore graphql logger * Add comment * Added comment about ignoring graphql logger
I guess there was a reason this was undocumented -- this appears to have been removed in Graphene v3 |
This workaround works for me - it's not Sentry but could be adapted:
|
We're trying to forward exceptions to Sentry but it seems the graphene-django seems to be swallowing everything. Is there any way to catch the exception and send it to Sentry?
Thank you!
Regards,
Martin
The text was updated successfully, but these errors were encountered: