.. _logging:
Logging
=======
Pecan uses the Python standard library's :py:mod:`logging` module by passing
logging configuration options into the `logging.config.dictConfig`_
function. The full documentation for the :func:`dictConfig` format is
the best source of information for logging configuration, but to get
you started, this chapter will provide you with a few simple examples.
.. _logging.config.dictConfig: http://docs.python.org/library/logging.config.html#configuration-dictionary-schema
Configuring Logging
-------------------
Sample logging configuration is provided with the quickstart project
introduced in :ref:`quick_start`:
::
$ pecan create myapp
The default configuration defines one handler and two loggers.
::
# myapp/config.py
app = { ... }
server = { ... }
logging = {
'root' : {'level': 'INFO', 'handlers': ['console']},
'loggers': {
'myapp': {'level': 'DEBUG', 'handlers': ['console']}
},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'simple'
}
},
'formatters': {
'simple': {
'format': ('%(asctime)s %(levelname)-5.5s [%(name)s]'
'[%(threadName)s] %(message)s')
}
}
}
* ``console`` logs messages to ``stderr`` using the ``simple`` formatter.
* ``myapp`` logs messages sent at a level above or equal to ``DEBUG`` to
the ``console`` handler
* ``root`` logs messages at a level above or equal to the ``INFO`` level to
the ``console`` handler
Writing Log Messages in Your Application
----------------------------------------
The logger named ``myapp`` is reserved for your usage in your Pecan
application.
Once you have configured your logging, you can place logging calls in your
code. Using the logging framework is very simple.
::
# myapp/myapp/controllers/root.py
from pecan import expose
import logging
logger = logging.getLogger(__name__)
class RootController(object):
@expose()
def index(self):
if bad_stuff():
logger.error('Uh-oh!')
return dict()
Logging to Files and Other Locations
------------------------------------
Python's :py:mod:`logging` library defines a variety of handlers that assist in
writing logs to file. A few interesting ones are:
* :class:`~logging.FileHandler` - used to log messages to a file on the filesystem
* :class:`~logging.handlers.RotatingFileHandler` - similar to
:class:`~logging.FileHandler`, but also rotates logs
periodically
* :class:`~logging.handlers.SysLogHandler` - used to log messages to a UNIX syslog
* :class:`~logging.handlers.SMTPHandler` - used to log messages to an email
address via SMTP
Using any of them is as simple as defining a new handler in your
application's ``logging`` block and assigning it to one of more loggers.
Logging Requests with Paste Translogger
---------------------------------------
`Paste `_ (which is not included with Pecan) includes
the :class:`~paste.translogger.TransLogger` middleware
for logging requests in `Apache Combined Log Format
`_. Combined with
file-based logging, TransLogger can be used to create an ``access.log`` file
similar to ``Apache``.
To add this middleware, modify your the ``setup_app`` method in your
project's ``app.py`` as follows::
# myapp/myapp/app.py
from pecan import make_app
from paste.translogger import TransLogger
def setup_app(config):
# ...
app = make_app(
config.app.root
# ...
)
app = TransLogger(app, setup_console_handler=False)
return app
By default, :class:`~paste.translogger.TransLogger` creates a logger named
``wsgi``, so you'll need to specify a new (file-based) handler for this logger
in our Pecan configuration file::
# myapp/config.py
app = { ... }
server = { ... }
logging = {
'loggers': {
# ...
'wsgi': {'level': 'INFO', 'handlers': ['logfile'], 'qualname': 'wsgi'}
},
'handlers': {
# ...
'logfile': {
'class': 'logging.FileHandler',
'filename': '/etc/access.log',
'level': 'INFO',
'formatter': 'messageonly'
}
},
'formatters': {
# ...
'messageonly': {'format': '%(message)s'}
}
}