blob: cf9f3fa8e1606d9f7247006f1bc80b3fd614eaca [file] [log] [blame]
#!/bin/env python
# Copyright 2008, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# logging_utils.py
''' 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)