Source code for pytiger.logging.config
# -*- coding: utf-8 -*-
# Copyright © 2018 Tiger Computing Ltd
# This file is part of pytiger and distributed under the terms
# of a BSD-like license
# See the file COPYING for details
"""
.. versionadded:: 1.2.0
Configure the Python :mod:`logging` system following Tiger conventions.
Example usage::
>>> import logging
>>> import pytiger.logging.config
>>> pytiger.logging.config.basic_config()
>>> log = logging.getLogger(__name__)
>>> log.warning('Unable to biggle')
W: Unable to biggle
>>> log.error('Abandon ship, all ye who run this')
E: Abandon ship, all ye who run this
"""
from __future__ import absolute_import
import logging
from .syslog import SyslogFormatter, SyslogHandler
#: Log format string following Tiger Computing conventions.
TCL_FORMAT = "%(leveltag)s: %(message)s"
[docs]
class LevelTagFilter(object):
"""
Log filter that adds the `leveltag` field.
This :class:`logging.Filter` sub-class (using duck-typing) is used to add
the `leveltag` field to :class:`logging.LogRecord` objects so that the tag
is available for use when formatted with the :const:`TCL_FORMAT` format
string.
"""
def filter(self, record):
# Extract the first character of the level name
record.leveltag = record.levelname[0]
# We never actually filter messages out, just abuse filtering to add an
# extra field to the LogRecord
return True
[docs]
def basic_config(fmt=None, datefmt=None, level=None, stderr=True,
stderr_level=None, syslog=True, syslog_level=None):
"""
Perform basic configuration of the Python :mod:`logging` system.
This is very similar to :func:`logging.basicConfig` but designed to follow
Tiger Computing's logging conventions: messages are logged to stderr and to
syslog, and messages are prefixed with a single character tag describing
the log level.
This function does nothing if the root logger already has handlers
configured, therefore this function will only configure logging once. It is
a convenience method to do one-shot configuration of the Python logging
package.
The default behaviour is to:
* Create a :class:`logging.StreamHandler` which writes to
:data:`sys.stderr`.
* Create a :class:`pytiger.logging.syslog.SyslogHandler`, which forwards
messages to syslog using :func:`syslog.syslog`.
* Add the :class:`LevelTagFilter` to the above handlers.
* Set a formatter on the above handlers using the :const:`TCL_FORMAT`
format string.
* Add the handlers to the root logger.
* Sets the root logger's log level to :const:`logging.INFO`.
:param str fmt: Use the specified format string for the handlers.
:param str datefmt: Use the specified date/time format.
:param level: Set the root logger's log level.
:param bool stderr: Determine whether the stderr `StreamHandler` is
configured or added to the root logger.
:param stderr_level: Set the stderr logger's log level.
:param bool syslog: Determine whether the `SyslogHandler` is
configured or added to the root logger.
:param syslog_level: Set the syslog logger's log level.
"""
root = logging.getLogger()
# Do nothing if the root logger already has handlers configured
if len(root.handlers) == 0:
ltf = LevelTagFilter()
if fmt is None:
fmt = TCL_FORMAT
# Configure output to stderr if desired
if stderr:
h = logging.StreamHandler()
h.setFormatter(logging.Formatter(fmt, datefmt))
h.addFilter(ltf)
if stderr_level is not None:
h.setLevel(stderr_level)
root.addHandler(h)
# Configure output to syslog if desired
if syslog:
h = SyslogHandler()
h.setFormatter(SyslogFormatter(fmt, datefmt))
h.addFilter(ltf)
if syslog_level is not None:
h.setLevel(syslog_level)
root.addHandler(h)
# Set the standard log level threshold for the root logger
if level is None:
level = logging.INFO
root.setLevel(level)