gunicorn
gunicorn copied to clipboard
"capture_output" fails when using "logconfig_dict" for logging configuration
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"
}
}
}
Any follow-up? I met the same issue.