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

[BoundLogger].exception() fails with structlog._generic.BoundLogger #200

cognitiaclaeves opened this issue Mar 12, 2019 · 2 comments


Copy link

@cognitiaclaeves cognitiaclaeves commented Mar 12, 2019


logger = wrap_logger(
        # wrapper_class=structlog.stdlib.BoundLogger,
        # wrapper_class=BoundLoggerWexc,

This code:

        except ZeroDivisionError as zde:
            logger.exception('Test exception OK')

will not have the same result if wrapper_class is not set ( and uses the default generic BoundLogger ) as it does when explicitly setting structlog.stdlib.BoundLogger.

I solved the issue in my code with this:

class BoundLoggerWexc(structlog._generic.BoundLogger ):

    def exception(self, event=None, *args, **kw):
        Process event and call :meth:`logging.Logger.error` with the result,
        after setting ``exc_info`` to `True`.
        kw.setdefault("exc_info", True)
        return self.error(event, *args, **kw)

( The exception def is the same one in stdlib's BoundLogger. )

For me, this was kind of a big deal because I was rendering logs to JSON, and it ended up looking like this:

['{"event": "Test exception OK", "level": "exception", "path": "/Users/jason.norment/gitrepo/assess-pythag/pythagoras/pythagoras/tests/", "function": "pythagoras.tests.test_logger.test_log_exception", "lineno": 163, "timestamp": "2019-03-12T20:21:56.529188Z"}\nTraceback (most recent call last):\n File "/Users/jason.norment/gitrepo/assess-pythag/pythagoras/pythagoras/tests/", line 161, in test_log_exception\n 1/0\nZeroDivisionError: division by zero']

( Note the way the trace-back is just tacked onto the end of the JSON, thus rendering invalid JSON. )

After my fix, the JSON validates:

['{"event": "Test error w/ exc_info", "level": "error", "path": "/Users/jason.norment/gitrepo/assess-pythag/pythagoras/pythagoras/tests/", "function": "pythagoras.tests.test_logger.test_log_exception", "lineno": 148, "exception": "Traceback (most recent call last):\n File \"/Users/jason.norment/gitrepo/assess-pythag/pythagoras/pythagoras/tests/\", line 146, in test_log_exception\n 1/0\nZeroDivisionError: division by zero", "timestamp": "2019-03-12T20:21:56.528610Z"}']

The above renders correctly with the default _generic.BoundLogger if I use this statement:

        except ZeroDivisionError as zde:
            logger.error('Test exception OK', exc_info=True)

But I didn't want to force exc_info to be passed, or force logger.exception() not to be used. (And I wanted to use the default BoundLogger, if possible.)

Copy link

@hynek hynek commented Mar 19, 2019

Just so I understand you correctly: you want to wrap a standard lib logger (app.log), but you don't want to use structlog's stdlib.BoundLogger? Any specific reason?

I'm afraid changing the behavior of the vanilla BoundLogger would break b/w compatibility. Unless we make it a flag on instantiation I guess.

Copy link

@hynek hynek commented Sep 21, 2019

Fixed in de4ef4e

@hynek hynek closed this Sep 21, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants