make the Logger pluggable. Allows people to use their own logger by

giving to gunicorn an entry point or a module path.
This commit is contained in:
benoitc 2011-09-09 00:43:00 +02:00
parent 2375ca87fe
commit 824801d017
4 changed files with 41 additions and 8 deletions

View File

@ -14,7 +14,6 @@ import time
import traceback
from gunicorn.glogging import Logger
from gunicorn.errors import HaltServer
from gunicorn.pidfile import Pidfile
from gunicorn.sock import create_socket
@ -85,7 +84,7 @@ class Arbiter(object):
def setup(self, app):
self.app = app
self.cfg = app.cfg
self.log = Logger(app.cfg)
self.log = self.cfg.logger_class(app.cfg)
if 'GUNICORN_FD' in os.environ:
self.log.reopen_files()

View File

@ -72,7 +72,7 @@ class Config(object):
@property
def worker_class(self):
uri = self.settings['worker_class'].get()
worker_class = util.load_worker_class(uri)
worker_class = util.load_class(uri)
if hasattr(worker_class, "setup"):
worker_class.setup()
return worker_class
@ -101,6 +101,17 @@ class Config(object):
return pn
else:
return self.settings['default_proc_name'].get()
@property
def logger_class(self):
uri = self.settings['logger_class'].get()
logger_class = util.load_class(uri, default="simple",
section="gunicorn.loggers")
if hasattr(logger_class, "install"):
logger_class.install()
return logger_class
class SettingMeta(type):
def __new__(cls, name, bases, attrs):
@ -617,6 +628,25 @@ class Loglevel(Setting):
* critical
"""
class LoggerClass(Setting):
name = "logger_class"
section = "Logging"
cli = ["--logger-class"]
meta = "STRING"
validator = validate_string
default = "simple"
desc = """\
The logger you want to use to log events in gunicorn.
The default class (``gunicorn.glogging.Logger``) handle most of
normal usages in logging. It provides error and access logging.
You can provide your own worker by giving gunicorn a
python path to a subclass like gunicorn.glogging.Logger.
Alternatively the syntax can also load the Logger class
with ``egg:gunicorn#simple`
"""
class Procname(Setting):
name = "proc_name"
section = "Process Naming"

View File

@ -64,7 +64,7 @@ except ImportError:
def _setproctitle(title):
return
def load_worker_class(uri):
def load_class(uri, default="sync", section="gunicorn.workers"):
if uri.startswith("egg:"):
# uses entry points
entry_str = uri.split("egg:")[1]
@ -72,19 +72,20 @@ def load_worker_class(uri):
dist, name = entry_str.rsplit("#",1)
except ValueError:
dist = entry_str
name = "sync"
name = default
return pkg_resources.load_entry_point(dist, "gunicorn.workers", name)
return pkg_resources.load_entry_point(dist, section, name)
else:
components = uri.split('.')
if len(components) == 1:
try:
if uri.startswith("#"):
uri = uri[1:]
return pkg_resources.load_entry_point("gunicorn",
"gunicorn.workers", uri)
section, uri)
except ImportError:
raise RuntimeError("arbiter uri invalid or not found")
raise RuntimeError("class uri invalid or not found")
klass = components.pop(-1)
mod = __import__('.'.join(components))
for comp in components[1:]:

View File

@ -61,6 +61,9 @@ setup(
gevent_pywsgi=gunicorn.workers.ggevent:GeventPyWSGIWorker
tornado=gunicorn.workers.gtornado:TornadoWorker
[gunicorn.loggers]
simple=gunicorn.glogging:Logger
[paste.server_runner]
main=gunicorn.app.pasterapp:paste_server
""",