Search code examples
pythonlogginggunicornplotly-dash

Using Gunicorn with custom getMessage() logging --> logging error


I'm using a custom LogRecord to handle an additional variable (session_id), each time a log is created

class LogRecord(logging.LogRecord):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.session_id = None

    def getMessage(self):
        msg = str(self.msg)
        if self.args:
            msg = msg % self.args
            self.session_id = self.args[0]
        return msg


logging.setLogRecordFactory(LogRecord)

I'm using this inside a Dash application. When starting the application with Dash, all logs work like intended. When I run the app with gunicorn, it is using its own record engine but with my custom LogRecord which results in the following error trace:

  File ".../lib/python3.9/logging/__init__.py", line 1083, in emit
    msg = self.format(record)
  File ".../lib/python3.9/logging/__init__.py", line 927, in format
    return fmt.format(record)
  File ".../lib/python3.9/logging/__init__.py", line 663, in format
    record.message = record.getMessage()
  File ".../LipViz/log/classes_log.py", line 17, in getMessage
    self.session_id = self.args[0]
  File ".../lib/python3.9/site-packages/gunicorn/glogging.py", line 108, in __getitem__
    if k.startswith("{"):
AttributeError: 'int' object has no attribute 'startswith'

This is because gunicorn uses its own array of custom arguments for logs. I'd need to find a way to tell gunicorn to use its LogRecord.getMessage() for its own logs and my custom one for the program it is casting.


Solution

  • With log.info('MESSAGE', extra={'session_id'=SESSION_ID}) I did not need to use LogFactory anymore.