Implement sprockets.logging.ContextFilter

This commit is contained in:
Dave Shawley 2015-06-08 13:20:30 -04:00
parent f9959a52c3
commit 5c334181d1
3 changed files with 79 additions and 1 deletions

View file

@ -3,4 +3,4 @@ Version History
Next Release
------------
- implement greatness
- Added :class:`sprockets.logging.ContextFilter`

View file

@ -1,5 +1,39 @@
"""
Make good log output easier.
- :class:`ContextFilter` adds fixed properties to a log record
"""
from __future__ import absolute_import
import logging
version_info = (0, 0, 0)
__version__ = '.'.join(str(v) for v in version_info)
class ContextFilter(logging.Filter):
"""
Ensures that properties exist on a LogRecord.
:param list|None properties: optional list of properties that
will be added to LogRecord instances if they are missing
This filter implementation will ensure that a set of properties
exists on every log record which means that you can always refer
to custom properties in a format string. Without this, referring
to a property that is not explicitly passed in will result in an
ugly ``KeyError`` exception.
"""
def __init__(self, name='', properties=None):
logging.Filter.__init__(self, name)
self.properties = list(properties) if properties else []
def filter(self, record):
for property_name in self.properties:
if not hasattr(record, property_name):
setattr(record, property_name, None)
return True

View file

@ -0,0 +1,44 @@
import logging
import uuid
import unittest
import sprockets.logging
class Prototype(object):
pass
class RecordingHandler(logging.FileHandler):
def __init__(self):
logging.FileHandler.__init__(self, filename='/dev/null')
self.log_lines = []
def format(self, record):
log_line = logging.FileHandler.format(self, record)
self.log_lines.append(log_line)
return log_line
class ContextFilterTests(unittest.TestCase):
def setUp(self):
super(ContextFilterTests, self).setUp()
self.logger = logging.getLogger(uuid.uuid4().hex)
self.handler = RecordingHandler()
self.logger.addHandler(self.handler)
def test_that_filter_blocks_key_errors(self):
formatter = logging.Formatter('%(message)s [%(context)s]')
self.handler.setFormatter(formatter)
self.handler.addFilter(sprockets.logging.ContextFilter(
properties=['context']))
self.logger.info('hi there')
def test_that_filter_does_not_overwrite_extras(self):
formatter = logging.Formatter('%(message)s [%(context)s]')
self.handler.setFormatter(formatter)
self.handler.addFilter(sprockets.logging.ContextFilter(
properties=['context']))
self.logger.info('hi there', extra={'context': 'foo'})
self.assertEqual(self.handler.log_lines[-1], 'hi there [foo]')