Search code examples
pythonflaskfastapigunicornuvicorn

When using uvicorn with gunicorn, why attach logs to the error logger?


When running Gunicorn as a process manager for Uvicorn the access logs, exceptions, etc are not displayed in the Gunicorn logs by default.

The solutions I found in several places suggest variations of the following:

gunicorn_error_logger = logging.getLogger("gunicorn.error")
uvicorn_access_logger = logging.getLogger("uvicorn.access")
uvicorn_access_logger.handlers = gunicorn_error_logger.handlers

Basically reusing the handlers of the Gunicorn error logger for the Uvicorn access logger. This results in Uvicorn access logs being printed to the console, but feels a bit wrong because:

  1. Both GUnicorn and Uvicorn go to the effort to separate their access logging from their error logging
  2. When used as a worker, Uvicorn already attaches its loggers to the loggers given to it by Gunicorn
  3. Using this solution means that unless configured otherwise your Uvicorn access logs are streaming to STDERR instead of STDOUT

Is there something I'm missing here? Is there a better way?


Solution

  • Manually wrangling the handlers of the loggers is not necessary. :-)

    In current versions of Gunicorn (and I guess for quite a while), the default is to silently discard access logs unless a location is explicitly configured.

    Configuring Gunicorn with --access-logfile="-" will send access logs (including those of the Uvicorn worker and its app) to STDOUT. Alternately you can configure a preferred file location.

    Some additional context here.