1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
# 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)
|