pythonloggingquarthypercorn

How can I change the debug-level and format for the Quart (i.e. hypercorn) logger?


I'm trying to set the level and format for the loggers used by the Quart module the way I did it successfully for other 'foreign' loggers:

However those approaches don't work for the loggers spawned by Quart. Neither are those affected by basicConfig nor can I set the level. Output will always look like this:

[2023-07-28 16:17:12 +0200] [1254610] [INFO] Running on http://0.0.0.0:5432 (CTRL + C to quit)

Setting breakpoints in logging/__init__.py let the program break on log messages by hypercorn.error (so it seems to use the same module), but setting the level like this

logging.getLogger("hypercorn.error").setLevel(logging.WARNING)

doesn't have any effect.

The doc says I should use dictConfig, so I've added

dictConfig({
    'version': 1,
    'loggers': {
        'quart.app': {'level': 'ERROR'},
        'hypercorn.error': {'level': 'ERROR'},
    },
})

.. no effect

I found https://github.com/pgjones/hypercorn/issues/120, and tried

logger = logging.getLogger("hypercorn.error")
logger.addHandler(my_own_handler)
logger.setLevel(logging.WARNING)
logger.propagate = False

but also without effect.

What else can I try?


Solution

  • I had the same issue recently, and it was a real headache to find how to solve it, but here is my solution:

    First, for clarity, I defined a function that takes a logger as an input and that patches the logger how I want it.

    import logging
    
    
    def patch_logger(logger_: logging.Logger):
        logger_.handlers = []  # Clear any existing handlers
        logger_.addHandler(file_handler)
        logger_.addHandler(console_handler)
        logger_.propagate = False
        logger_.setLevel(level)
        return logger_
    

    Then later when running my app, I subclassed the HypercornLogger to have it patch its own loggers:

    from hypercorn.config import Config
    from hypercorn.logging import Logger as HypercornLogger
    from hypercorn.asyncio import serve
    
    
    class CustomLogger(HypercornLogger):
        def __init__(self, *args, **kwargs) -> None:
            super().__init__(*args, **kwargs)
            if self.error_logger:
                patch_logger(self.error_logger)
            if self.access_logger:
                patch_logger(self.access_logger)
    
    app_config = Config()
    app_config.logger_class = CustomLogger
    

    The patch_logger function can really be anything you want to change to your logger, what I did is just an example.