mirror of
https://github.com/sprockets/sprockets.logging.git
synced 2024-12-27 20:24:41 +00:00
Implement sprockets.logging.ContextFilter
This commit is contained in:
parent
f9959a52c3
commit
5c334181d1
3 changed files with 79 additions and 1 deletions
|
@ -3,4 +3,4 @@ Version History
|
|||
|
||||
Next Release
|
||||
------------
|
||||
- implement greatness
|
||||
- Added :class:`sprockets.logging.ContextFilter`
|
||||
|
|
|
@ -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
|
||||
|
|
44
tests.py
44
tests.py
|
@ -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]')
|
Loading…
Reference in a new issue