Search code examples
pythonloggingpython-logging

How can I ignore empty log messages?


I use sanic framework.

I add log module and saw strange logs like this:

[2023-05-02 19:25:40 +0900] - (sanic.access)[INFO][127.0.0.1:34844]: GET http://127.0.0.1/api/v1/ta?idtype=1  200 7559
[2023-05-02 19:25:40,969] [INFO] 
[2023-05-02 19:25:40 +0900] - (sanic.access)[INFO][127.0.0.1:34846]: GET http://127.0.0.1/api/v1/sa?idtype=1  200 84895
[2023-05-02 19:25:43,857] [INFO] 
[2023-05-02 19:25:43 +0900] - (sanic.access)[INFO][127.0.0.1:34846]: GET http://127.0.0.1/api/v1/to?type=I&idtype=2  200 26729
[2023-05-02 19:25:43 +0900] - (sanic.access)[INFO][127.0.0.1:34842]: GET http://127.0.0.1/api/v1/ta?idtype=2  200 6233
[2023-05-02 19:25:43,870] [INFO] 
[2023-05-02 19:25:43,877] [INFO] 

I never wrote empty logs, so I check call stacks.

lower is part of call stack.

[13] -   File "/home/deploy/utils/miniconda3/lib/python3.7/site-packages/sanic/response.py", line 122, in send
    await self.stream.send(data, end_stream=end_stream)

[14] -   File "http1_response_header", line 68, in http1_response_header
    HEADER_CEILING = 16_384

[15] -   File "/home/deploy/utils/miniconda3/lib/python3.7/site-packages/sanic/http.py", line 477, in log_response
    access_logger.info("", extra=extra)

[16] -   File "/home/deploy/utils/miniconda3/lib/python3.7/logging/__init__.py", line 1383, in info
    self._log(INFO, msg, args, **kwargs)

[17] -   File "/home/deploy/utils/miniconda3/lib/python3.7/logging/__init__.py", line 1519, in _log
    self.handle(record)

I think, sanic prints empty logs (I can't understand why).

I want to ignore empty logs. lower is my logger initialize code. How can I do it?

def initialize_logger():
    class StreamLogFormatter(logging.Formatter):
        format_type = "[%(asctime)s] [%(levelname)s] %(message)s"

        def format(self, record):
            trace(record.msg)
            formatter = logging.Formatter(self.format_type)
            return formatter.format(record)

    logger = logging.getLogger()

    # remove default handler
    logger.handlers = []

    # console log
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.INFO)
    console_handler.setFormatter(StreamLogFormatter())
    logger.addHandler(console_handler)

    logger.setLevel(logging.INFO)

    return logger

Solution

  • Handlers can filter records according to the filters they have defined. If for whatever reason your program sends empty logs, you can filter those out by adding a simple filter:

    console_handler.addFilter(lambda record: record.msg.strip() != '')
    

    A short MRE to demonstrate:

    import logging
    
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    
    console_handler = logging.StreamHandler()
    console_handler.addFilter(lambda record: record.msg.strip() != '')
    logger.addHandler(console_handler)
    
    logger.info("msg1")
    logger.info("   ")
    logger.info("msg2")
    

    Will only print:

    msg1
    msg2
    

    If you have multiple Handlers and want them all to have that behavior - Logger objects also have a addFilter method so the same filter can be applied directly on the logger.