summaryrefslogtreecommitdiff
path: root/docs/source/logging.rst
blob: 940c7af0be58ff78dbba5f411fbebabc9c43fa87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
.. _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 = {
        'loggers': {
            'root' : {'level': 'INFO', 'handlers': ['console']},
            '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 <http://pythonpaste.org/>`_ (which is not included with Pecan) includes
the :class:`~paste.translogger.TransLogger` middleware
for logging requests in `Apache Combined Log Format
<http://httpd.apache.org/docs/2.2/logs.html#combined>`_. 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'}
        }
    }