519
519
message = format % args
523
# first all the unlimited ones
524
if level > getCategoryLevel(category):
525
handlers = _log_handlers
527
handlers = _log_handlers + _log_handlers_limited
525
530
if filePath is None and line is None:
526
531
(filePath, line, funcname) = getFileLine(where=where)
527
532
ret['filePath'] = filePath
528
533
ret['line'] = line
530
535
message = "\033[00m\033[32;01m%s:\033[00m %s" % (funcname, message)
531
for handler in _log_handlers:
536
for handler in handlers:
533
handler(level, object, category, file, line, message)
538
handler(level, object, category, filePath, line, message)
534
539
except TypeError, e:
535
540
raise SystemError("handler %r raised a TypeError: %s" % (
536
541
handler, getExceptionMessage(e)))
538
if level > getCategoryLevel(category):
541
if _log_handlers_limited:
542
if filePath is None and line is None:
543
(filePath, line, funcname) = getFileLine(where=where)
544
ret['filePath'] = filePath
547
message = "\033[00m\033[32;01m%s:\033[00m %s" % (funcname, message)
548
for handler in _log_handlers_limited:
549
# set this a second time, just in case there weren't unlimited
550
# loggers there before
552
handler(level, object, category, filePath, line, message)
554
raise SystemError("handler %r raised a TypeError" % handler)
559
546
def errorObject(object, cat, format, *args):
1024
1001
return doLog(level, self.logObjectName(), self.logCategory,
1025
1002
format, args, where=where, **kwargs)
1027
def warningFailure(self, failure, swallow=True):
1029
Log a warning about a Twisted Failure. Useful as an errback handler:
1030
d.addErrback(self.warningFailure)
1032
@param swallow: whether to swallow the failure or not
1035
if _canShortcutLogging(self.logCategory, WARN):
1039
warningObject(self.logObjectName(), self.logCategory,
1040
*self.logFunction(getFailureMessage(failure)))
1044
1004
def logFunction(self, *args):
1045
1005
"""Overridable log function. Default just returns passed message."""
1057
1017
def handleException(self, exc):
1058
1018
self.warning(getExceptionMessage(exc))
1060
# Twisted helper stuff
1063
_initializedTwisted = False
1066
__theTwistedLogObserver = None
1069
def _getTheTwistedLogObserver():
1070
# used internally and in test
1071
global __theTwistedLogObserver
1073
if not __theTwistedLogObserver:
1074
__theTwistedLogObserver = TwistedLogObserver()
1076
return __theTwistedLogObserver
1079
# public helper methods
1082
def getFailureMessage(failure):
1084
Return a short message based on L{twisted.python.failure.Failure}.
1085
Tries to find where the exception was triggered.
1087
exc = str(failure.type)
1088
msg = failure.getErrorMessage()
1089
if len(failure.frames) == 0:
1090
return "failure %(exc)s: %(msg)s" % locals()
1092
(func, filename, line, some, other) = failure.frames[-1]
1093
filename = scrubFilename(filename)
1094
return "failure %(exc)s at %(filename)s:%(line)s: %(func)s(): %(msg)s" % locals()
1097
def warningFailure(failure, swallow=True):
1099
Log a warning about a Failure. Useful as an errback handler:
1100
d.addErrback(warningFailure)
1102
@param swallow: whether to swallow the failure or not
1105
warning('', getFailureMessage(failure))
1112
Integrate twisted's logger with our logger.
1114
This is done in a separate method because calling this imports and sets
1115
up a reactor. Since we want basic logging working before choosing a
1116
reactor, we need to separate these.
1118
global _initializedTwisted
1120
if _initializedTwisted:
1123
debug('log', 'Integrating twisted logger')
1125
# integrate twisted's logging with us
1126
from twisted.python import log as tlog
1128
# this call imports the reactor
1129
# that is why we do this in a separate method
1130
from twisted.spread import pb
1132
# we don't want logs for pb.Error types since they
1133
# are specifically raised to be handled on the other side
1134
observer = _getTheTwistedLogObserver()
1135
observer.ignoreErrors([pb.Error, ])
1136
tlog.startLoggingWithObserver(observer.emit, False)
1138
_initializedTwisted = True
1141
# we need an object as the observer because startLoggingWithObserver
1142
# expects a bound method
1145
class TwistedLogObserver(BaseLoggable):
1147
Twisted log observer that integrates with our logging.
1149
logCategory = "logobserver"
1152
self._ignoreErrors = [] # Failure types
1154
def emit(self, eventDict):
1155
method = log # by default, lowest level
1156
edm = eventDict['message']
1158
if eventDict['isError'] and 'failure' in eventDict:
1159
f = eventDict['failure']
1160
for failureType in self._ignoreErrors:
1161
r = f.check(failureType)
1163
self.debug("Failure of type %r, ignoring" % failureType)
1166
self.log("Failure %r" % f)
1168
method = debug # tracebacks from errors at debug level
1169
msg = "A twisted traceback occurred."
1170
if getCategoryLevel("twisted") < WARN:
1171
msg += " Run with debug level >= 2 to see the traceback."
1172
# and an additional warning
1173
warning('twisted', msg)
1174
text = f.getTraceback()
1175
safeprintf(sys.stderr, "\nTwisted traceback:\n")
1176
safeprintf(sys.stderr, text + '\n')
1177
elif 'format' in eventDict:
1178
text = eventDict['format'] % eventDict
1180
# we don't know how to log this
1183
text = ' '.join(map(str, edm))
1185
fmtDict = {'system': eventDict['system'],
1186
'text': text.replace("\n", "\n\t")}
1187
msgStr = " [%(system)s] %(text)s\n" % fmtDict
1188
# because msgstr can contain %, as in a backtrace, make sure we
1189
# don't try to splice it
1190
method('twisted', msgStr)
1192
def ignoreErrors(self, *types):
1193
for failureType in types:
1194
self._ignoreErrors.append(failureType)
1196
def clearIgnores(self):
1197
self._ignoreErrors = []
1200
1021
class Loggable(BaseLoggable):
1201
1022
def __init__(self, logCategory=None):