Permalink
Browse files

add greins.app.GreinsLogger

This change makes it easier to use the gunicorn log for application
messages. Everything is overridable and configurable as before, but by
default greins will use a new logging class, `greins.GreinsLogger`.

The `GreinsLogger` class is just like the logger from gunicorn, except
it configures a handler on the root logger which forwards to the
handler for the 'gunicorn.error' logger and uses a formatter that
includes the package name of the source of each log message.

Reported by Mark Doliner (#14).
  • Loading branch information...
1 parent 93a7ad9 commit 877430e39254546b708cae17c92733f785ef8f0a Randall Leeds committed with tilgovi Mar 27, 2012
Showing with 43 additions and 1 deletion.
  1. +40 −1 greins/app.py
  2. +3 −0 setup.py
View
@@ -6,14 +6,52 @@
import textwrap
import traceback
+from logging import getLogger, NOTSET
+from logging.handlers import MemoryHandler
+
from gunicorn.app.wsgiapp import WSGIApplication
from gunicorn.config import make_settings
+from gunicorn.glogging import Logger
from gunicorn.util import import_app
from greins.reloader import Reloader
from greins.router import Router
from greins.synchronization import synchronized
+class GreinsLogger(Logger):
+ """
+ A `gunicorn.glogging.Logger` subclass which sets up a
+ `logging.handlers.MemoryHandler` that delegates to the gunicorn error
+ logger but filters out the messages from the gunicorn package.
+
+ """
+
+ root_handler = None
+ error_fmt = r"%(asctime)s [%(process)d] [%(levelname)s] [%(name)s] %(message)s"
+
+ @classmethod
+ def install(cls):
+ """
+ Invoked by the gunicorn config system to perform one-time, class-level
+ initialization of the logger.
+ """
+ cls.root_handler = MemoryHandler(0)
+ cls.root_handler.addFilter(cls)
+ getLogger().addHandler(cls.root_handler)
+ getLogger().setLevel(NOTSET)
+
+ @staticmethod
+ def filter(record):
+ return not record.name.startswith('gunicorn')
+
+ def setup(self, cfg):
+ """
+ Resets the target of the forwarding, root handler whenever the
+ logger is reset.
+ """
+ super(GreinsLogger, self).setup(cfg)
+ self.root_handler.setTarget(self._get_gunicorn_handler(self.error_log))
+
class GreinsApplication(WSGIApplication):
synchronize_hooks = synchronized('_hooks_lock')
@@ -24,8 +62,9 @@ def init(self, parser, opts, args):
parser.error("APP_DIR must refer to an existing directory.")
self.cfg.set("default_proc_name", parser.get_prog_name())
+ self.cfg.set("logger_class", 'greins.app.GreinsLogger')
self.app_dir = os.path.abspath(args[0])
- self.logger = logging.getLogger('gunicorn.error')
+ self.logger = getLogger(__name__)
self._use_reloader = opts.reloader
self._hooks = {}
View
@@ -44,5 +44,8 @@
entry_points="""
[console_scripts]
greins=greins.app:run
+
+ [gunicorn.loggers]
+ greins=greins.app:GreinsLogger
"""
)

0 comments on commit 877430e

Please sign in to comment.