From: Christian Herdtweck Date: Thu, 27 Aug 2015 09:04:02 +0000 (+0200) Subject: created log_helpers with 4-char-level formatter ShortLevelFormatter X-Git-Tag: v1.2~110 X-Git-Url: http://developer.intra2net.com/git/?a=commitdiff_plain;h=3098ca94efff4ca9955a1f398b57c3b4759f2866;p=pyi2ncommon created log_helpers with 4-char-level formatter ShortLevelFormatter --- diff --git a/log_helpers.py b/log_helpers.py new file mode 100644 index 0000000..798301c --- /dev/null +++ b/log_helpers.py @@ -0,0 +1,141 @@ +# The software in this package is distributed under the GNU General +# Public License version 2 (with a special exception described below). +# +# A copy of GNU General Public License (GPL) is included in this distribution, +# in the file COPYING.GPL. +# +# As a special exception, if other files instantiate templates or use macros +# or inline functions from this file, or you compile this file and link it +# with other works to produce a work based on this file, this file +# does not by itself cause the resulting work to be covered +# by the GNU General Public License. +# +# However the source code for this file must still be made available +# in accordance with section (3) of the GNU General Public License. +# +# This exception does not invalidate any other reasons why a work based +# on this file might be covered by the GNU General Public License. + +""" Helpers for logging + +ShortLevelFormatter: provide a 4-char-sized field "levl" for messge urgency +(dbug/info/warn/err /crit) + +Further ideas + +* create logger sublcass with logger.notice() +* allow milliseconds in dateformat field (see test_short_level_format) +* create own basicConfig-like function that uses our classes as default + +.. codeauthor:: Christian Herdtweck, christian.herdtweck@intra2net.com +""" + +from logging import Formatter, DEBUG, INFO, WARNING, ERROR, CRITICAL, NOTSET + + +class ShortLevelFormatter(Formatter): + """ + Formatter for logging handlers that allows use of log format field "levl" + + using this formatter, you can specify in the log message format string the + field "levl" which will introduce in your log messages a 4-char field for + the log record urgency: "DEBUG" --> "dbug", "INFO" --> "info", + "WARNING" --> "warn", "ERROR" --> "err ", "CRITICAL" --> "crit" + + All other functionality (like other format fields) is inherited from base + class Formatter + + Usage example:: + + logger = logging.getLogger(__name__) + logger.setLevel(logging.DEBUG) + handler = logging.StreamHandler() + handler.setLevel(logging.DEBUG) + formatter = ShortLevelFormatter('%(levl)s| %(msg)s') + handler.setFormatter(formatter) + logger.addHandler(handler) + + You can even add new levels:: + + notice = (logging.INFO + logging.WARNING)/2 + formatter.add_level(notice, 'note') + logger.log(notice, 'more important than info but no warning nor error') + + .. seealso:: testing funcion :py:func:`test_short_level_format` + """ + + def __init__(self, *args, **kwargs): + """ creates a new ShortLevelFormatter + + forwards all args to super class Formatter and initializes dict with + levelno and short string representations + """ + self.supr = super(ShortLevelFormatter, self) + self.supr.__init__(*args, **kwargs) + self._levl_dict = {DEBUG: 'dbug', INFO: 'info', WARNING: 'warn', + ERROR: 'err ', CRITICAL: 'crit', NOTSET: '----'} + + def format(self, record): + """ create string representation of given log record """ + try: + record.levl = self._levl_dict[record.levelno] + except KeyError: + record.levl = '????' + + return self.supr.format(record) + + def add_level(self, levelno, levl_str): + """ add a new message urgency level + + :param int levelno: numeric urgency level + :param str levl_str: string representation of message urgency; should + be of length 4 + :returns: nothing + """ + + self._levl_dict[levelno] = levl_str + + +def test_short_level_format(): + """ quick test of :py:class:`ShortLevelFormatter` """ + + import logging + logger = logging.getLogger('logtest') + logger.setLevel(DEBUG) + handler = logging.StreamHandler() + handler.setLevel(DEBUG) + formatter = ShortLevelFormatter('%(asctime)s:%(msecs)03d %(levl)s| %(msg)s' + ' [regular levelname=%(levelname)s]', + datefmt='%H:%M:%S') + handler.setFormatter(formatter) + logger.addHandler(handler) + + # 'application' code + logger.debug('debug message') + logger.info('info message') + logger.warn('warn message') + logger.error('error message') + logger.critical('critical message') + logger.log(15, 'unknown level') + logger.log(NOTSET, 'level not set') + + # add notice level + notice = (logging.INFO + logging.WARNING)/2 + formatter.add_level(notice, 'note') + logger.log(notice, 'more important than info but no warning nor error') + + # try if exception formatting still works: + try: + logger.info('this is what an exception looks like:') + impossible_result = 1/0 + logger.critical('just divided 1/0! The result is {0}' + .format(impossible_result)) + except ZeroDivisionError: + logger.exception('1/0 still does not work!', exc_info=True) + + # done + logger.info('done testing') + + +if __name__ == '__main__': + test_short_level_format()