wimglenn / pytest-structlog

Structured logging assertions
MIT License
56 stars 6 forks source link

Version 0.3 breaks with django (structlog is configured in its settings.py file). #12

Closed skoot closed 3 years ago

skoot commented 4 years ago

Version 0.3 breaks our tests. We use django and configure structlog in our settings.py file.

structlog.configure(
    processors=[
        structlog.stdlib.filter_by_level,
        structlog.processors.TimeStamper(),
        structlog.stdlib.add_logger_name,
        structlog.stdlib.add_log_level,
        structlog.stdlib.PositionalArgumentsFormatter(),
        structlog.processors.StackInfoRenderer(),
        structlog.processors.format_exc_info,
        structlog.processors.UnicodeDecoder(),
        structlog.processors.ExceptionPrettyPrinter(),
        structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
    ],
    context_class=structlog.threadlocal.wrap_dict(dict),
    logger_factory=structlog.stdlib.LoggerFactory(),
    wrapper_class=structlog.stdlib.BoundLogger,
    cache_logger_on_first_use=True,
)

When we run the tests we now get this error:

logger = <PrintLogger(file=<_io.TextIOWrapper name="<_io.FileIO name=8 mode='rb+' closefd=True>" mode='r+' encoding='utf-8'>)>
name = 'error'
event_dict = {'client': 'test_client', 'duration': 0.051772, 'event': 'campaign-list.create', 'headers': {'Authorization': '***', 'Content-Length': '185', 'Content-Type': 'application/json; charset=None', 'Cookie': ''}, ...}

    def filter_by_level(logger, name, event_dict):
        """
        Check whether logging is configured to accept messages from this log level.

        Should be the first processor if stdlib's filtering by level is used so
        possibly expensive processors like exception formatters are avoided in the
        first place.

        >>> import logging
        >>> from structlog.stdlib import filter_by_level
        >>> logging.basicConfig(level=logging.WARN)
        >>> logger = logging.getLogger()
        >>> filter_by_level(logger, 'warn', {})
        {}
        >>> filter_by_level(logger, 'debug', {})
        Traceback (most recent call last):
        ...
        DropEvent
        """
>       if logger.isEnabledFor(_NAME_TO_LEVEL[name]):
E       AttributeError: 'PrintLogger' object has no attribute 'isEnabledFor'

Originally posted by @skoot in https://github.com/wimglenn/pytest-structlog/issues/10#issuecomment-686408689

menecio commented 4 years ago

I'm having the same error using this config:

structlog.configure(
    processors=[
        structlog.stdlib.filter_by_level,
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.stdlib.add_logger_name,
        structlog.stdlib.add_log_level,
        structlog.stdlib.PositionalArgumentsFormatter(),
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.processors.StackInfoRenderer(),
        structlog.processors.format_exc_info,
        structlog.processors.UnicodeDecoder(),
        structlog.processors.ExceptionPrettyPrinter(),
        structlog.dev.ConsoleRenderer(),
    ],
    context_class=structlog.threadlocal.wrap_dict(dict),
    logger_factory=structlog.stdlib.LoggerFactory(),
    wrapper_class=structlog.stdlib.BoundLogger,
    cache_logger_on_first_use=True,
)
menecio commented 4 years ago

I realised that it only happened to me when I was running all tests but not when running one specific test, so looking around I found this https://github.com/hynek/structlog/issues/76#issuecomment-240373958, which right away fixed my issue. Hope it helps.

wimglenn commented 3 years ago

@skoot @menecio I believe this should be resolved in v0.4, would you mind to try it out and report back please?

skoot commented 3 years ago

Happy to report that it seems to have fixed the issue for us.