1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
'''Bcfg2 logging support'''
__revision__ = '$Revision: $'
import copy, fcntl, logging, logging.handlers, math, struct, termios, types
class TermiosFormatter(logging.Formatter):
'''The termios formatter displays output in a terminal-sensitive fashion'''
def __init__(self, fmt=None, datefmt=None):
logging.Formatter.__init__(self, fmt, datefmt)
# now get termios info
try:
self.height, self.width = struct.unpack('hhhh',
fcntl.ioctl(0, termios.TIOCGWINSZ,
"\000"*8))[0:2]
if self.height == 0 or self.width == 0:
self.height, self.width = (25, 80)
except:
self.height, self.width = (25, 80)
def format(self, record):
'''format a record for display'''
returns = []
line_len = self.width - len(record.name) - 2
if type(record.msg) in types.StringTypes:
for line in record.msg.split('\n'):
if len(line) <= line_len:
returns.append("%s: %s" % (record.name, line))
else:
inner_lines = int(math.floor(float(len(line)) / line_len))+1
for i in xrange(inner_lines):
returns.append("%s: %s" % (record.name, line[i*line_len:(i+1)*line_len]))
elif type(record.msg) == types.ListType:
record.msg.sort()
msgwidth = self.width - len(record.name) - 2
columnWidth = max([len(item) for item in record.msg])
columns = int(math.floor(float(msgwidth) / (columnWidth+2)))
lines = int(math.ceil(float(len(record.msg)) / columns))
for lineNumber in xrange(lines):
indices = [idx for idx in [(colNum * lines) + lineNumber
for colNum in range(columns)] if idx < len(record.msg)]
format = record.name + ':' + (len(indices) * (" %%-%ds " % columnWidth))
returns.append(format % tuple([record.msg[idx] for idx in indices]))
else:
# got unsupported type
returns.append(record.name + ':' + str(record.msg))
if record.exc_info:
returns.append(self.formatException(record.exc_info))
return '\n'.join(returns)
class FragmentingSysLogHandler(logging.handlers.SysLogHandler):
'''This handler fragments messages into chunks smaller than 250 characters'''
def emit(self, record):
'''chunk and deliver records'''
if str(record.msg) > 250:
start = 0
msgdata = str(record.msg)
while start < len(msgdata):
newrec = copy.deepcopy(record)
newrec.msg = msgdata[start:start+250]
logging.handlers.SysLogHandler.emit(self, newrec)
start += 250
else:
logging.handlers.SysLogHandler.emit(self, newrec)
def setup_logging(to_console=True, to_syslog=True, level=0):
'''setup logging for bcfg2 software'''
if hasattr(logging, 'enabled'):
return
console = logging.StreamHandler()
console.setLevel(logging.DEBUG)
# tell the handler to use this format
console.setFormatter(TermiosFormatter())
syslog = FragmentingSysLogHandler('/dev/log', 'local0')
syslog.setLevel(logging.DEBUG)
syslog.setFormatter(logging.Formatter('%(name)s[%(process)d]: %(message)s'))
# add the handler to the root logger
if to_console:
logging.root.addHandler(console)
if to_syslog:
logging.root.addHandler(syslog)
logging.root.level = level
logging.enabled = True
|