pythonpython-3.xflaskloggingwerkzeug

werkzeug: disable bash colors when logging to file


In a Flask application, I use a RotatingFileLogger to log werkzeug access logs to a file like shown in this question:

file_handler_access_log = RotatingFileHandler("access.log",
                                              backupCount=5,
                                              encoding='utf-8')
formatter = logging.Formatter('%(asctime)s %(module)s %(levelname)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
file_handler_access_log.setFormatter(formatter)
werkzeug_logger.addHandler(file_handler_access_log)
werkzeug_logger.setLevel(logging.DEBUG)

In the access.log file, the request looks like this:

2020-10-07 09:43:51 _internal INFO: 127.0.0.1 - - [07/Oct/2020 09:43:51] "[37mGET /api/foo HTTP/1.1[0m" 200 -

I want to get rid of the color codes like [37m in the log file.

The werkzeug documentation states:

The development server can optionally highlight the request logs in different colors based on the status code. Install Click to enable this feature.

Click is a Flask dependency, so I cannot uninstall it. How can I disable the colored logging?


Solution

  • OK, so what you are hitting is

    if click:
        color = click.style
    
        if code[0] == "1":  # 1xx - Informational
            msg = color(msg, bold=True)
        ...
    self.log("info", '"%s" %s %s', msg, code, size)
    

    Source: https://github.com/pallets/werkzeug/blob/ef545f0d0bf28cbad02066b4cb7471bea50a93ee/src/werkzeug/serving.py

    Not easy to prevent the behavior. The second option is to remove color codes from messages. I would try to use log Filter to update the message, something like

    import logging
    
    import click
        
    
    class RemoveColorFilter(logging.Filter):
        def filter(self, record):
            if record and record.msg and isinstance(record.msg, str):
                record.msg = click.unstyle(record.msg) 
            return True
    
    remove_color_filter = RemoveColorFilter()
    file_handler_access_log.addFilter(remove_color_filter)
    

    The above suggestion was inspired by the following answer https://stackoverflow.com/a/60692906/4183498.

    I didn't test the proposed solution.