41c6100ceb4a17f25dce2533088a439d04525a9e
1"""
2This file sets up logging for the entire logparse package. Custom log formatter
3and handler classes are specified below and the logger is supplied to all
4subsequent modules, including parsers.
5"""
6
7__version__ = '2.0'
8__name__ = 'logparse'
9
10
11from copy import copy
12import logging
13import logging.handlers
14
15
16# Standard shell escape codes
17ESC = {
18 "reset": "\033[0m",
19 "color": "\033[1;%dm",
20 "bold": "\033[1m",
21 "underlined": "\033[4m"
22 }
23
24# Standard shell colour codes (30..39 are the foreground colors)
25DEFAULT = 39
26BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN = range(30, 37)
27
28# Map colours to log levels (used for level text only)
29COLORS = {
30 10: BLUE, # debug
31 20: DEFAULT, # info
32 30: YELLOW, # warning
33 40: RED, # error
34 50: RED # critical
35 }
36
37# Template for formatting log messages
38FORMAT = ("{bold}%(name)-15s{reset} %(levelname)-18s %(message)s "
39 "({bold}%(filename)s{reset}:%(lineno)d)")
40
41
42class ColoredFormatter(logging.Formatter):
43 """
44 Custom implementation of a log formatter to apply standard shell colour
45 escape sequences depending on the log level. The original record is copied
46 so as to not interfere with subsequent handlings (i.e. the syslog handler).
47 """
48
49 def __init__(self, msg):
50 logging.Formatter.__init__(self, msg)
51
52 def format(self, record):
53 temprecord = copy(record)
54 levelname = temprecord.levelname
55 if temprecord.levelno in COLORS:
56 levelname_color = ESC["color"] % (COLORS[temprecord.levelno]) \
57 + levelname + ESC["reset"]
58 temprecord.levelname = levelname_color
59 temprecord.name = record.name.replace(__name__ + ".", "")
60 return logging.Formatter.format(self, temprecord)
61
62
63class ColoredLogger(logging.Logger):
64 """
65 Custom implementation of a logger object using the `ColoredFormatter` class
66 above. This class also includes a syslog handler to direct a minimal amount
67 of output to /dev/log.
68 """
69
70 message = FORMAT.format(**ESC)
71
72 def __init__(self, name):
73 """
74 Initialise the logger for the entire package. This is done here so that
75 the configuration is applied to all child modules. A syslog handler
76 is also initialised, with a min level of INFO so that journald doesn't
77 get spammed with debug messages..
78 """
79
80 logging.Logger.__init__(self, name)
81
82 color_formatter = ColoredFormatter(self.message)
83
84 syslog_handler = logging.handlers.SysLogHandler(address = '/dev/log')
85 syslog_handler.setLevel(logging.INFO)
86 syslog_handler.setFormatter(logging.Formatter(
87 fmt='{}[%(process)d]: (%(module)s) %(message)s'.format(__name__)))
88
89 console = logging.StreamHandler()
90 console.setFormatter(color_formatter)
91
92 self.addHandler(console)
93 self.addHandler(syslog_handler)
94 return
95
96
97# Initialise logger object
98logging.setLoggerClass(ColoredLogger)
99logger = logging.getLogger()