Configuration

Mill comes with some default configurators that are simple helper functions for configuring the system. Each one is registered in the mill.configurators dictionary and can be called through the mill.configure() function.

The default configurator is the classic one which you would have used in the Getting Started guide.

Note

You can find reference for each configurator that comes with Mill in the mill.configurator section.

You don’t have to use a configurator though (or you might want to create your own) so let’s take a look at manually configuring the system.

First, decide what you want to handle, where it should go and how it should be formatted. For our purposes, we will configure Mill to:

  • Send all logs to sys.stderr that have a level greater than ‘warning’ or have been tagged with a ‘user’ key. The format will be just the level and message.
  • Send all logs to a file displaying all available fields verbosely starting with date, level, name, message.
  • Send a formatted email for any log with a level of ‘error’ or higher to our support team including the traceback and a buffer of recent logs.

Before you start make sure you import all the necessary modules:

import sys

import mill
import mill.handler.stream
import mill.handler.email
import mill.handler.buffer
import mill.formatter.template
import mill.formatter.field
import mill.filterer.level
import mill.filterer.item

User Visible Or High Level To Standard Error

First up we need a Stream handler to direct output to sys.stderr:

    stderr_handler = mill.handler.stream.Stream(sys.stderr)

We want to use a simple Template formatter to display each log as a string of level and message:

    stderr_formatter = mill.formatter.template.Template('{level}:{message}')

And attach that as the formatter for the stderr_handler:

    stderr_handler.formatter = stderr_formatter

Now we need to filter all logs that don’t meet the level requirement unless they are tagged with a ‘user’ key:

    stderr_filterer = mill.filterer.level.Level(min='warning', max=None)
    stderr_filterer |= mill.filterer.item.Item('user', True)

And attach as the filterer for the stderr_handler:

    stderr_handler.filterer = stderr_filterer

Next we just need to register this handler under a sensible name like stderr:

    mill.root.handlers['stderr'] = stderr_handler

All To File

Logging everything to a file means we need another Stream handler, but pointing at a file this time:

    log_path = '/path/to/logfile.log'
    file_stream = open(log_path, 'a')
    file_handler = mill.handler.stream.Stream(file_stream)

We don’t need any filterer as all logs should go to the file, but we do want a specific formatter to try and capture as much information as the logs can provide:

    file_formatter = mill.formatter.field.Field([
        'timestamp', 'level', 'name', 'message', '*'
    ])
    file_handler.formatter = file_formatter

Note

The ‘*’ is special and means capture all other fields present ordered alphabetically by key.

And register that one as well:

    mill.root.handlers['file'] = file_handler

Errors To Email

Finally create an email handler that will send any errors to a predefined email address, including a buffer of recent messages. First setup the email handler with the default template:

    # Send email on errors.
    email_handler = mill.handler.email.Email(
        'Error Report',
        'no-reply@mill.net',

Next, we need a buffer so that errors will have context. This buffer will wrap the email handler and only pass on messages when the set trigger is activated:

    email_handler = mill.handler.email.Email(
        'Error Report',
        'no-reply@mill.net',
        'support@mill.net'
    )

    def check_for_error(logs, buffer):
        '''Return True if any of the recent logs was an error message.'''
        for log in logs:
            if log.get('level') == 'error':
                return True

        return False

    email_buffer_handler = mill.handler.buffer.Buffer(
        email_handler,
        check_for_error,
        limit=30
    )

And register the buffer handler as the email handler:

    mill.root.handlers['email'] = email_buffer_handler

See also

See Configurator Example for the full code used in this tutorial.

Project Versions

Table Of Contents

Previous topic

Getting Started

Next topic

Examples

This Page