test_splits takes allowed/target codecs as arguments, no longer relies on get_codec.
[audiomangler.git] / audiomangler / logging.py
blobcdaf527c7977a59cc51e54392fe6f5c1182dfcda
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=VERBOSE):
17 self.output = f
18 self.loglevel = get_level(loglevel, VERBOSE)
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(level, default=ERROR):
70 try:
71 return int(level)
72 except ValueError:
73 pass
74 try:
75 if isinstance(level, basestring):
76 level = level.upper()
77 return loglevels[level]
78 except KeyError:
79 return default
81 def err(*msg, **kwargs):
82 global collector, logfile
83 if 'nologerror' not in kwargs:
84 if collector is None:
85 try:
86 collector = FilteredFileLogObserver(StringIO(), ERROR)
87 collector.start()
88 except: pass
89 if logfile is None:
90 try:
91 logfile = FilteredFileLogObserver(open(Config.get('logfile', 'audiomangler-%d.log' % os.getpid()), 'wb'), get_level(Config['loglevel']))
92 logfile.start()
93 except: pass
94 kwargs['loglevel'] = ERROR
95 if msg and isinstance(msg[0], (failure.Failure, Exception)):
96 log.err(_noignore=1, *msg, **kwargs)
97 else:
98 log.msg(_noignore=1, *msg, **kwargs)
100 def msg(*msg, **kwargs):
101 global logfile, logout
102 if logout is None:
103 try:
104 logout = FilteredConsoleLogObserver(Config['consolelevel'])
105 logout.start()
106 except: pass
107 kwargs.setdefault('loglevel', DEBUG)
108 if kwargs['loglevel'] == ERROR:
109 err(_noignore=1, *msg, **kwargs)
110 else:
111 if Config['logfile'] and logfile is None and kwargs['loglevel'] <= get_level(Config['loglevel']):
112 try:
113 logfile = FilteredFileLogObserver(open(Config['logfile'], 'wb'), Config['loglevel'])
114 logfile.start()
115 except: pass
116 log.msg(_noignore=1, *msg, **kwargs)
118 def fatal(*msg, **kwargs):
119 err(*msg, **kwargs)
120 sys.exit()
122 def cleanup():
123 if logout:
124 sys.stdout.flush()
125 logout.stop()
126 if collector:
127 collector.output.flush()
128 collector.stop()
129 text = collector.output.getvalue()
130 if text:
131 print "The following errors occurred:"
132 print text
133 print "The above errors may also have been reported during processing."
134 if logfile:
135 logfile.output.flush()
136 logfile.stop()
137 print "Errors are also recorded in the logfile '%s'." % os.path.abspath(logfile.output.name)
138 sys.stdout.flush()
140 if log.defaultObserver:
141 log.defaultObserver.stop()
142 log.defaultObserver = None
144 atexit.register(cleanup)
146 __all__ = ['err', 'msg', 'fatal', 'ERROR', 'WARNING', 'INFO', 'VERBOSE', 'DEBUG']