Files
pecan/docs/source/logging.rst
Stanislaw Pitucha 0596397e93 Configure the root logger properly
The documentation and project template showed logging configuration
which sets level INFO for module called 'root' rather than the root
logger. Configure the root (default) logger instead.

Change-Id: I172d06dc6b81a31c5b698e43be50ab6302d54984
2014-08-27 16:28:38 +01:00

4.5 KiB

Logging

Pecan uses the Python standard library's :pylogging module by passing logging configuration options into the logging.config.dictConfig function. The full documentation for the 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.

Configuring Logging

Sample logging configuration is provided with the quickstart project introduced in 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 :pylogging library defines a variety of handlers that assist in writing logs to file. A few interesting ones are:

  • ~logging.FileHandler - used to log messages to a file on the filesystem
  • ~logging.handlers.RotatingFileHandler - similar to ~logging.FileHandler, but also rotates logs periodically
  • ~logging.handlers.SysLogHandler - used to log messages to a UNIX syslog
  • ~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 ~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, ~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'}
    }
}