2
2
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
3
3
# See LICENSE for details.
6
5
"""Logging and metrics infrastructure.
8
from __future__ import division
15
17
from twisted.python import util, context, reflect
19
UnicodeEncodeError # Introduced sometime after Python 2.2.3
21
UnicodeEncodeError = UnicodeError
25
20
"""Actually, this interface is just a synoym for the dictionary interface,
26
21
but it serves as a key for the default information in a log.
60
"""Write some data to the log.
61
DEPRECATED. Use L{msg} instead."""
62
warnings.warn("Use log.msg, not log.write.", DeprecationWarning, stacklevel=2)
65
def debug(*stuff,**otherstuff):
67
Write some debug data to the log. It passes debug=1 in the log
70
DEPRECATED (Since Twisted 2.1): Pass debug=1 to msg() yourself.
72
warnings.warn("Use log.msg(..., debug=True), not log.debug().", DeprecationWarning, stacklevel=2)
73
msg(debug=1, *stuff, **otherstuff)
75
54
def showwarning(message, category, filename, lineno, file=None):
77
msg(warning=message, category=category, filename=filename, lineno=lineno,
56
msg(warning=message, category=reflect.qual(category), filename=filename, lineno=lineno,
78
57
format="%(filename)s:%(lineno)s: %(category)s: %(warning)s")
80
59
_oldshowwarning(message, category, filename, lineno, file)
86
65
def startKeepingErrors():
87
"""Support function for testing frameworks.
67
DEPRECATED in Twisted 2.5.
69
Support function for testing frameworks.
89
71
Start keeping errors in a buffer which can be retrieved (and emptied) with
74
warnings.warn("log.startKeepingErrors is deprecated since Twisted 2.5",
75
category=DeprecationWarning, stacklevel=2)
96
80
def flushErrors(*errorTypes):
97
"""Support function for testing frameworks.
82
DEPRECATED in Twisted 2.5. See L{TestCase.flushLoggedErrors}.
84
Support function for testing frameworks.
99
86
Return a list of errors that occurred since the last call to flushErrors().
100
87
(This will return None unless startKeepingErrors has been called.)
90
warnings.warn("log.flushErrors is deprecated since Twisted 2.5. "
91
"If you need to flush errors from within a unittest, "
92
"use TestCase.flushLoggedErrors instead.",
93
category=DeprecationWarning, stacklevel=2)
94
return _flushErrors(*errorTypes)
97
def _flushErrors(*errorTypes):
99
PRIVATE. DEPRECATED. DON'T USE.
103
101
global _keptErrors
116
114
def ignoreErrors(*types):
116
warnings.warn("log.ignoreErrors is deprecated since Twisted 2.5",
117
category=DeprecationWarning, stacklevel=2)
122
PRIVATE. DEPRECATED. DON'T USE.
117
124
for type in types:
118
125
_ignoreErrors.append(type)
120
127
def clearIgnores():
129
warnings.warn("log.clearIgnores is deprecated since Twisted 2.5",
130
category=DeprecationWarning, stacklevel=2)
135
PRIVATE. DEPRECATED. DON'T USE.
121
137
global _ignoreErrors
122
138
_ignoreErrors = []
124
def err(_stuff=None,**kw):
141
def err(_stuff=None, _why=None, **kw):
126
143
Write a failure to the log.
142
159
_keptErrors.append(_stuff)
144
161
_keptErrors.append(_stuff)
145
msg(failure=_stuff, isError=1, **kw)
162
msg(failure=_stuff, why=_why, isError=1, **kw)
146
163
elif isinstance(_stuff, Exception):
147
msg(failure=failure.Failure(_stuff), isError=1, **kw)
164
msg(failure=failure.Failure(_stuff), why=_why, isError=1, **kw)
149
msg(repr(_stuff), isError=1, **kw)
166
msg(repr(_stuff), why=_why, isError=1, **kw)
166
class EscapeFromTheMeaninglessConfinesOfCapital:
167
def own(self, owner):
168
warnings.warn("Foolish capitalist! Your opulent toilet will be your undoing!!",
169
DeprecationWarning, stacklevel=2)
170
def disown(self, owner):
171
warnings.warn("The proletariat is victorious.",
172
DeprecationWarning, stacklevel=2)
174
logOwner = EscapeFromTheMeaninglessConfinesOfCapital()
177
182
class LogPublisher:
178
183
"""Class for singleton log message publishing."""
226
231
o = self.observers.pop(i)
227
msg("Log observer %s failed, removing from observer list." % (o,))
232
err(failure.Failure(),
233
"Log observer %s failed, removing from observer list." % (o,))
240
245
class FileLogObserver:
241
"""Log observer that writes to a file-like object.
247
Log observer that writes to a file-like object.
243
@ivar timeFormat: Format string passed to strftime()
249
@type timeFormat: C{str} or C{NoneType}
250
@ivar timeFormat: If not C{None}, the format string passed to strftime().
245
timeFormat = "%Y/%m/%d %H:%M %Z"
247
254
def __init__(self, f):
248
255
self.write = f.write
269
276
text = 'PATHOLOGICAL ERROR IN BOTH FORMAT STRING AND MESSAGE DETAILS, MESSAGE LOST'
280
def getTimezoneOffset(self):
282
Return the current local timezone offset from UTC.
285
@return: The number of seconds offset from UTC. West is positive,
293
def formatTime(self, when):
295
Return the given UTC value formatted as a human-readable string
296
representing that time in the local timezone.
299
@param when: POSIX timestamp to convert to a human-readable string.
303
if self.timeFormat is not None:
304
return time.strftime(self.timeFormat, time.localtime(when))
306
tzOffset = -self.getTimezoneOffset()
307
when = datetime.datetime.utcfromtimestamp(when + tzOffset)
308
tzHour = int(tzOffset / 60 / 60)
309
tzMin = int(tzOffset / 60 % 60)
310
return '%d/%02d/%02d %02d:%02d %+03d%02d' % (
311
when.year, when.month, when.day,
312
when.hour, when.minute,
272
316
def emit(self, eventDict):
273
317
edm = eventDict['message']
275
319
if eventDict['isError'] and eventDict.has_key('failure'):
276
text = eventDict['failure'].getTraceback()
320
text = ((eventDict.get('why') or 'Unhandled Error')
321
+ '\n' + eventDict['failure'].getTraceback())
277
322
elif eventDict.has_key('format'):
278
323
text = self._safeFormat(eventDict['format'], eventDict)
283
328
text = ' '.join(map(reflect.safe_str, edm))
285
timeStr = time.strftime(self.timeFormat, time.localtime(eventDict['time']))
330
timeStr = self.formatTime(eventDict['time'])
286
331
fmtDict = {'system': eventDict['system'], 'text': text.replace("\n", "\n\t")}
287
332
msgStr = self._safeFormat("[%(system)s] %(text)s\n", fmtDict)