Skip to content
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

Exception traceback disappears when running middleware #208

Open
flacerdk opened this issue Sep 24, 2018 · 3 comments
Open

Exception traceback disappears when running middleware #208

flacerdk opened this issue Sep 24, 2018 · 3 comments

Comments

@flacerdk
Copy link

Here's a small example that illustrates the issue:

import logging

import graphene

logging.basicConfig()


class Query(graphene.ObjectType):
    hello = graphene.String()

    def resolve_hello(self, info):
        raise Exception('error')
        return 'Hello'


schema = graphene.Schema(query=Query)


def middleware(next, root, info, **kwargs):
    return next(root, info, **kwargs)

If we execute a query without any middleware, we get the traceback:

In [3]: schema.execute('{ hello }')
ERROR:graphql.execution.executor:An error occurred while resolving field Query.hello
Traceback (most recent call last):
  File "/home/felipe/.local/share/virtualenvs/graphene-hello-viSdSxbU/local/lib/python2.7/site-packages/graphql/execution/executor.py", line 447, in resolve_or_error
    return executor.execute(resolve_fn, source, info, **args)
  File "/home/felipe/.local/share/virtualenvs/graphene-hello-viSdSxbU/local/lib/python2.7/site-packages/graphql/execution/executors/sync.py", line 16, in execute
    return fn(*args, **kwargs)
  File "<ipython-input-1-89a125ef67fc>", line 12, in resolve_hello
    raise Exception('error')
Exception: error
ERROR:graphql.execution.utils:Traceback (most recent call last):
  File "/home/felipe/.local/share/virtualenvs/graphene-hello-viSdSxbU/local/lib/python2.7/site-packages/graphql/execution/executor.py", line 447, in resolve_or_error
    return executor.execute(resolve_fn, source, info, **args)
  File "/home/felipe/.local/share/virtualenvs/graphene-hello-viSdSxbU/local/lib/python2.7/site-packages/graphql/execution/executors/sync.py", line 16, in execute
    return fn(*args, **kwargs)
  File "<ipython-input-1-89a125ef67fc>", line 12, in resolve_hello
    raise Exception('error')
GraphQLLocatedError: error

But if we run it with the middleware, we get very little information:

In [4]: schema.execute('{ hello }', middleware=[middleware])
ERROR:graphql.execution.utils:GraphQLLocatedError: error

While investigating the issue, it looks like the point the traceback gets lost is around https://github.com/graphql-python/graphql-core/blob/master/graphql/execution/executor.py#L529. The promise gets rejected because of the exception, and then the is_reject handler returns another promise that gets immediately rejected. This new error has no traceback, so it doesn't get logged when it's caught inside complete_value_catching_error.

@maebert
Copy link

maebert commented Mar 20, 2019

Is there a good workaround for this until this is fixed in graphql-core?

@ProjectCheshire
Copy link
Member

ProjectCheshire commented Mar 20, 2019

@maebert this could be tidied up, but I'm using this middleware which seems to work well. (obv switch out so it raises what is useful to you, I send things to sentry.io so they weren't relevant to include but you get the idea)

from api.utils.logging import get_logger


class LoggingMiddleware(object):
    @staticmethod
    def resolve(next, root, info, **args):
        logger = get_logger('ctx_logging')
        try:
            return next(root, info, **args)
        except Exception as e:
            logger.error(e)
            logger.warn(args)
            logger.debug(
                "{parent_type}.{field_name}".format(
                    parent_type=root._meta.name
                    if root and hasattr(root, "_meta")
                    else "",
                    field_name=info.field_name,
                )
            )
            raise

@lucassimon
Copy link

lucassimon commented Sep 27, 2019

This traceback it's just print on console? Because the tests ran ok.

from graphql import GraphQLError

from .auth import get_authorization_header, decode_token


class AuthorizationMiddleware(object):
    def resolve(self, next, root, info, **args):
        try:
            token = get_authorization_header(info.context.META)
            decode_token(token)
        except GraphQLError as e:
            raise e

        # TODO: get the user in payload
        return next(root, info, **args)
class AllTestCase(GraphQLTestCase, GenerateToken):
    def make_request(self, headers=None):
        token = self.make_jwt().decode('utf-8')
        if headers is None:
            headers = {'Authorization': f'Bearer {token}'}

        response = self._client.post(
            self.GRAPHQL_URL, json.dumps({"query": self.QUERY}), content_type="application/json",
            headers=headers
        )
          return response

    def test_should_returns_error_response_without_headers(self):
        headers = {}
        response = self.make_request(headers)

        content = json.loads(response.content)
        self.assertTrue(content['data']['all'] is None)
        self.assertResponseHasErrors(response)
$ python manage.py test -k
Using existing test database for alias 'default'...
System check identified no issues (0 silenced).
...An error occurred while resolving field Query.all
Traceback (most recent call last):
  File "/Users/lucas/.virtualenvs/invoice/lib/python3.7/site-packages/graphql/execution/executor.py", line 450, in resolve_or_error
    return executor.execute(resolve_fn, source, info, **args)
  File "/Users/lucas/.virtualenvs/invoice/lib/python3.7/site-packages/graphql/execution/executors/sync.py", line 16, in execute
    return fn(*args, **kwargs)
  File "/Users/lucas/dev/projects/invoice-service/utils/middleware.py", line 10, in resolve
    token = get_authorization_header(info.context.META)
  File "/Users/lucas/dev/projects/invoice-service/utils/auth.py", line 14, in get_authorization_header
    raise GraphQLError(Messages.AUTH_NOT_FOUND_AUTHORIZATION.value)
graphql.error.base.GraphQLError: Not found Authorization.
Traceback (most recent call last):
  File "/Users/lucas/.virtualenvs/invoice/lib/python3.7/site-packages/graphql/execution/executor.py", line 450, in resolve_or_error
    return executor.execute(resolve_fn, source, info, **args)
  File "/Users/lucas/.virtualenvs/invoice/lib/python3.7/site-packages/graphql/execution/executors/sync.py", line 16, in execute
    return fn(*args, **kwargs)
  File "/Users/lucas/dev/projects/invoice-service/utils/middleware.py", line 10, in resolve
    token = get_authorization_header(info.context.META)
  File "/Users/lucas/dev/projects/invoice-service/utils/auth.py", line 14, in get_authorization_header
    raise GraphQLError(Messages.AUTH_NOT_FOUND_AUTHORIZATION.value)
graphql.error.located_error.GraphQLLocatedError: Not found Authorization.

.........................................

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants