gunicorn icon indicating copy to clipboard operation
gunicorn copied to clipboard

"capture_output" fails when using "logconfig_dict" for logging configuration

Open cdhigh opened this issue 9 months ago • 1 comments

The persistence of a bug has been identified in Gunicorn version 22.0.0. Bug Summary: In the configuration file gunicorn.conf.py, the capture_output variable fails to function properly when the logging system is configured using logconfig_dict rather than errorlog.

Issue Details: Previously, I configured Gunicorn using the errorlog variable along with capture_output, which worked as expected. However, the log file grew rapidly, prompting a need for file size control. Consequently, I opted to use logconfig_dict with RotatingFileHandler. After this change, the logging system ceased to capture stdout messages.

Upon investigation of the Gunicorn source code, I identified the following segment: https://github.com/benoitc/gunicorn/blob/5b68c17b170c7b021a7a982a06c08e3898a5a640/gunicorn/glogging.py#L202

if self.cfg.capture_output and cfg.errorlog != "-":
            for stream in sys.stdout, sys.stderr:
                stream.flush()

            self.logfile = open(cfg.errorlog, 'a+')
            os.dup2(self.logfile.fileno(), sys.stdout.fileno())
            os.dup2(self.logfile.fileno(), sys.stderr.fileno())

This code snippet reveals that capture_output only takes effect when errorlog is set. However, I did not set errorlog; instead, I configured the logging system using logconfig_dict.

here is the full content of my gunicorn.conf.py

# gunicorn.conf.py
import os
pythonpath = "/usr/local/lib/python3.9/site-packages"
bind = "0.0.0.0:8000"
workers = 1
threads = 3
capture_output = True
enable_stdio_inheritance = True
#accesslog = "/data/gunicorn.access.log"
#errorlog = "/data/gunicorn.error.log"
#loglevel = "info"
#preload_app = True
certfile = os.getenv('GUNI_CERT')
keyfile = os.getenv('GUNI_KEY')
#example: https://github.com/benoitc/gunicorn/blob/master/gunicorn/glogging.py
logconfig_dict = {
    'version': 1,
    'disable_existing_loggers': False,
    "root": {"level": "INFO", "handlers": ["error_file"]},
    'loggers': {
        "gunicorn.error": {
            "level": "INFO", 
            "handlers": ["error_file"],
            "propagate": False,
            "qualname": "gunicorn.error"
        },
        "gunicorn.access": {
            "level": "INFO",
            "handlers": ["access_file"],
            "propagate": False,
            "qualname": "gunicorn.access"
        }
    },
    'handlers': {
        "error_file": {
            "class": "logging.handlers.RotatingFileHandler",
            "maxBytes": 50*1024*1024, #50M
            "backupCount": 1,
            "formatter": "generic",
            "filename": "/data/gunicorn.error.log"
        },
        "access_file": {
            "class": "logging.handlers.RotatingFileHandler",
            "maxBytes": 10*1024*1024, #10M
            "backupCount": 1,
            "formatter": "access",
            "filename": "/data/gunicorn.access.log"
        }
    },
    'formatters':{
        "generic": {
            "format": "%(asctime)s %(levelname)s [%(filename)s:%(lineno)s] %(message)s",
            "datefmt": "[%Y-%m-%d %H:%M:%S %z]",
            "class": "logging.Formatter"
        },
        "access": {
            "format": "%(message)s",
            "datefmt": "[%Y-%m-%d %H:%M:%S %z]",
            "class": "logging.Formatter"
        }
    }
}

cdhigh avatar May 12 '24 17:05 cdhigh

Any follow-up? I met the same issue.

danielwonght avatar Aug 15 '24 08:08 danielwonght