Fix broken loglevel handling in logging
[audiomangler.git] / audiomangler / logging.py
blob34e36158145aec788476e0c5f18afaad97a81bb1
1 # -*- coding: utf-8 -*-
2 from twisted.python import log, failure
3 from audiomangler.config import Config
4 import os, sys, atexit
6 try:
7 from cStringIO import StringIO
8 except ImportError:
9 from StringIO import StringIO
11 loglevels = dict(ERROR=0, WARNING=1, INFO=2, VERBOSE=3, DEBUG=4)
12 loglevels.update(map(reversed, loglevels.items()))
13 ERROR, WARNING, INFO, VERBOSE, DEBUG = range(5)
15 class FilteredFileLogObserver(log.FileLogObserver):
16 def __init__(self, f, loglevel=INFO):
17 self.output = f
18 self.loglevel = get_level(loglevel, INFO)
20 def emit(self, eventDict):
21 if '_noignore' not in eventDict and not eventDict['isError']: return
22 if eventDict.get('loglevel', DEBUG) > self.loglevel:
23 return
24 encoding = sys.stdout.encoding
25 if eventDict['isError'] and 'failure' in eventDict:
26 text = log.textFromEventDict(eventDict)
27 elif eventDict['message']:
28 text = ' '.join(s.encode(encoding, 'replace') if isinstance(s, unicode) else s for s in eventDict['message'])
29 elif 'format' in eventDict or 'consoleformat' in eventDict:
30 fmt = eventDict.get('format', eventDict.get('consoleformat'))
31 text = (fmt % eventDict).encode(encoding, 'replace')
32 else:
33 text = log.textFromEventDict(eventDict)
34 timeStr = self.formatTime(eventDict['time'])
35 self.output.write(timeStr + ' [' + loglevels[eventDict['loglevel']].ljust(7) + '] ' + text + '\n')
37 class FilteredConsoleLogObserver:
38 def __init__(self, loglevel=INFO):
39 self.loglevel = get_level(loglevel, INFO)
41 def start(self):
42 log.addObserver(self.emit)
44 def stop(self):
45 log.removeObserver(self.emit)
47 def emit(self, eventDict):
48 if '_noignore' not in eventDict and not eventDict['isError']: return
50 if eventDict.get('loglevel', DEBUG) > self.loglevel:
51 return
52 encoding = sys.stdout.encoding
53 if eventDict['isError'] and 'failure' in eventDict:
54 text = log.textFromEventDict(eventDict)
55 elif eventDict['message']:
56 text = ''.join(s.encode(encoding, 'replace') if isinstance(s, unicode) else s for s in eventDict['message'])
57 elif 'format' in eventDict or 'consoleformat' in eventDict:
58 fmt = eventDict.get('consoleformat', eventDict.get('format'))
59 text = (fmt % eventDict).encode(encoding, 'replace')
60 else:
61 text = log.textFromEventDict(eventDict)
62 sys.stdout.write(text + '\n')
63 sys.stdout.flush()
65 collector = None
66 logfile = None
67 logout = None
69 def get_level(x, default=ERROR):
70 try:
71 return int(x)
72 except ValueError:
73 pass
74 try:
75 return loglevels[x]
76 except KeyError:
77 return default
79 def err(*msg, **kwargs):
80 global collector, logfile
81 if 'nologerror' not in kwargs:
82 if collector is None:
83 try:
84 collector = FilteredFileLogObserver(StringIO(), ERROR)
85 collector.start()
86 except: pass
87 if logfile is None:
88 try:
89 logfile = FilteredFileLogObserver(open(Config.get('logfile', 'audiomangler-%d.log' % os.getpid()), 'wb'), get_level(Config['loglevel']))
90 logfile.start()
91 except: pass
92 kwargs['loglevel'] = ERROR
93 if msg and isinstance(msg[0], (failure.Failure, Exception)):
94 log.err(_noignore=1, *msg, **kwargs)
95 else:
96 log.msg(_noignore=1, *msg, **kwargs)
98 def msg(*msg, **kwargs):
99 global logfile, logout
100 if logout is None:
101 try:
102 logout = FilteredConsoleLogObserver(Config['consolelevel'])
103 logout.start()
104 except: pass
105 kwargs.setdefault('loglevel', DEBUG)
106 if kwargs['loglevel'] == ERROR:
107 err(_noignore=1, *msg, **kwargs)
108 else:
109 if Config['logfile'] and logfile is None and kwargs['loglevel'] <= get_level(Config['loglevel']):
110 try:
111 logfile = FilteredFileLogObserver(open(Config['logfile'], 'wb'), Config['loglevel'])
112 logfile.start()
113 except: pass
114 log.msg(_noignore=1, *msg, **kwargs)
116 def fatal(*msg, **kwargs):
117 err(*msg, **kwargs)
118 sys.exit()
120 def cleanup():
121 if logout:
122 sys.stdout.flush()
123 logout.stop()
124 if collector:
125 collector.output.flush()
126 collector.stop()
127 text = collector.output.getvalue()
128 if text:
129 print "The following errors occurred:"
130 print text
131 print "The above errors may also have been reported during processing."
132 if logfile:
133 logfile.output.flush()
134 logfile.stop()
135 print "Errors are also recorded in the logfile '%s'." % os.path.abspath(logfile.output.name)
136 sys.stdout.flush()
138 if log.defaultObserver:
139 log.defaultObserver.stop()
140 log.defaultObserver = None
142 atexit.register(cleanup)
144 __all__ = ['err', 'msg', 'fatal', 'ERROR', 'WARNING', 'INFO', 'VERBOSE', 'DEBUG']