blob: 9d6aa92ec618328304aeedf7ae2dfed1dbbbcc82 [file] [log] [blame]
Guido van Rossum57102f82002-11-13 16:15:58 +00001# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
2#
3# Permission to use, copy, modify, and distribute this software and its
4# documentation for any purpose and without fee is hereby granted,
5# provided that the above copyright notice appear in all copies and that
6# both that copyright notice and this permission notice appear in
7# supporting documentation, and that the name of Vinay Sajip
8# not be used in advertising or publicity pertaining to distribution
9# of the software without specific, written prior permission.
10# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
11# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
12# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
13# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
14# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Guido van Rossum57102f82002-11-13 16:15:58 +000016
17"""
18Logging package for Python. Based on PEP 282 and comments thereto in
19comp.lang.python, and influenced by Apache's log4j system.
20
21Should work under Python versions >= 1.5.2, except that source line
Jeremy Hylton250684d2003-01-23 18:29:29 +000022information is not available unless 'sys._getframe()' is.
Guido van Rossum57102f82002-11-13 16:15:58 +000023
24Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
25
26To use, simply 'import logging' and log away!
27"""
28
Neal Norwitzd1cade02002-11-15 23:31:28 +000029import sys, os, types, time, string, cStringIO
Guido van Rossum57102f82002-11-13 16:15:58 +000030
31try:
32 import thread
33 import threading
34except ImportError:
35 thread = None
Guido van Rossum57102f82002-11-13 16:15:58 +000036
37__author__ = "Vinay Sajip <vinay_sajip@red-dove.com>"
Neal Norwitzf297bd12003-04-23 03:49:43 +000038__status__ = "beta"
Neal Norwitz6fa635d2003-02-18 14:20:07 +000039__version__ = "0.4.8"
Neal Norwitzf297bd12003-04-23 03:49:43 +000040__date__ = "22 April 2003"
Guido van Rossum57102f82002-11-13 16:15:58 +000041
42#---------------------------------------------------------------------------
43# Miscellaneous module data
44#---------------------------------------------------------------------------
45
46#
47#_srcfile is used when walking the stack to check when we've got the first
48# caller stack frame.
Neal Norwitz6fa635d2003-02-18 14:20:07 +000049#
Guido van Rossum455ab772002-11-13 16:18:29 +000050if string.lower(__file__[-4:]) in ['.pyc', '.pyo']:
51 _srcfile = __file__[:-4] + '.py'
Guido van Rossum57102f82002-11-13 16:15:58 +000052else:
Guido van Rossum455ab772002-11-13 16:18:29 +000053 _srcfile = __file__
54_srcfile = os.path.normcase(_srcfile)
Guido van Rossum57102f82002-11-13 16:15:58 +000055
Jeremy Hylton250684d2003-01-23 18:29:29 +000056# _srcfile is only used in conjunction with sys._getframe().
57# To provide compatibility with older versions of Python, set _srcfile
58# to None if _getframe() is not available; this value will prevent
59# findCaller() from being called.
60if not hasattr(sys, "_getframe"):
61 _srcfile = None
62
Guido van Rossum57102f82002-11-13 16:15:58 +000063#
64#_startTime is used as the base when calculating the relative time of events
65#
66_startTime = time.time()
67
68#
69#raiseExceptions is used to see if exceptions during handling should be
70#propagated
71#
72raiseExceptions = 1
73
Guido van Rossum57102f82002-11-13 16:15:58 +000074#---------------------------------------------------------------------------
75# Level related stuff
76#---------------------------------------------------------------------------
77#
78# Default levels and level names, these can be replaced with any positive set
79# of values having corresponding names. There is a pseudo-level, NOTSET, which
80# is only really there as a lower limit for user-defined levels. Handlers and
81# loggers are initialized with NOTSET so that they will log all messages, even
82# at user-defined levels.
83#
84CRITICAL = 50
85FATAL = CRITICAL
86ERROR = 40
Neal Norwitz6fa635d2003-02-18 14:20:07 +000087WARNING = 30
88WARN = WARNING
Guido van Rossum57102f82002-11-13 16:15:58 +000089INFO = 20
90DEBUG = 10
91NOTSET = 0
92
93_levelNames = {
94 CRITICAL : 'CRITICAL',
95 ERROR : 'ERROR',
Neal Norwitz6fa635d2003-02-18 14:20:07 +000096 WARNING : 'WARNING',
Guido van Rossum57102f82002-11-13 16:15:58 +000097 INFO : 'INFO',
98 DEBUG : 'DEBUG',
99 NOTSET : 'NOTSET',
100 'CRITICAL' : CRITICAL,
101 'ERROR' : ERROR,
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000102 'WARN' : WARNING,
103 'WARNING' : WARNING,
Guido van Rossum57102f82002-11-13 16:15:58 +0000104 'INFO' : INFO,
105 'DEBUG' : DEBUG,
106 'NOTSET' : NOTSET,
107}
108
109def getLevelName(level):
110 """
111 Return the textual representation of logging level 'level'.
112
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000113 If the level is one of the predefined levels (CRITICAL, ERROR, WARNING,
Guido van Rossum57102f82002-11-13 16:15:58 +0000114 INFO, DEBUG) then you get the corresponding string. If you have
115 associated levels with names using addLevelName then the name you have
116 associated with 'level' is returned. Otherwise, the string
117 "Level %s" % level is returned.
118 """
119 return _levelNames.get(level, ("Level %s" % level))
120
121def addLevelName(level, levelName):
122 """
123 Associate 'levelName' with 'level'.
124
125 This is used when converting levels to text during message formatting.
126 """
127 _acquireLock()
128 try: #unlikely to cause an exception, but you never know...
129 _levelNames[level] = levelName
130 _levelNames[levelName] = level
131 finally:
132 _releaseLock()
133
134#---------------------------------------------------------------------------
135# Thread-related stuff
136#---------------------------------------------------------------------------
137
138#
139#_lock is used to serialize access to shared data structures in this module.
140#This needs to be an RLock because fileConfig() creates Handlers and so
141#might arbitrary user threads. Since Handler.__init__() updates the shared
142#dictionary _handlers, it needs to acquire the lock. But if configuring,
143#the lock would already have been acquired - so we need an RLock.
144#The same argument applies to Loggers and Manager.loggerDict.
145#
146_lock = None
147
148def _acquireLock():
149 """
150 Acquire the module-level lock for serializing access to shared data.
151
152 This should be released with _releaseLock().
153 """
154 global _lock
155 if (not _lock) and thread:
156 _lock = threading.RLock()
157 if _lock:
158 _lock.acquire()
159
160def _releaseLock():
161 """
162 Release the module-level lock acquired by calling _acquireLock().
163 """
164 if _lock:
165 _lock.release()
166
167#---------------------------------------------------------------------------
168# The logging record
169#---------------------------------------------------------------------------
170
171class LogRecord:
172 """
173 A LogRecord instance represents an event being logged.
174
175 LogRecord instances are created every time something is logged. They
176 contain all the information pertinent to the event being logged. The
177 main information passed in is in msg and args, which are combined
178 using str(msg) % args to create the message field of the record. The
179 record also includes information such as when the record was created,
180 the source line where the logging call was made, and any exception
181 information to be logged.
182 """
183 def __init__(self, name, level, pathname, lineno, msg, args, exc_info):
184 """
185 Initialize a logging record with interesting information.
186 """
187 ct = time.time()
188 self.name = name
189 self.msg = msg
190 self.args = args
191 self.levelname = getLevelName(level)
192 self.levelno = level
193 self.pathname = pathname
194 try:
195 self.filename = os.path.basename(pathname)
196 self.module = os.path.splitext(self.filename)[0]
197 except:
198 self.filename = pathname
199 self.module = "Unknown module"
200 self.exc_info = exc_info
201 self.lineno = lineno
202 self.created = ct
203 self.msecs = (ct - long(ct)) * 1000
204 self.relativeCreated = (self.created - _startTime) * 1000
205 if thread:
206 self.thread = thread.get_ident()
207 else:
208 self.thread = None
Jack Jansen4c641d02003-02-21 22:29:45 +0000209 if hasattr(os, 'getpid'):
210 self.process = os.getpid()
211 else:
212 self.process = None
Guido van Rossum57102f82002-11-13 16:15:58 +0000213
214 def __str__(self):
215 return '<LogRecord: %s, %s, %s, %s, "%s">'%(self.name, self.levelno,
216 self.pathname, self.lineno, self.msg)
217
218 def getMessage(self):
219 """
220 Return the message for this LogRecord.
221
222 Return the message for this LogRecord after merging any user-supplied
223 arguments with the message.
224 """
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000225 if not hasattr(types, "UnicodeType"): #if no unicode support...
226 msg = str(self.msg)
227 else:
228 try:
229 msg = str(self.msg)
230 except UnicodeError:
231 msg = self.msg #Defer encoding till later
Guido van Rossum57102f82002-11-13 16:15:58 +0000232 if self.args:
233 msg = msg % self.args
234 return msg
235
236#---------------------------------------------------------------------------
237# Formatter classes and functions
238#---------------------------------------------------------------------------
239
240class Formatter:
241 """
242 Formatter instances are used to convert a LogRecord to text.
243
244 Formatters need to know how a LogRecord is constructed. They are
245 responsible for converting a LogRecord to (usually) a string which can
246 be interpreted by either a human or an external system. The base Formatter
247 allows a formatting string to be specified. If none is supplied, the
248 default value of "%s(message)\\n" is used.
249
250 The Formatter can be initialized with a format string which makes use of
251 knowledge of the LogRecord attributes - e.g. the default value mentioned
252 above makes use of the fact that the user's message and arguments are pre-
253 formatted into a LogRecord's message attribute. Currently, the useful
254 attributes in a LogRecord are described by:
255
256 %(name)s Name of the logger (logging channel)
257 %(levelno)s Numeric logging level for the message (DEBUG, INFO,
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000258 WARNING, ERROR, CRITICAL)
Guido van Rossum57102f82002-11-13 16:15:58 +0000259 %(levelname)s Text logging level for the message ("DEBUG", "INFO",
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000260 "WARNING", "ERROR", "CRITICAL")
Guido van Rossum57102f82002-11-13 16:15:58 +0000261 %(pathname)s Full pathname of the source file where the logging
262 call was issued (if available)
263 %(filename)s Filename portion of pathname
264 %(module)s Module (name portion of filename)
265 %(lineno)d Source line number where the logging call was issued
266 (if available)
267 %(created)f Time when the LogRecord was created (time.time()
268 return value)
269 %(asctime)s Textual time when the LogRecord was created
270 %(msecs)d Millisecond portion of the creation time
271 %(relativeCreated)d Time in milliseconds when the LogRecord was created,
272 relative to the time the logging module was loaded
273 (typically at application startup time)
274 %(thread)d Thread ID (if available)
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000275 %(process)d Process ID (if available)
Guido van Rossum57102f82002-11-13 16:15:58 +0000276 %(message)s The result of record.getMessage(), computed just as
277 the record is emitted
278 """
279
280 converter = time.localtime
281
282 def __init__(self, fmt=None, datefmt=None):
283 """
284 Initialize the formatter with specified format strings.
285
286 Initialize the formatter either with the specified format string, or a
287 default as described above. Allow for specialized date formatting with
288 the optional datefmt argument (if omitted, you get the ISO8601 format).
289 """
290 if fmt:
291 self._fmt = fmt
292 else:
293 self._fmt = "%(message)s"
294 self.datefmt = datefmt
295
296 def formatTime(self, record, datefmt=None):
297 """
298 Return the creation time of the specified LogRecord as formatted text.
299
300 This method should be called from format() by a formatter which
301 wants to make use of a formatted time. This method can be overridden
302 in formatters to provide for any specific requirement, but the
303 basic behaviour is as follows: if datefmt (a string) is specified,
304 it is used with time.strftime() to format the creation time of the
305 record. Otherwise, the ISO8601 format is used. The resulting
306 string is returned. This function uses a user-configurable function
307 to convert the creation time to a tuple. By default, time.localtime()
308 is used; to change this for a particular formatter instance, set the
309 'converter' attribute to a function with the same signature as
310 time.localtime() or time.gmtime(). To change it for all formatters,
311 for example if you want all logging times to be shown in GMT,
312 set the 'converter' attribute in the Formatter class.
313 """
314 ct = self.converter(record.created)
315 if datefmt:
316 s = time.strftime(datefmt, ct)
317 else:
318 t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
319 s = "%s,%03d" % (t, record.msecs)
320 return s
321
322 def formatException(self, ei):
323 """
324 Format and return the specified exception information as a string.
325
326 This default implementation just uses
327 traceback.print_exception()
328 """
329 import traceback
330 sio = cStringIO.StringIO()
331 traceback.print_exception(ei[0], ei[1], ei[2], None, sio)
332 s = sio.getvalue()
333 sio.close()
334 if s[-1] == "\n":
335 s = s[:-1]
336 return s
337
338 def format(self, record):
339 """
340 Format the specified record as text.
341
342 The record's attribute dictionary is used as the operand to a
343 string formatting operation which yields the returned string.
344 Before formatting the dictionary, a couple of preparatory steps
345 are carried out. The message attribute of the record is computed
346 using LogRecord.getMessage(). If the formatting string contains
347 "%(asctime)", formatTime() is called to format the event time.
348 If there is exception information, it is formatted using
349 formatException() and appended to the message.
350 """
351 record.message = record.getMessage()
352 if string.find(self._fmt,"%(asctime)") >= 0:
353 record.asctime = self.formatTime(record, self.datefmt)
354 s = self._fmt % record.__dict__
355 if record.exc_info:
356 if s[-1] != "\n":
357 s = s + "\n"
358 s = s + self.formatException(record.exc_info)
359 return s
360
361#
362# The default formatter to use when no other is specified
363#
364_defaultFormatter = Formatter()
365
366class BufferingFormatter:
367 """
368 A formatter suitable for formatting a number of records.
369 """
370 def __init__(self, linefmt=None):
371 """
372 Optionally specify a formatter which will be used to format each
373 individual record.
374 """
375 if linefmt:
376 self.linefmt = linefmt
377 else:
378 self.linefmt = _defaultFormatter
379
380 def formatHeader(self, records):
381 """
382 Return the header string for the specified records.
383 """
384 return ""
385
386 def formatFooter(self, records):
387 """
388 Return the footer string for the specified records.
389 """
390 return ""
391
392 def format(self, records):
393 """
394 Format the specified records and return the result as a string.
395 """
396 rv = ""
397 if len(records) > 0:
398 rv = rv + self.formatHeader(records)
399 for record in records:
400 rv = rv + self.linefmt.format(record)
401 rv = rv + self.formatFooter(records)
402 return rv
403
404#---------------------------------------------------------------------------
405# Filter classes and functions
406#---------------------------------------------------------------------------
407
408class Filter:
409 """
410 Filter instances are used to perform arbitrary filtering of LogRecords.
411
412 Loggers and Handlers can optionally use Filter instances to filter
413 records as desired. The base filter class only allows events which are
414 below a certain point in the logger hierarchy. For example, a filter
415 initialized with "A.B" will allow events logged by loggers "A.B",
416 "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If
417 initialized with the empty string, all events are passed.
418 """
419 def __init__(self, name=''):
420 """
421 Initialize a filter.
422
423 Initialize with the name of the logger which, together with its
424 children, will have its events allowed through the filter. If no
425 name is specified, allow every event.
426 """
427 self.name = name
428 self.nlen = len(name)
429
430 def filter(self, record):
431 """
432 Determine if the specified record is to be logged.
433
434 Is the specified record to be logged? Returns 0 for no, nonzero for
435 yes. If deemed appropriate, the record may be modified in-place.
436 """
437 if self.nlen == 0:
438 return 1
439 elif self.name == record.name:
440 return 1
441 elif string.find(record.name, self.name, 0, self.nlen) != 0:
442 return 0
443 return (record.name[self.nlen] == ".")
444
445class Filterer:
446 """
447 A base class for loggers and handlers which allows them to share
448 common code.
449 """
450 def __init__(self):
451 """
452 Initialize the list of filters to be an empty list.
453 """
454 self.filters = []
455
456 def addFilter(self, filter):
457 """
458 Add the specified filter to this handler.
459 """
460 if not (filter in self.filters):
461 self.filters.append(filter)
462
463 def removeFilter(self, filter):
464 """
465 Remove the specified filter from this handler.
466 """
467 if filter in self.filters:
468 self.filters.remove(filter)
469
470 def filter(self, record):
471 """
472 Determine if a record is loggable by consulting all the filters.
473
474 The default is to allow the record to be logged; any filter can veto
475 this and the record is then dropped. Returns a zero value if a record
476 is to be dropped, else non-zero.
477 """
478 rv = 1
479 for f in self.filters:
480 if not f.filter(record):
481 rv = 0
482 break
483 return rv
484
485#---------------------------------------------------------------------------
486# Handler classes and functions
487#---------------------------------------------------------------------------
488
489_handlers = {} #repository of handlers (for flushing when shutdown called)
490
491class Handler(Filterer):
492 """
493 Handler instances dispatch logging events to specific destinations.
494
495 The base handler class. Acts as a placeholder which defines the Handler
496 interface. Handlers can optionally use Formatter instances to format
497 records as desired. By default, no formatter is specified; in this case,
498 the 'raw' message as determined by record.message is logged.
499 """
500 def __init__(self, level=NOTSET):
501 """
502 Initializes the instance - basically setting the formatter to None
503 and the filter list to empty.
504 """
505 Filterer.__init__(self)
506 self.level = level
507 self.formatter = None
508 #get the module data lock, as we're updating a shared structure.
509 _acquireLock()
510 try: #unlikely to raise an exception, but you never know...
511 _handlers[self] = 1
512 finally:
513 _releaseLock()
514 self.createLock()
515
516 def createLock(self):
517 """
518 Acquire a thread lock for serializing access to the underlying I/O.
519 """
520 if thread:
521 self.lock = thread.allocate_lock()
522 else:
523 self.lock = None
524
525 def acquire(self):
526 """
527 Acquire the I/O thread lock.
528 """
529 if self.lock:
530 self.lock.acquire()
531
532 def release(self):
533 """
534 Release the I/O thread lock.
535 """
536 if self.lock:
537 self.lock.release()
538
539 def setLevel(self, level):
540 """
541 Set the logging level of this handler.
542 """
543 self.level = level
544
545 def format(self, record):
546 """
547 Format the specified record.
548
549 If a formatter is set, use it. Otherwise, use the default formatter
550 for the module.
551 """
552 if self.formatter:
553 fmt = self.formatter
554 else:
555 fmt = _defaultFormatter
556 return fmt.format(record)
557
558 def emit(self, record):
559 """
560 Do whatever it takes to actually log the specified logging record.
561
562 This version is intended to be implemented by subclasses and so
563 raises a NotImplementedError.
564 """
565 raise NotImplementedError, 'emit must be implemented '\
566 'by Handler subclasses'
567
568 def handle(self, record):
569 """
570 Conditionally emit the specified logging record.
571
572 Emission depends on filters which may have been added to the handler.
573 Wrap the actual emission of the record with acquisition/release of
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000574 the I/O thread lock. Returns whether the filter passed the record for
575 emission.
Guido van Rossum57102f82002-11-13 16:15:58 +0000576 """
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000577 rv = self.filter(record)
578 if rv:
Guido van Rossum57102f82002-11-13 16:15:58 +0000579 self.acquire()
580 try:
581 self.emit(record)
582 finally:
583 self.release()
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000584 return rv
Guido van Rossum57102f82002-11-13 16:15:58 +0000585
586 def setFormatter(self, fmt):
587 """
588 Set the formatter for this handler.
589 """
590 self.formatter = fmt
591
592 def flush(self):
593 """
594 Ensure all logging output has been flushed.
595
596 This version does nothing and is intended to be implemented by
597 subclasses.
598 """
599 pass
600
601 def close(self):
602 """
603 Tidy up any resources used by the handler.
604
605 This version does nothing and is intended to be implemented by
606 subclasses.
607 """
608 pass
609
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000610 def handleError(self, record):
Guido van Rossum57102f82002-11-13 16:15:58 +0000611 """
612 Handle errors which occur during an emit() call.
613
614 This method should be called from handlers when an exception is
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000615 encountered during an emit() call. If raiseExceptions is false,
Guido van Rossum57102f82002-11-13 16:15:58 +0000616 exceptions get silently ignored. This is what is mostly wanted
617 for a logging system - most users will not care about errors in
618 the logging system, they are more interested in application errors.
619 You could, however, replace this with a custom handler if you wish.
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000620 The record which was being processed is passed in to this method.
Guido van Rossum57102f82002-11-13 16:15:58 +0000621 """
622 if raiseExceptions:
623 import traceback
624 ei = sys.exc_info()
625 traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
626 del ei
627
628class StreamHandler(Handler):
629 """
630 A handler class which writes logging records, appropriately formatted,
631 to a stream. Note that this class does not close the stream, as
632 sys.stdout or sys.stderr may be used.
633 """
634 def __init__(self, strm=None):
635 """
636 Initialize the handler.
637
638 If strm is not specified, sys.stderr is used.
639 """
640 Handler.__init__(self)
641 if not strm:
642 strm = sys.stderr
643 self.stream = strm
644 self.formatter = None
645
646 def flush(self):
647 """
648 Flushes the stream.
649 """
650 self.stream.flush()
651
652 def emit(self, record):
653 """
654 Emit a record.
655
656 If a formatter is specified, it is used to format the record.
657 The record is then written to the stream with a trailing newline
658 [N.B. this may be removed depending on feedback]. If exception
659 information is present, it is formatted using
660 traceback.print_exception and appended to the stream.
661 """
662 try:
663 msg = self.format(record)
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000664 if not hasattr(types, "UnicodeType"): #if no unicode support...
665 self.stream.write("%s\n" % msg)
666 else:
667 try:
668 self.stream.write("%s\n" % msg)
669 except UnicodeError:
670 self.stream.write("%s\n" % msg.encode("UTF-8"))
Guido van Rossum57102f82002-11-13 16:15:58 +0000671 self.flush()
672 except:
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000673 self.handleError(record)
Guido van Rossum57102f82002-11-13 16:15:58 +0000674
675class FileHandler(StreamHandler):
676 """
677 A handler class which writes formatted logging records to disk files.
678 """
679 def __init__(self, filename, mode="a"):
680 """
681 Open the specified file and use it as the stream for logging.
682 """
683 StreamHandler.__init__(self, open(filename, mode))
684 self.baseFilename = filename
685 self.mode = mode
686
687 def close(self):
688 """
689 Closes the stream.
690 """
691 self.stream.close()
692
693#---------------------------------------------------------------------------
694# Manager classes and functions
695#---------------------------------------------------------------------------
696
697class PlaceHolder:
698 """
699 PlaceHolder instances are used in the Manager logger hierarchy to take
700 the place of nodes for which no loggers have been defined [FIXME add
701 example].
702 """
703 def __init__(self, alogger):
704 """
705 Initialize with the specified logger being a child of this placeholder.
706 """
707 self.loggers = [alogger]
708
709 def append(self, alogger):
710 """
711 Add the specified logger as a child of this placeholder.
712 """
713 if alogger not in self.loggers:
714 self.loggers.append(alogger)
715
716#
717# Determine which class to use when instantiating loggers.
718#
719_loggerClass = None
720
721def setLoggerClass(klass):
722 """
723 Set the class to be used when instantiating a logger. The class should
724 define __init__() such that only a name argument is required, and the
725 __init__() should call Logger.__init__()
726 """
727 if klass != Logger:
Guido van Rossum57102f82002-11-13 16:15:58 +0000728 if not issubclass(klass, Logger):
729 raise TypeError, "logger not derived from logging.Logger: " + \
730 klass.__name__
731 global _loggerClass
732 _loggerClass = klass
733
734class Manager:
735 """
736 There is [under normal circumstances] just one Manager instance, which
737 holds the hierarchy of loggers.
738 """
Neal Norwitzd1cade02002-11-15 23:31:28 +0000739 def __init__(self, rootnode):
Guido van Rossum57102f82002-11-13 16:15:58 +0000740 """
741 Initialize the manager with the root node of the logger hierarchy.
742 """
Neal Norwitzd1cade02002-11-15 23:31:28 +0000743 self.root = rootnode
Guido van Rossum57102f82002-11-13 16:15:58 +0000744 self.disable = 0
745 self.emittedNoHandlerWarning = 0
746 self.loggerDict = {}
747
748 def getLogger(self, name):
749 """
750 Get a logger with the specified name (channel name), creating it
751 if it doesn't yet exist.
752
753 If a PlaceHolder existed for the specified name [i.e. the logger
754 didn't exist but a child of it did], replace it with the created
755 logger and fix up the parent/child references which pointed to the
756 placeholder to now point to the logger.
757 """
758 rv = None
759 _acquireLock()
760 try:
761 if self.loggerDict.has_key(name):
762 rv = self.loggerDict[name]
763 if isinstance(rv, PlaceHolder):
764 ph = rv
765 rv = _loggerClass(name)
766 rv.manager = self
767 self.loggerDict[name] = rv
768 self._fixupChildren(ph, rv)
769 self._fixupParents(rv)
770 else:
771 rv = _loggerClass(name)
772 rv.manager = self
773 self.loggerDict[name] = rv
774 self._fixupParents(rv)
775 finally:
776 _releaseLock()
777 return rv
778
779 def _fixupParents(self, alogger):
780 """
781 Ensure that there are either loggers or placeholders all the way
782 from the specified logger to the root of the logger hierarchy.
783 """
784 name = alogger.name
785 i = string.rfind(name, ".")
786 rv = None
787 while (i > 0) and not rv:
788 substr = name[:i]
789 if not self.loggerDict.has_key(substr):
790 self.loggerDict[substr] = PlaceHolder(alogger)
791 else:
792 obj = self.loggerDict[substr]
793 if isinstance(obj, Logger):
794 rv = obj
795 else:
796 assert isinstance(obj, PlaceHolder)
797 obj.append(alogger)
798 i = string.rfind(name, ".", 0, i - 1)
799 if not rv:
800 rv = self.root
801 alogger.parent = rv
802
803 def _fixupChildren(self, ph, alogger):
804 """
805 Ensure that children of the placeholder ph are connected to the
806 specified logger.
807 """
808 for c in ph.loggers:
809 if string.find(c.parent.name, alogger.name) <> 0:
810 alogger.parent = c.parent
811 c.parent = alogger
812
813#---------------------------------------------------------------------------
814# Logger classes and functions
815#---------------------------------------------------------------------------
816
817class Logger(Filterer):
818 """
819 Instances of the Logger class represent a single logging channel. A
820 "logging channel" indicates an area of an application. Exactly how an
821 "area" is defined is up to the application developer. Since an
822 application can have any number of areas, logging channels are identified
823 by a unique string. Application areas can be nested (e.g. an area
824 of "input processing" might include sub-areas "read CSV files", "read
825 XLS files" and "read Gnumeric files"). To cater for this natural nesting,
826 channel names are organized into a namespace hierarchy where levels are
827 separated by periods, much like the Java or Python package namespace. So
828 in the instance given above, channel names might be "input" for the upper
829 level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
830 There is no arbitrary limit to the depth of nesting.
831 """
832 def __init__(self, name, level=NOTSET):
833 """
834 Initialize the logger with a name and an optional level.
835 """
836 Filterer.__init__(self)
837 self.name = name
838 self.level = level
839 self.parent = None
840 self.propagate = 1
841 self.handlers = []
842 self.disabled = 0
843
844 def setLevel(self, level):
845 """
846 Set the logging level of this logger.
847 """
848 self.level = level
849
850# def getRoot(self):
851# """
852# Get the root of the logger hierarchy.
853# """
854# return Logger.root
855
856 def debug(self, msg, *args, **kwargs):
857 """
858 Log 'msg % args' with severity 'DEBUG'.
859
860 To pass exception information, use the keyword argument exc_info with
861 a true value, e.g.
862
863 logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
864 """
865 if self.manager.disable >= DEBUG:
866 return
867 if DEBUG >= self.getEffectiveLevel():
Guido van Rossum0df64422003-03-02 20:47:29 +0000868 apply(self._log, (DEBUG, msg, args), kwargs)
Guido van Rossum57102f82002-11-13 16:15:58 +0000869
870 def info(self, msg, *args, **kwargs):
871 """
872 Log 'msg % args' with severity 'INFO'.
873
874 To pass exception information, use the keyword argument exc_info with
875 a true value, e.g.
876
877 logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
878 """
879 if self.manager.disable >= INFO:
880 return
881 if INFO >= self.getEffectiveLevel():
Guido van Rossum0df64422003-03-02 20:47:29 +0000882 apply(self._log, (INFO, msg, args), kwargs)
Guido van Rossum57102f82002-11-13 16:15:58 +0000883
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000884 def warning(self, msg, *args, **kwargs):
Guido van Rossum57102f82002-11-13 16:15:58 +0000885 """
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000886 Log 'msg % args' with severity 'WARNING'.
Guido van Rossum57102f82002-11-13 16:15:58 +0000887
888 To pass exception information, use the keyword argument exc_info with
889 a true value, e.g.
890
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000891 logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
Guido van Rossum57102f82002-11-13 16:15:58 +0000892 """
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000893 if self.manager.disable >= WARNING:
Guido van Rossum57102f82002-11-13 16:15:58 +0000894 return
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000895 if self.isEnabledFor(WARNING):
Guido van Rossum0df64422003-03-02 20:47:29 +0000896 apply(self._log, (WARNING, msg, args), kwargs)
Neal Norwitz6fa635d2003-02-18 14:20:07 +0000897
898 warn = warning
Guido van Rossum57102f82002-11-13 16:15:58 +0000899
900 def error(self, msg, *args, **kwargs):
901 """
902 Log 'msg % args' with severity 'ERROR'.
903
904 To pass exception information, use the keyword argument exc_info with
905 a true value, e.g.
906
907 logger.error("Houston, we have a %s", "major problem", exc_info=1)
908 """
909 if self.manager.disable >= ERROR:
910 return
911 if self.isEnabledFor(ERROR):
Guido van Rossum0df64422003-03-02 20:47:29 +0000912 apply(self._log, (ERROR, msg, args), kwargs)
Guido van Rossum57102f82002-11-13 16:15:58 +0000913
914 def exception(self, msg, *args):
915 """
916 Convenience method for logging an ERROR with exception information.
917 """
Guido van Rossum0df64422003-03-02 20:47:29 +0000918 apply(self.error, (msg,) + args, {'exc_info': 1})
Guido van Rossum57102f82002-11-13 16:15:58 +0000919
920 def critical(self, msg, *args, **kwargs):
921 """
922 Log 'msg % args' with severity 'CRITICAL'.
923
924 To pass exception information, use the keyword argument exc_info with
925 a true value, e.g.
926
927 logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
928 """
929 if self.manager.disable >= CRITICAL:
930 return
931 if CRITICAL >= self.getEffectiveLevel():
Guido van Rossum0df64422003-03-02 20:47:29 +0000932 apply(self._log, (CRITICAL, msg, args), kwargs)
Guido van Rossum57102f82002-11-13 16:15:58 +0000933
934 fatal = critical
935
936 def log(self, level, msg, *args, **kwargs):
937 """
938 Log 'msg % args' with the severity 'level'.
939
940 To pass exception information, use the keyword argument exc_info with
941 a true value, e.g.
942
943 logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
944 """
945 if self.manager.disable >= level:
946 return
947 if self.isEnabledFor(level):
Guido van Rossum0df64422003-03-02 20:47:29 +0000948 apply(self._log, (level, msg, args), kwargs)
Guido van Rossum57102f82002-11-13 16:15:58 +0000949
950 def findCaller(self):
951 """
952 Find the stack frame of the caller so that we can note the source
953 file name and line number.
954 """
Jeremy Hylton250684d2003-01-23 18:29:29 +0000955 f = sys._getframe(1)
956 while 1:
957 co = f.f_code
958 filename = os.path.normcase(co.co_filename)
959 if filename == _srcfile:
960 f = f.f_back
961 continue
962 return filename, f.f_lineno
Guido van Rossum57102f82002-11-13 16:15:58 +0000963
964 def makeRecord(self, name, level, fn, lno, msg, args, exc_info):
965 """
966 A factory method which can be overridden in subclasses to create
967 specialized LogRecords.
968 """
969 return LogRecord(name, level, fn, lno, msg, args, exc_info)
970
971 def _log(self, level, msg, args, exc_info=None):
972 """
973 Low-level logging routine which creates a LogRecord and then calls
974 all the handlers of this logger to handle the record.
975 """
Jeremy Hylton250684d2003-01-23 18:29:29 +0000976 if _srcfile:
977 fn, lno = self.findCaller()
Guido van Rossum57102f82002-11-13 16:15:58 +0000978 else:
979 fn, lno = "<unknown file>", 0
980 if exc_info:
981 exc_info = sys.exc_info()
982 record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info)
983 self.handle(record)
984
985 def handle(self, record):
986 """
987 Call the handlers for the specified record.
988
989 This method is used for unpickled records received from a socket, as
990 well as those created locally. Logger-level filtering is applied.
991 """
992 if (not self.disabled) and self.filter(record):
993 self.callHandlers(record)
994
995 def addHandler(self, hdlr):
996 """
997 Add the specified handler to this logger.
998 """
999 if not (hdlr in self.handlers):
1000 self.handlers.append(hdlr)
1001
1002 def removeHandler(self, hdlr):
1003 """
1004 Remove the specified handler from this logger.
1005 """
1006 if hdlr in self.handlers:
Neal Norwitz6fa635d2003-02-18 14:20:07 +00001007 #hdlr.close()
Guido van Rossum57102f82002-11-13 16:15:58 +00001008 self.handlers.remove(hdlr)
1009
1010 def callHandlers(self, record):
1011 """
1012 Pass a record to all relevant handlers.
1013
1014 Loop through all handlers for this logger and its parents in the
1015 logger hierarchy. If no handler was found, output a one-off error
1016 message to sys.stderr. Stop searching up the hierarchy whenever a
1017 logger with the "propagate" attribute set to zero is found - that
1018 will be the last logger whose handlers are called.
1019 """
1020 c = self
1021 found = 0
1022 while c:
1023 for hdlr in c.handlers:
1024 found = found + 1
1025 if record.levelno >= hdlr.level:
1026 hdlr.handle(record)
1027 if not c.propagate:
1028 c = None #break out
1029 else:
1030 c = c.parent
1031 if (found == 0) and not self.manager.emittedNoHandlerWarning:
1032 sys.stderr.write("No handlers could be found for logger"
1033 " \"%s\"\n" % self.name)
1034 self.manager.emittedNoHandlerWarning = 1
1035
1036 def getEffectiveLevel(self):
1037 """
1038 Get the effective level for this logger.
1039
1040 Loop through this logger and its parents in the logger hierarchy,
1041 looking for a non-zero logging level. Return the first one found.
1042 """
1043 logger = self
1044 while logger:
1045 if logger.level:
1046 return logger.level
1047 logger = logger.parent
1048 return NOTSET
1049
1050 def isEnabledFor(self, level):
1051 """
1052 Is this logger enabled for level 'level'?
1053 """
1054 if self.manager.disable >= level:
1055 return 0
1056 return level >= self.getEffectiveLevel()
1057
1058class RootLogger(Logger):
1059 """
1060 A root logger is not that different to any other logger, except that
1061 it must have a logging level and there is only one instance of it in
1062 the hierarchy.
1063 """
1064 def __init__(self, level):
1065 """
1066 Initialize the logger with the name "root".
1067 """
1068 Logger.__init__(self, "root", level)
1069
1070_loggerClass = Logger
1071
Neal Norwitz6fa635d2003-02-18 14:20:07 +00001072root = RootLogger(WARNING)
Guido van Rossum57102f82002-11-13 16:15:58 +00001073Logger.root = root
1074Logger.manager = Manager(Logger.root)
1075
1076#---------------------------------------------------------------------------
1077# Configuration classes and functions
1078#---------------------------------------------------------------------------
1079
1080BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s"
1081
1082def basicConfig():
1083 """
1084 Do basic configuration for the logging system by creating a
1085 StreamHandler with a default Formatter and adding it to the
1086 root logger.
1087 """
1088 if len(root.handlers) == 0:
1089 hdlr = StreamHandler()
1090 fmt = Formatter(BASIC_FORMAT)
1091 hdlr.setFormatter(fmt)
1092 root.addHandler(hdlr)
1093
1094#---------------------------------------------------------------------------
1095# Utility functions at module level.
1096# Basically delegate everything to the root logger.
1097#---------------------------------------------------------------------------
1098
1099def getLogger(name=None):
1100 """
1101 Return a logger with the specified name, creating it if necessary.
1102
1103 If no name is specified, return the root logger.
1104 """
1105 if name:
1106 return Logger.manager.getLogger(name)
1107 else:
1108 return root
1109
1110#def getRootLogger():
1111# """
1112# Return the root logger.
1113#
1114# Note that getLogger('') now does the same thing, so this function is
1115# deprecated and may disappear in the future.
1116# """
1117# return root
1118
1119def critical(msg, *args, **kwargs):
1120 """
1121 Log a message with severity 'CRITICAL' on the root logger.
1122 """
1123 if len(root.handlers) == 0:
1124 basicConfig()
Guido van Rossum0df64422003-03-02 20:47:29 +00001125 apply(root.critical, (msg,)+args, kwargs)
Guido van Rossum57102f82002-11-13 16:15:58 +00001126
1127fatal = critical
1128
1129def error(msg, *args, **kwargs):
1130 """
1131 Log a message with severity 'ERROR' on the root logger.
1132 """
1133 if len(root.handlers) == 0:
1134 basicConfig()
Guido van Rossum0df64422003-03-02 20:47:29 +00001135 apply(root.error, (msg,)+args, kwargs)
Guido van Rossum57102f82002-11-13 16:15:58 +00001136
1137def exception(msg, *args):
1138 """
1139 Log a message with severity 'ERROR' on the root logger,
1140 with exception information.
1141 """
Guido van Rossum0df64422003-03-02 20:47:29 +00001142 apply(error, (msg,)+args, {'exc_info': 1})
Guido van Rossum57102f82002-11-13 16:15:58 +00001143
Neal Norwitz6fa635d2003-02-18 14:20:07 +00001144def warning(msg, *args, **kwargs):
Guido van Rossum57102f82002-11-13 16:15:58 +00001145 """
Neal Norwitz6fa635d2003-02-18 14:20:07 +00001146 Log a message with severity 'WARNING' on the root logger.
Guido van Rossum57102f82002-11-13 16:15:58 +00001147 """
1148 if len(root.handlers) == 0:
1149 basicConfig()
Guido van Rossum0df64422003-03-02 20:47:29 +00001150 apply(root.warning, (msg,)+args, kwargs)
Neal Norwitz6fa635d2003-02-18 14:20:07 +00001151
1152warn = warning
Guido van Rossum57102f82002-11-13 16:15:58 +00001153
1154def info(msg, *args, **kwargs):
1155 """
1156 Log a message with severity 'INFO' on the root logger.
1157 """
1158 if len(root.handlers) == 0:
1159 basicConfig()
Guido van Rossum0df64422003-03-02 20:47:29 +00001160 apply(root.info, (msg,)+args, kwargs)
Guido van Rossum57102f82002-11-13 16:15:58 +00001161
1162def debug(msg, *args, **kwargs):
1163 """
1164 Log a message with severity 'DEBUG' on the root logger.
1165 """
1166 if len(root.handlers) == 0:
1167 basicConfig()
Guido van Rossum0df64422003-03-02 20:47:29 +00001168 apply(root.debug, (msg,)+args, kwargs)
Guido van Rossum57102f82002-11-13 16:15:58 +00001169
1170def disable(level):
1171 """
1172 Disable all logging calls less severe than 'level'.
1173 """
1174 root.manager.disable = level
1175
1176def shutdown():
1177 """
1178 Perform any cleanup actions in the logging system (e.g. flushing
1179 buffers).
1180
1181 Should be called at application exit.
1182 """
1183 for h in _handlers.keys():
1184 h.flush()
1185 h.close()