logging.fileConfig support is back.

This commit is contained in:
benoitc 2012-02-19 17:07:02 +01:00
parent 85c60c26b5
commit cc99181cee
4 changed files with 80 additions and 32 deletions

View File

@ -1,33 +1,48 @@
[loggers] [loggers]
keys=root, gunicorn keys=root, gunicorn_error, gunicorn_access
[handlers] [handlers]
keys=console, file keys=console, error_file, access_file
[formatters] [formatters]
keys=generic keys=generic, access
[logger_root] [logger_root]
level=INFO level=INFO
handlers=console handlers=console
[logger_gunicorn] [logger_gunicorn_error]
level=DEBUG level=INFO
handlers=file handlers=error_file
propagate=1 propagate=1
qualname=gunicorn qualname=gunicorn.error
[logger_gunicorn_access]
level=INFO
handlers=access_file
propagate=1
qualname=gunicorn.access
[handler_console] [handler_console]
class=StreamHandler class=StreamHandler
formatter=generic formatter=generic
args=(sys.stdout, ) args=(sys.stdout, )
[handler_file] [handler_error_file]
class=logging.FileHandler class=logging.FileHandler
formatter=generic formatter=generic
args=('/tmp/test.log',) args=('/tmp/gunicorn.error.log',)
[handler_access_file]
class=logging.FileHandler
formatter=access
args=('/tmp/gunicorn.access.log',)
[formatter_generic] [formatter_generic]
format="%(asctime)s [%(process)d] [%(levelname)s] %(message)s" format=%(asctime)s [%(process)d] [%(levelname)s] %(message)s
datefmt="%Y-%m-%d %H:%M:%S" datefmt=%Y-%m-%d %H:%M:%S
class=logging.Formatter
[formatter_access]
format=%(message)s
class=logging.Formatter class=logging.Formatter

View File

@ -686,6 +686,20 @@ class LoggerClass(Setting):
with `egg:gunicorn#simple` with `egg:gunicorn#simple`
""" """
class LogConfig(Setting):
name = "logconfig"
section = "Logging"
cli = ["--log-config"]
meta = "FILE"
validator = validate_string
default = None
desc = """\
The log config file to use.
Gunicorn uses the standard Python logging module's Configuration
file format.
"""
class Procname(Setting): class Procname(Setting):
name = "proc_name" name = "proc_name"
section = "Process Naming" section = "Process Naming"

View File

@ -6,10 +6,16 @@
import datetime import datetime
import logging import logging
logging.Logger.manager.emittedNoHandlerWarning = 1 logging.Logger.manager.emittedNoHandlerWarning = 1
import os
import sys import sys
import traceback import traceback
import threading import threading
try:
from logging.config import fileConfig
except ImportError:
from gunicorn.logging_config import fileConfig
from gunicorn import util from gunicorn import util
class LazyWriter(object): class LazyWriter(object):
@ -68,32 +74,37 @@ class Logger(object):
self.access_log = logging.getLogger("gunicorn.access") self.access_log = logging.getLogger("gunicorn.access")
self.error_handlers = [] self.error_handlers = []
self.access_handlers = [] self.access_handlers = []
self.cfg = cfg
self.setup(cfg) self.setup(cfg)
def setup(self, cfg): def setup(self, cfg):
self.cfg = cfg if not cfg.logconfig:
loglevel = self.LOG_LEVELS.get(cfg.loglevel.lower(), logging.INFO)
self.error_log.setLevel(loglevel)
self.access_log.setLevel(logging.INFO)
loglevel = self.LOG_LEVELS.get(cfg.loglevel.lower(), logging.INFO)
if cfg.errorlog != "-": if cfg.errorlog != "-":
# if an error log file is set redirect stdout & stderr to # if an error log file is set redirect stdout & stderr to
# this log file. # this log file.
stdout_log = LazyWriter(cfg.errorlog, 'a') stdout_log = LazyWriter(cfg.errorlog, 'a')
sys.stdout = stdout_log sys.stdout = stdout_log
sys.stderr = stdout_log sys.stderr = stdout_log
self.error_log.setLevel(loglevel) # set gunicorn.error handler
self._set_handler(self.error_log, cfg.errorlog,
logging.Formatter(self.error_fmt, self.datefmt))
# always info in access log # set gunicorn.access handler
self.access_log.setLevel(logging.INFO) if cfg.accesslog is not None:
self._set_handler(self.access_log, cfg.accesslog,
self._set_handler(self.error_log, cfg.errorlog, fmt=logging.Formatter(self.access_fmt))
logging.Formatter(self.error_fmt, self.datefmt)) else:
if os.path.exists(cfg.logconfig):
if cfg.accesslog is not None: util.check_is_writeable(cfg.logconfig)
self._set_handler(self.access_log, cfg.accesslog, fileConfig(cfg.logconfig)
fmt=logging.Formatter(self.access_fmt)) else:
raise RuntimeError("Error: log config '%s' not found" % path)
def critical(self, msg, *args, **kwargs): def critical(self, msg, *args, **kwargs):
@ -124,10 +135,9 @@ class Logger(object):
for format details for format details
""" """
if not self.cfg.accesslog: if not self.cfg.accesslog and not self.cfg.logconfig:
return return
status = resp.status.split(None, 1)[0] status = resp.status.split(None, 1)[0]
atoms = { atoms = {
'h': environ['REMOTE_ADDR'], 'h': environ['REMOTE_ADDR'],
@ -197,6 +207,7 @@ class Logger(object):
if output == "-": if output == "-":
h = logging.StreamHandler() h = logging.StreamHandler()
else: else:
util.check_is_writeable(output)
h = logging.FileHandler(output) h = logging.FileHandler(output)
h.setFormatter(fmt) h.setFormatter(fmt)

View File

@ -303,3 +303,11 @@ def seed():
random.seed(os.urandom(64)) random.seed(os.urandom(64))
except NotImplementedError: except NotImplementedError:
random.seed(random.random()) random.seed(random.random())
def check_is_writeable(path):
try:
f = open(path, 'a')
except IOError, e:
raise RuntimeError("Error: '%s' isn't writable [%r]" % (path, e))
f.close()