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

Improving make_filtering_bound_logger's compatibility with the stdlib logger #469

Open
segfault opened this issue Nov 14, 2022 · 3 comments

Comments

@segfault
Copy link

segfault commented Nov 14, 2022

While trying to use structlog as a drop in for the stdlib logger usage in slack_bolt, I encountered a variety of errors stemming from missing wrapper implementations.

Error example:

AttributeError: 'BoundLoggerFilteringAtDebug' object has no attribute 'disabled'

The root cause appears to be make_filtering_bound_logger's usage of BoundLoggerBase instead of the fully implemented BoundLogger. BoundLogger itself is missing the filters wrapper, but that is trivial to fix. BoundLoggerBase is missing all of the wrapper logic and that appears intentional.

With an analog to BoundLogger implemented I am able to use structlog as a drop-in replacement for the standard logger.

I'll be tying in a pull request with a proposed solution.

segfault added a commit to segfault/structlog that referenced this issue Nov 14, 2022
As noted in hynek#469, `make_filtering_bound_logger` was returning
a `BoundLoggerBase` with minimal functionality. These changes
refactor the `BoundLogger` definition to avoid circular dependencies
and allow for it's use in `make_filtering_bound_logger`.
@segfault segfault mentioned this issue Nov 14, 2022
8 tasks
@hynek
Copy link
Owner

hynek commented Nov 14, 2022

Let's discuss this here, before delving into #470.

What you're doing there is basically re-implementing parts of our stdlib integration.

I'm sympathetic to wanting a true drop-in replacement, but that's what literally what https://www.structlog.org/en/latest/api.html#structlog.stdlib.BoundLogger is for (along with all the goodies).


If you want to gradually switch away from stdlib APIs, but use the faster loggers from make_filtering_bound_logger now, I would suspect the best way would be to create a logger using make_filtering_bound_logger and then add stub methods that can still be called, but don't do any anything.

Does that make sense? Essentially:

import structlog
import logging


FL = structlog.make_filtering_bound_logger(logging.INFO)


class StubFilteringLogger(FL):
    @property
    def disabled(self):
        return False


structlog.configure(wrapper_class=StubFilteringLogger)

logger = structlog.get_logger()

logger.info("hi", disabled=logger.disabled)

I might be open to add such a stub logger to structlog, but I'm not sure if it's possible those stubs make universally useful?

@segfault
Copy link
Author

So my intent was to we-use the existing implementation instead of mirroring the behavior in order to get something that would be performant when filtering leveled log messages but compatible with stdlib logger use I'm encountering "in the wild".

I started with generating my ownStubFilteringLogger but quickly found myself effectively re-implementing everything in stdlib.BoundLogger.

Alternatively would a make_filtering_stdlib_bound_logger be acceptable? Ultimately the intent here is just to swap the base class and hopefully use all of the same existing well-optimized/tested code.

@segfault
Copy link
Author

I should note that my use case here isn't gradual replacement. It's supporting third party libraries and frameworks that use the stdlib logger interface. If I had control I'd just use structlog natively everywhere.

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

Successfully merging a pull request may close this issue.

2 participants