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')