1 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 ''' Utility functions and objects for logging. 6 ''' 7 8 import logging 9 import sys 10 11 class StdoutStderrHandler(logging.Handler): 12 ''' Subclass of logging.Handler which outputs to either stdout or stderr 13 based on a threshold level. 14 ''' 15 16 def __init__(self, threshold=logging.WARNING, err=sys.stderr, out=sys.stdout): 17 ''' Args: 18 threshold: below this logging level messages are sent to stdout, 19 otherwise they are sent to stderr 20 err: a stream object that error messages are sent to, defaults to 21 sys.stderr 22 out: a stream object that non-error messages are sent to, defaults to 23 sys.stdout 24 ''' 25 logging.Handler.__init__(self) 26 self._err = logging.StreamHandler(err) 27 self._out = logging.StreamHandler(out) 28 self._threshold = threshold 29 self._last_was_err = False 30 31 def setLevel(self, lvl): 32 logging.Handler.setLevel(self, lvl) 33 self._err.setLevel(lvl) 34 self._out.setLevel(lvl) 35 36 def setFormatter(self, formatter): 37 logging.Handler.setFormatter(self, formatter) 38 self._err.setFormatter(formatter) 39 self._out.setFormatter(formatter) 40 41 def emit(self, record): 42 if record.levelno < self._threshold: 43 self._out.emit(record) 44 self._last_was_err = False 45 else: 46 self._err.emit(record) 47 self._last_was_err = False 48 49 def flush(self): 50 # preserve order on the flushing, the stalest stream gets flushed first 51 if self._last_was_err: 52 self._out.flush() 53 self._err.flush() 54 else: 55 self._err.flush() 56 self._out.flush() 57 58 59 FORMAT = "%(asctime)s %(filename)s [%(levelname)s] %(message)s" 60 DATEFMT = "%H:%M:%S" 61 62 def config_root(level=logging.INFO, threshold=logging.WARNING, format=FORMAT, 63 datefmt=DATEFMT): 64 ''' Configure the root logger to use a StdoutStderrHandler and some default 65 formatting. 66 Args: 67 level: messages below this level are ignored 68 threshold: below this logging level messages are sent to stdout, 69 otherwise they are sent to stderr 70 format: format for log messages, see logger.Format 71 datefmt: format for date in log messages 72 73 ''' 74 # to set the handler of the root logging object, we need to do setup 75 # manually rather than using basicConfig 76 root = logging.getLogger() 77 root.setLevel(level) 78 formatter = logging.Formatter(format, datefmt) 79 handler = StdoutStderrHandler(threshold=threshold) 80 handler.setLevel(level) 81 handler.setFormatter(formatter) 82 root.addHandler(handler) 83