""" This file sets up logging for the entire logparse package. Custom log formatter and handler classes are specified below and the logger is supplied to all subsequent modules, including parsers. """ __version__ = '2.0' __name__ = 'logparse' from copy import copy import logging import logging.handlers # Standard shell escape codes ESC = { "reset": "\033[0m", "color": "\033[1;%dm", "bold": "\033[1m", "underlined": "\033[4m" } # Standard shell colour codes (30..39 are the foreground colors) DEFAULT = 39 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN = range(30, 37) # Map colours to log levels (used for level text only) COLORS = { 10: BLUE, # debug 20: DEFAULT, # info 30: YELLOW, # warning 40: RED, # error 50: RED # critical } # Template for formatting log messages FORMAT = ("{bold}%(module)-15s{reset} %(levelname)-18s %(message)s " "({bold}%(filename)s{reset}:%(lineno)d)") class ColoredFormatter(logging.Formatter): """ Custom implementation of a log formatter to apply standard shell colour escape sequences depending on the log level. The original record is copied so as to not interfere with subsequent handlings (i.e. the syslog handler). """ def __init__(self, msg): logging.Formatter.__init__(self, msg) def format(self, record): temprecord = copy(record) levelname = temprecord.levelname if temprecord.levelno in COLORS: levelname_color = ESC["color"] % (COLORS[temprecord.levelno]) \ + levelname + ESC["reset"] temprecord.levelname = levelname_color temprecord.name = record.name.replace(__name__ + ".", "") return logging.Formatter.format(self, temprecord) class ColoredLogger(logging.Logger): """ Custom implementation of a logger object using the `ColoredFormatter` class above. This class also includes a syslog handler to direct a minimal amount of output to /dev/log. """ message = FORMAT.format(**ESC) def __init__(self, name): """ Initialise the logger for the entire package. This is done here so that the configuration is applied to all child modules. A syslog handler is also initialised, with a min level of INFO so that journald doesn't get spammed with debug messages.. """ logging.Logger.__init__(self, name) color_formatter = ColoredFormatter(self.message) syslog_handler = logging.handlers.SysLogHandler(address = '/dev/log') syslog_handler.setLevel(logging.INFO) syslog_handler.setFormatter(logging.Formatter( fmt='{}[%(process)d]: (%(module)s) %(message)s'.format(__name__))) console = logging.StreamHandler() console.setFormatter(color_formatter) self.addHandler(console) self.addHandler(syslog_handler) return # Initialise logger object logging.setLoggerClass(ColoredLogger) logger = logging.getLogger()