color logging support
Change-Id: Ic88b41e4032d6c97e020485341d375c196a1a1c0
This commit is contained in:
parent
8e9d8b7bb7
commit
503a586d38
|
@ -2,12 +2,19 @@
|
|||
Serve command for Pecan.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import subprocess
|
||||
from wsgiref.simple_server import WSGIRequestHandler
|
||||
|
||||
|
||||
from pecan.commands import BaseCommand
|
||||
from pecan import util
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ServeCommand(BaseCommand):
|
||||
|
@ -100,7 +107,12 @@ class ServeCommand(BaseCommand):
|
|||
from wsgiref.simple_server import make_server
|
||||
|
||||
host, port = conf.server.host, int(conf.server.port)
|
||||
srv = make_server(host, port, app)
|
||||
srv = make_server(
|
||||
host,
|
||||
port,
|
||||
app,
|
||||
handler_class=PecanWSGIRequestHandler,
|
||||
)
|
||||
|
||||
print('Starting server in PID %s' % os.getpid())
|
||||
|
||||
|
@ -178,3 +190,34 @@ def gunicorn_run():
|
|||
return deploy(self.cfgfname)
|
||||
|
||||
PecanApplication("%(prog)s [OPTIONS] config.py").run()
|
||||
|
||||
|
||||
class PecanWSGIRequestHandler(WSGIRequestHandler, object):
|
||||
"""
|
||||
A wsgiref request handler class that allows actual log output depending on
|
||||
the application configuration.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
# We set self.path to avoid crashes in log_message() on unsupported
|
||||
# requests (like "OPTIONS").
|
||||
self.path = ''
|
||||
super(PecanWSGIRequestHandler, self).__init__(*args, **kwargs)
|
||||
|
||||
def log_message(self, format, *args):
|
||||
"""
|
||||
overrides the ``log_message`` method from the wsgiref server so that
|
||||
normal logging works with whatever configuration the application has
|
||||
been set to.
|
||||
|
||||
Levels are inferred from the HTTP status code, 4XX codes are treated as
|
||||
warnings, 5XX as errors and everything else as INFO level.
|
||||
"""
|
||||
code = args[1][0]
|
||||
levels = {
|
||||
'4': 'warning',
|
||||
'5': 'error'
|
||||
}
|
||||
|
||||
log_handler = getattr(logger, levels.get(code, 'info'))
|
||||
log_handler(format % args)
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
import logging
|
||||
|
||||
from logutils.colorize import ColorizingStreamHandler
|
||||
|
||||
|
||||
class DefaultColorizer(ColorizingStreamHandler):
|
||||
|
||||
level_map = {
|
||||
logging.DEBUG: (None, 'blue', True),
|
||||
logging.INFO: (None, None, True),
|
||||
logging.WARNING: (None, 'yellow', True),
|
||||
logging.ERROR: (None, 'red', True),
|
||||
logging.CRITICAL: (None, 'red', True),
|
||||
}
|
||||
|
||||
|
||||
class ColorFormatter(logging.Formatter):
|
||||
"""
|
||||
A very basic logging formatter that not only applies color to the
|
||||
levels of the ouput but can also add padding to the the level names so that
|
||||
they do not alter the visuals of logging when presented on the terminal.
|
||||
|
||||
The padding is provided by a convenient keyword that adds padding to the
|
||||
``levelname`` so that log output is easier to follow::
|
||||
|
||||
%(padded_color_levelname)s
|
||||
|
||||
Which would result in log level output that looks like::
|
||||
|
||||
[INFO ]
|
||||
[WARNING ]
|
||||
[ERROR ]
|
||||
[DEBUG ]
|
||||
[CRITICAL]
|
||||
|
||||
If colored output is not supported, it falls back to non-colored output
|
||||
without any extra settings.
|
||||
"""
|
||||
|
||||
def __init__(self, _logging=None, colorizer=None, *a, **kw):
|
||||
self.logging = _logging or logging
|
||||
self.color = colorizer or DefaultColorizer()
|
||||
logging.Formatter.__init__(self, *a, **kw)
|
||||
|
||||
def format(self, record):
|
||||
levelname = record.levelname
|
||||
padded_level = '%-8s' % levelname
|
||||
|
||||
record.color_levelname = self.color.colorize(levelname, record)
|
||||
record.padded_color_levelname = self.color.colorize(
|
||||
padded_level,
|
||||
record
|
||||
)
|
||||
return self.logging.Formatter.format(self, record)
|
|
@ -21,6 +21,7 @@ logging = {
|
|||
'loggers': {
|
||||
'root': {'level': 'INFO', 'handlers': ['console']},
|
||||
'${package}': {'level': 'DEBUG', 'handlers': ['console']},
|
||||
'pecan.commands.serve': {'level': 'DEBUG', 'handlers': ['console']},
|
||||
'py.warnings': {'handlers': ['console']},
|
||||
'__force_dict__': True
|
||||
},
|
||||
|
@ -28,13 +29,19 @@ logging = {
|
|||
'console': {
|
||||
'level': 'DEBUG',
|
||||
'class': 'logging.StreamHandler',
|
||||
'formatter': 'simple'
|
||||
'formatter': 'color'
|
||||
}
|
||||
},
|
||||
'formatters': {
|
||||
'simple': {
|
||||
'format': ('%(asctime)s %(levelname)-5.5s [%(name)s]'
|
||||
'[%(threadName)s] %(message)s')
|
||||
},
|
||||
'color': {
|
||||
'()': 'pecan.log.ColorFormatter',
|
||||
'format': ('%(asctime)s [%(padded_color_levelname)s] [%(name)s]'
|
||||
'[%(threadName)s] %(message)s'),
|
||||
'__force_dict__': True
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ logging = {
|
|||
'loggers': {
|
||||
'root': {'level': 'INFO', 'handlers': ['console']},
|
||||
'${package}': {'level': 'DEBUG', 'handlers': ['console']},
|
||||
'pecan.commands.serve': {'level': 'DEBUG', 'handlers': ['console']},
|
||||
'py.warnings': {'handlers': ['console']},
|
||||
'__force_dict__': True
|
||||
},
|
||||
|
@ -22,13 +23,19 @@ logging = {
|
|||
'console': {
|
||||
'level': 'DEBUG',
|
||||
'class': 'logging.StreamHandler',
|
||||
'formatter': 'simple'
|
||||
'formatter': 'color'
|
||||
}
|
||||
},
|
||||
'formatters': {
|
||||
'simple': {
|
||||
'format': ('%(asctime)s %(levelname)-5.5s [%(name)s]'
|
||||
'[%(threadName)s] %(message)s')
|
||||
},
|
||||
'color': {
|
||||
'()': 'pecan.log.ColorFormatter',
|
||||
'format': ('%(asctime)s [%(padded_color_levelname)s] [%(name)s]'
|
||||
'[%(threadName)s] %(message)s'),
|
||||
'__force_dict__': True
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,3 +2,4 @@ WebOb>=1.2dev
|
|||
Mako>=0.4.0
|
||||
WebTest>=1.3.1
|
||||
six
|
||||
logutils>=0.3
|
||||
|
|
9
setup.py
9
setup.py
|
@ -22,15 +22,6 @@ except:
|
|||
except:
|
||||
requirements.append("simplejson >= 2.1.1")
|
||||
|
||||
try:
|
||||
from logging.config import dictConfig # noqa
|
||||
except ImportError:
|
||||
#
|
||||
# This was introduced in Python 2.7 - the logutils package contains
|
||||
# a backported replacement for 2.6
|
||||
#
|
||||
requirements.append('logutils')
|
||||
|
||||
try:
|
||||
import argparse # noqa
|
||||
except:
|
||||
|
|
Loading…
Reference in New Issue