chromium/tools/python/google/logging_utils.py

# Copyright 2011 The Chromium Authors
# 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)