~ubuntu-branches/ubuntu/raring/kiwi/raring

« back to all changes in this revision

Viewing changes to kiwi/log.py

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-01-30 09:52:28 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20070130095228-n0mkqlt82e74twqc
Tags: 1.9.12-0ubuntu1
* New upstream release.
* debian/patches/03_epyrun_use_local_modules.patch:
  - updated.
* debian/control:
  - moved python-support from Build-Depends to Build-Depends-Indep.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
19
19
# USA
20
20
#
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>
23
22
#
24
23
 
 
24
"""
 
25
Extension to the logging module
 
26
 
 
27
This module defines a couple of extensions to the logging module included
 
28
in the python standard distribution.
 
29
 
 
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.
 
35
 
 
36
The syntax for the string which KIWI_LOG points to is the following::
 
37
 
 
38
    domain ':' level [, domain ':', level]
 
39
 
 
40
domain can contain wildcards such as * and ?
 
41
level is an integer 1-5 which defines the minimal level:
 
42
 
 
43
  - B{5}: DEBUG
 
44
  - B{4}: INFO
 
45
  - B{3}: WARNING
 
46
  - B{2}: ERROR
 
47
  - B{1}: CRITICAL
 
48
 
 
49
Examples::
 
50
 
 
51
    KIWI_LOG="stoq*:5"
 
52
 
 
53
will print all the messages in a domain starting with stoq with DEBUG or higher::
 
54
 
 
55
    KIWI_LOG="kiwi*:4,stoq.*:5"
 
56
 
 
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
 
59
 
 
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.
 
62
"""
 
63
 
25
64
import fnmatch
26
65
import logging
27
66
import os
28
 
import sys
 
67
 
 
68
# Globals
 
69
 
 
70
_console = None
 
71
_filter = None
29
72
 
30
73
class LogError(Exception):
31
74
    pass
32
75
 
33
 
class Formatter(logging.Formatter):
34
 
    def format(self, record):
35
 
        # 1: format
36
 
        # 2-6: logging module
37
 
        # 7: log (log.info/log.warn etc)
38
 
        # 8: callsite
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)
43
 
 
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.
50
 
 
51
 
        logging default levels table:
52
 
 
53
 
        Level
54
 
          - logging.NOTSET
55
 
          - logging.DEBUG
56
 
          - logging.INFO
57
 
          - logging.WARNING
58
 
          - logging.ERROR
59
 
          - logging.CRITICAL
60
 
        """
61
 
        if not name:
62
 
            name = Logger.log_name
63
 
        logging.Logger.__init__(self, name, get_log_level(name))
64
 
 
65
 
        stream_handler = logging.StreamHandler(sys.stdout)
66
 
 
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,
75
 
                                              datefmt='%T'))
76
 
        self.addHandler(stream_handler)
77
 
 
 
76
class Logger(object):
 
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)
 
81
 
 
82
class _Logger(logging.Logger):
78
83
    def __call__(self, message, *args, **kwargs):
79
84
        self.info(message, *args, **kwargs)
80
85
 
81
 
_log_levels = {}
82
 
_default_level = logging.WARNING
 
86
logging.setLoggerClass(_Logger)
 
87
 
 
88
class ReversedGlobalFilter(logging.Filter):
 
89
    """
 
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
 
93
    """
 
94
    def __init__(self):
 
95
        logging.Filter.__init__(self)
 
96
        self.filters = []
 
97
 
 
98
    def add_filter(self, f, level=logging.DEBUG):
 
99
        self.filters.append((f, level))
 
100
 
 
101
    def filter(self, record):
 
102
        for f, level in self.filters:
 
103
            if (record.levelno >= level and
 
104
                fnmatch.fnmatch(record.name, f)):
 
105
                return True
 
106
 
 
107
        return False
 
108
 
 
109
def set_log_file(filename, mask=None):
 
110
    """
 
111
    @param filename:
 
112
    @param mask: optional
 
113
    """
 
114
    file_handler = logging.FileHandler(filename, 'w')
 
115
    file_handler.setFormatter(logging.Formatter(
 
116
        '%(asctime)s %(name)-18s %(levelname)-8s %(message)s',
 
117
        datefmt='%F %T'))
 
118
    root = logging.getLogger()
 
119
    root.addHandler(file_handler)
 
120
 
 
121
    if mask:
 
122
        file_filter = ReversedGlobalFilter()
 
123
        file_filter.add_filter(mask, logging.DEBUG)
 
124
        file_handler.addFilter(file_filter)
83
125
 
84
126
def set_log_level(name, level):
85
127
    """
86
128
    @param name: logging category
87
129
    @param level: level
88
130
    """
89
 
    global _log_levels
90
 
    _log_levels[name] = level
91
 
 
92
 
def get_log_level(name):
93
 
    """
94
 
    @param name: logging category
95
 
    @returns: the level
96
 
    """
97
 
    global _log_levels, _default_level
98
 
 
99
 
    for category in _log_levels:
100
 
        if fnmatch.fnmatch(name, category):
101
 
            level = _log_levels[category]
102
 
            break
103
 
    else:
104
 
        level = _default_level
105
 
    return level
106
 
 
107
 
def _read_log_level():
108
 
    global _default_level
109
 
 
 
131
    global _filter
 
132
    _filter.add_filter(name, level)
 
133
 
 
134
def _read_log_levels(console_filter):
110
135
    log_levels = {}
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
130
155
 
131
156
        level = 50 - (level * 10)
132
157
 
133
 
        if name == '*':
134
 
            _default_level = level
135
 
            continue
136
 
        log_levels[name] = level
137
 
 
138
 
    return log_levels
139
 
 
140
 
_log_levels = _read_log_level()
 
158
        console_filter.add_filter(name, level)
 
159
 
 
160
def _create_console():
 
161
    global _filter, _console
 
162
 
 
163
    console = logging.StreamHandler()
 
164
    console.setFormatter(logging.Formatter(
 
165
        "%(asctime)s %(message)s", datefmt='%T'))
 
166
    root = logging.getLogger()
 
167
    root.addHandler(console)
 
168
    root.setLevel(logging.DEBUG)
 
169
 
 
170
    console_filter = ReversedGlobalFilter()
 
171
    # Always display warnings or higher on the console
 
172
    console_filter.add_filter('*', logging.WARNING)
 
173
    console.addFilter(console_filter)
 
174
 
 
175
    _read_log_levels(console_filter)
 
176
 
 
177
    # Set globals
 
178
    _filter = console_filter
 
179
    _console = console
 
180
 
 
181
_create_console()
141
182
 
142
183
kiwi_log = Logger('kiwi')