18
18
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21
# Author(s): Adriano Monteiro <adriano@globalret.com.br>
22
# Johan Dahlin <jdahlin@async.com.br>
21
# Author(s): Johan Dahlin <jdahlin@async.com.br>
25
Extension to the logging module
27
This module defines a couple of extensions to the logging module included
28
in the python standard distribution.
30
It creates an additional logging handler that print log records on the
31
standard output. This handler is only showing records which has a level
32
set to logging.WARNING or higher by default.
33
The messages printed by this handler can be modified by using the environment
34
variable called KIWI_LOG.
36
The syntax for the string which KIWI_LOG points to is the following::
38
domain ':' level [, domain ':', level]
40
domain can contain wildcards such as * and ?
41
level is an integer 1-5 which defines the minimal level:
53
will print all the messages in a domain starting with stoq with DEBUG or higher::
55
KIWI_LOG="kiwi*:4,stoq.*:5"
57
will print all the messages with INFO or higher in all domains starting with kiwi,
58
and all the messages in the stoq.* domains which are DEBUG or higher
60
Inspiration for the syntax is taken from the U{debugging facilities<http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/gstreamer-GstInfo.html#id2857358>} of the
61
U{GStreamer<http://www.gstreamer.net>} multimedia framework.
30
73
class LogError(Exception):
33
class Formatter(logging.Formatter):
34
def format(self, record):
37
# 7: log (log.info/log.warn etc)
39
frame = sys._getframe(8)
40
filename = os.path.basename(frame.f_code.co_filename)
41
record.msg = '%s:%d %s' % (filename, frame.f_lineno, record.msg)
42
return logging.Formatter.format(self, record)
44
class Logger(logging.Logger):
45
log_domain = 'default'
46
def __init__(self, name=None, level=logging.NOTSET):
47
"""Initializes Log module, creating log handler and defining log
48
level. level attribute is not mandatory. It defines from which level
49
messages should be logged. Logs with lower level are ignored.
51
logging default levels table:
62
name = Logger.log_name
63
logging.Logger.__init__(self, name, get_log_level(name))
65
stream_handler = logging.StreamHandler(sys.stdout)
67
# Formater class define a format for the log messages been
68
# logged with this handler
69
# The following format string
70
# ("%(asctime)s (%(levelname)s) - %(message)s") will result
71
# in a log message like this:
72
# 2005-09-07 18:15:12,636 (WARNING) - (message!)
73
format_string = ("%(asctime)s %(message)s")
74
stream_handler.setFormatter(Formatter(format_string,
76
self.addHandler(stream_handler)
77
# Backwards compatibility, we should probably replace the callsites
78
# with import logging; logging.getLogger(name)
79
def __new__(self, name):
80
return logging.getLogger(name)
82
class _Logger(logging.Logger):
78
83
def __call__(self, message, *args, **kwargs):
79
84
self.info(message, *args, **kwargs)
82
_default_level = logging.WARNING
86
logging.setLoggerClass(_Logger)
88
class ReversedGlobalFilter(logging.Filter):
90
It's like a reversed filter, the default behavior
91
is to not show the message, you need to add custom filters for all
92
the records you wish to see
95
logging.Filter.__init__(self)
98
def add_filter(self, f, level=logging.DEBUG):
99
self.filters.append((f, level))
101
def filter(self, record):
102
for f, level in self.filters:
103
if (record.levelno >= level and
104
fnmatch.fnmatch(record.name, f)):
109
def set_log_file(filename, mask=None):
112
@param mask: optional
114
file_handler = logging.FileHandler(filename, 'w')
115
file_handler.setFormatter(logging.Formatter(
116
'%(asctime)s %(name)-18s %(levelname)-8s %(message)s',
118
root = logging.getLogger()
119
root.addHandler(file_handler)
122
file_filter = ReversedGlobalFilter()
123
file_filter.add_filter(mask, logging.DEBUG)
124
file_handler.addFilter(file_filter)
84
126
def set_log_level(name, level):
86
128
@param name: logging category
87
129
@param level: level
90
_log_levels[name] = level
92
def get_log_level(name):
94
@param name: logging category
97
global _log_levels, _default_level
99
for category in _log_levels:
100
if fnmatch.fnmatch(name, category):
101
level = _log_levels[category]
104
level = _default_level
107
def _read_log_level():
108
global _default_level
132
_filter.add_filter(name, level)
134
def _read_log_levels(console_filter):
111
# bootstrap issue, cannot depend on environ
136
# bootstrap issue, cannot depend on kiwi.environ
112
137
log_level = os.environ.get('KIWI_LOG')
113
138
if not log_level:
114
139
return log_levels