--- /dev/null
+# 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()