|  | # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
|  | # Use of this source code is governed by a BSD-style license that can be | 
|  | # found in the LICENSE file. | 
|  |  | 
|  | ''' Utility functions and objects for logging. | 
|  | ''' | 
|  |  | 
|  | import logging | 
|  | import sys | 
|  |  | 
|  | class StdoutStderrHandler(logging.Handler): | 
|  | ''' Subclass of logging.Handler which outputs to either stdout or stderr | 
|  | based on a threshold level. | 
|  | ''' | 
|  |  | 
|  | def __init__(self, threshold=logging.WARNING, err=sys.stderr, out=sys.stdout): | 
|  | ''' Args: | 
|  | threshold: below this logging level messages are sent to stdout, | 
|  | otherwise they are sent to stderr | 
|  | err: a stream object that error messages are sent to, defaults to | 
|  | sys.stderr | 
|  | out: a stream object that non-error messages are sent to, defaults to | 
|  | sys.stdout | 
|  | ''' | 
|  | logging.Handler.__init__(self) | 
|  | self._err = logging.StreamHandler(err) | 
|  | self._out = logging.StreamHandler(out) | 
|  | self._threshold = threshold | 
|  | self._last_was_err = False | 
|  |  | 
|  | def setLevel(self, lvl): | 
|  | logging.Handler.setLevel(self, lvl) | 
|  | self._err.setLevel(lvl) | 
|  | self._out.setLevel(lvl) | 
|  |  | 
|  | def setFormatter(self, formatter): | 
|  | logging.Handler.setFormatter(self, formatter) | 
|  | self._err.setFormatter(formatter) | 
|  | self._out.setFormatter(formatter) | 
|  |  | 
|  | def emit(self, record): | 
|  | if record.levelno < self._threshold: | 
|  | self._out.emit(record) | 
|  | self._last_was_err = False | 
|  | else: | 
|  | self._err.emit(record) | 
|  | self._last_was_err = False | 
|  |  | 
|  | def flush(self): | 
|  | # preserve order on the flushing, the stalest stream gets flushed first | 
|  | if self._last_was_err: | 
|  | self._out.flush() | 
|  | self._err.flush() | 
|  | else: | 
|  | self._err.flush() | 
|  | self._out.flush() | 
|  |  | 
|  |  | 
|  | FORMAT = "%(asctime)s %(filename)s [%(levelname)s] %(message)s" | 
|  | DATEFMT = "%H:%M:%S" | 
|  |  | 
|  | def config_root(level=logging.INFO, threshold=logging.WARNING, format=FORMAT, | 
|  | datefmt=DATEFMT): | 
|  | ''' Configure the root logger to use a StdoutStderrHandler and some default | 
|  | formatting. | 
|  | Args: | 
|  | level: messages below this level are ignored | 
|  | threshold: below this logging level messages are sent to stdout, | 
|  | otherwise they are sent to stderr | 
|  | format: format for log messages, see logger.Format | 
|  | datefmt: format for date in log messages | 
|  |  | 
|  | ''' | 
|  | # to set the handler of the root logging object, we need to do setup | 
|  | # manually rather than using basicConfig | 
|  | root = logging.getLogger() | 
|  | root.setLevel(level) | 
|  | formatter = logging.Formatter(format, datefmt) | 
|  | handler = StdoutStderrHandler(threshold=threshold) | 
|  | handler.setLevel(level) | 
|  | handler.setFormatter(formatter) | 
|  | root.addHandler(handler) |