From f9959a52c3695f1aafbf2f2a9050fcfed9701b72 Mon Sep 17 00:00:00 2001 From: Dave Shawley <daves@aweber.com> Date: Mon, 8 Jun 2015 13:20:03 -0400 Subject: [PATCH] Add examples. --- README.rst | 18 +++++----- docs/examples.rst | 30 +++++----------- examples/simple.py | 22 ++++++++++++ examples/tornado-app.py | 77 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 29 deletions(-) create mode 100644 examples/simple.py create mode 100644 examples/tornado-app.py diff --git a/README.rst b/README.rst index 074b12b..28f6bc9 100644 --- a/README.rst +++ b/README.rst @@ -24,30 +24,32 @@ Requirements Example ------- -This examples demonstrates how to use ``sprockets.logging`` by ... +This examples demonstrates the most basic usage of ``sprockets.logging`` .. code-block:: python import logging import sys - + import sprockets.logging - + + formatter = logging.Formatter('%(levelname)s %(message)s {%(context)s}') handler = logging.StreamHandler(sys.stdout) handler.setFormatter(formatter) handler.addFilter(sprockets.logging.ContextFilter(properties=['context'])) logging.Logger.root.addHandler(handler) - - # Outputs: INFO Hi there {} + logging.Logger.root.setLevel(logging.DEBUG) + + # Outputs: INFO Hi there {None} logging.info('Hi there') - + # Outputs: INFO No KeyError {bah} logging.info('No KeyError', extra={'context': 'bah'}) - + # Outputs: INFO Now with context! {foo} adapted = logging.LoggerAdapter(logging.Logger.root, extra={'context': 'foo'}) - adapter.info('Now with context!') + adapted.info('Now with context!') Source ------ diff --git a/docs/examples.rst b/docs/examples.rst index 45f5d6c..db435cb 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -3,29 +3,17 @@ Examples Simple Usage ------------ -The following snippet uses :class:`sprockets.logging.filters.ContextFilter` +The following snippet uses :class:`sprockets.logging.ContextFilter` to insert context information into a message using a :class:`logging.LoggerAdapter` instance. -.. code-block:: python +.. literalinclude:: ../examples/simple.py - import logging - import sys +Dictionary-based Configuration +------------------------------ +This package begins to shine if you use the dictionary-based logging +configuration offered by :func:`logging.config.dictConfig`. You can insert +the custom filter and format string into the logging infrastructure and +insert context easily with :class:`logging.LoggerAdapter`. - import sprockets.logging - - formatter = logging.Formatter('%(levelname)s %(message)s {%(context)s}') - handler = logging.StreamHandler(sys.stdout) - handler.setFormatter(formatter) - handler.addFilter(sprockets.logging.ContextFilter(properties=['context'])) - logging.Logger.root.addHandler(handler) - - # Outputs: INFO Hi there {} - logging.info('Hi there') - - # Outputs: INFO No KeyError {bah} - logging.info('No KeyError', extra={'context': 'bah'}) - - # Outputs: INFO Now with context! {foo} - adapted = logging.LoggerAdapter(logging.Logger.root, extra={'context': 'foo'}) - adapter.info('Now with context!') +.. literalinclude:: ../examples/tornado-app.py diff --git a/examples/simple.py b/examples/simple.py new file mode 100644 index 0000000..a1ac45f --- /dev/null +++ b/examples/simple.py @@ -0,0 +1,22 @@ +import logging +import sys + +import sprockets.logging + + +formatter = logging.Formatter('%(levelname)s %(message)s {%(context)s}') +handler = logging.StreamHandler(sys.stdout) +handler.setFormatter(formatter) +handler.addFilter(sprockets.logging.ContextFilter(properties=['context'])) +logging.Logger.root.addHandler(handler) +logging.Logger.root.setLevel(logging.DEBUG) + +# Outputs: INFO Hi there {None} +logging.info('Hi there') + +# Outputs: INFO No KeyError {bah} +logging.info('No KeyError', extra={'context': 'bah'}) + +# Outputs: INFO Now with context! {foo} +adapted = logging.LoggerAdapter(logging.Logger.root, extra={'context': 'foo'}) +adapted.info('Now with context!') diff --git a/examples/tornado-app.py b/examples/tornado-app.py new file mode 100644 index 0000000..d88a852 --- /dev/null +++ b/examples/tornado-app.py @@ -0,0 +1,77 @@ +import logging.config +import signal +import uuid + +from tornado import ioloop, web +import sprockets.logging + + +LOG_CONFIG = { + 'version': 1, + 'handlers': { + 'console': { + 'class': 'logging.StreamHandler', + 'stream': 'ext://sys.stdout', + 'formatter': 'simple', + 'filters': ['context'], + }, + }, + 'formatters': { + 'simple': { + 'class': 'logging.Formatter', + 'format': '%(levelname)s %(name)s: %(message)s [%(context)s]', + }, + }, + 'filters': { + 'context': { + '()': 'sprockets.logging.ContextFilter', + 'properties': ['context'], + }, + }, + 'loggers': { + 'tornado': { + 'level': 'DEBUG', + }, + }, + 'root': { + 'handlers': ['console'], + 'level': 'DEBUG', + }, + 'incremental': False, +} + + +class RequestHandler(web.RequestHandler): + + def __init__(self, *args, **kwargs): + self.parent_log = kwargs.pop('parent_log') + super(RequestHandler, self).__init__(*args, **kwargs) + + def prepare(self): + uniq_id = self.request.headers.get('X-UniqID', uuid.uuid4().hex) + self.logger = logging.LoggerAdapter( + self.parent_log.getChild('RequestHandler'), + extra={'context': uniq_id}) + + def get(self, object_id): + self.logger.debug('fetchin %s', object_id) + self.set_status(200) + return self.finish() + +def sig_handler(signo, frame): + logging.info('caught signal %d, stopping IO loop', signo) + iol = ioloop.IOLoop.instance() + iol.add_callback_from_signal(iol.stop) + +if __name__ == '__main__': + logging.config.dictConfig(LOG_CONFIG) + logger = logging.getLogger('app') + app = web.Application([ + web.url('/(?P<object_id>\w+)', RequestHandler, + kwargs={'parent_log': logger}), + ]) + app.listen(8000) + signal.signal(signal.SIGINT, sig_handler) + signal.signal(signal.SIGTERM, sig_handler) + ioloop.IOLoop.instance().start() + logger.info('IO loop stopped, exiting')