~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/trace.py

  • Committer: Robert Collins
  • Date: 2005-11-28 05:13:41 UTC
  • mfrom: (1185.33.54 merge-recovered)
  • Revision ID: robertc@robertcollins.net-20051128051341-059936f2f29a12c8
Merge from Martin. Adjust check to work with HTTP again.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# This program is free software; you can redistribute it and/or modify
2
 
# it under the terms of the GNU General Public License as published by
3
 
# the Free Software Foundation; either version 2 of the License, or
4
 
# (at your option) any later version.
5
 
 
6
 
# This program is distributed in the hope that it will be useful,
7
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
8
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9
 
# GNU General Public License for more details.
10
 
 
11
 
# You should have received a copy of the GNU General Public License
12
 
# along with this program; if not, write to the Free Software
13
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
14
 
 
 
1
# Copyright (C) 2005, Canonical Ltd
15
2
 
16
3
"""Messages and logging for bazaar-ng.
17
4
 
27
14
those two places to another location.
28
15
 
29
16
~/.bzr.log gets all messages, and full tracebacks for uncaught exceptions.
 
17
This trace file is always in UTF-8, regardless of the user's default encoding,
 
18
so that we can always rely on writing any message.
30
19
 
31
20
Output to stderr depends on the mode chosen by the user.  By default, messages
32
21
of info and above are sent out, which results in progress messages such as the
43
32
form.
44
33
"""
45
34
 
46
 
 
47
35
# TODO: in debug mode, stderr should get full tracebacks and also
48
36
# debug messages.  (Is this really needed?)
49
37
 
50
 
# TODO: When running the test suites, we should add an additional
51
 
# logger that sends messages into the test log file.
52
 
 
53
38
# FIXME: Unfortunately it turns out that python's logging module
54
39
# is quite expensive, even when the message is not printed by any handlers.
55
40
# We should perhaps change back to just simply doing it here.
65
50
 
66
51
_file_handler = None
67
52
_stderr_handler = None
 
53
_stderr_quiet = False
 
54
_trace_file = None
 
55
_bzr_log_file = None
68
56
 
69
57
class QuietFormatter(logging.Formatter):
70
58
    """Formatter that supresses the details of errors.
85
73
            s += '\n' + format_exception_short(record.exc_info)
86
74
        return s
87
75
        
88
 
 
89
 
 
90
 
 
91
 
################
92
76
# configure convenient aliases for output routines
93
77
 
94
78
_bzr_logger = logging.getLogger('bzr')
97
81
warning =   _bzr_logger.warning
98
82
log_error = _bzr_logger.error
99
83
error =     _bzr_logger.error
100
 
mutter =    _bzr_logger.debug
101
 
debug =     _bzr_logger.debug
 
84
 
 
85
 
 
86
def mutter(fmt, *args):
 
87
    if _trace_file is None:
 
88
        return
 
89
    if hasattr(_trace_file, 'closed') and _trace_file.closed:
 
90
        return
 
91
    if len(args) > 0:
 
92
        out = fmt % args
 
93
    else:
 
94
        out = fmt
 
95
    out += '\n'
 
96
    if isinstance(out, unicode):
 
97
        out = out.encode('utf-8')
 
98
    _trace_file.write(out)
 
99
debug = mutter
102
100
 
103
101
 
104
102
def _rollover_trace_maybe(trace_fname):
118
116
    # Messages are always written to here, so that we have some
119
117
    # information if something goes wrong.  In a future version this
120
118
    # file will be removed on successful completion.
121
 
    global _file_handler
 
119
    global _file_handler, _bzr_log_file
122
120
    import stat, codecs
123
121
 
124
122
    trace_fname = os.path.join(os.path.expanduser(tracefilename))
126
124
    try:
127
125
        LINE_BUFFERED = 1
128
126
        tf = codecs.open(trace_fname, 'at', 'utf8', buffering=LINE_BUFFERED)
129
 
 
130
 
        if os.fstat(tf.fileno())[stat.ST_SIZE] == 0:
 
127
        _bzr_log_file = tf
 
128
        if tf.tell() == 0:
131
129
            tf.write("\nthis is a debug log for diagnosing/reporting problems in bzr\n")
132
130
            tf.write("you can delete or truncate this file, or include sections in\n")
133
131
            tf.write("bug reports to bazaar-ng@lists.canonical.com\n\n")
134
 
        
135
132
        _file_handler = logging.StreamHandler(tf)
136
133
        fmt = r'[%(process)5d] %(asctime)s.%(msecs)03d %(levelname)s: %(message)s'
137
134
        datefmt = r'%a %H:%M:%S'
143
140
 
144
141
 
145
142
def log_startup(argv):
146
 
    debug('bzr %s invoked on python %s (%s)',
 
143
    debug('\n\nbzr %s invoked on python %s (%s)',
147
144
          bzrlib.__version__,
148
145
          '.'.join(map(str, sys.version_info)),
149
146
          sys.platform)
157
154
    The exception string representation is used as the error
158
155
    summary, unless msg is given.
159
156
    """
160
 
    exc_str = format_exception_short(sys.exc_info())
161
157
    if msg:
162
 
        _bzr_logger.exception(msg)
163
 
    _bzr_logger.error(exc_str)
 
158
        error(msg)
 
159
    else:
 
160
        exc_str = format_exception_short(sys.exc_info())
 
161
        error(exc_str)
 
162
    log_exception_quietly()
164
163
 
165
164
 
166
165
def log_exception_quietly():
176
175
 
177
176
def enable_default_logging():
178
177
    """Configure default logging to stderr and .bzr.log"""
179
 
    global _stderr_handler, _file_handler
180
 
 
 
178
    # FIXME: if this is run twice, things get confused
 
179
    global _stderr_handler, _file_handler, _trace_file, _bzr_log_file
181
180
    _stderr_handler = logging.StreamHandler()
182
181
    _stderr_handler.setFormatter(QuietFormatter())
183
182
    logging.getLogger('').addHandler(_stderr_handler)
184
 
 
185
 
    if os.environ.get('BZR_DEBUG'):
186
 
        level = logging.DEBUG
187
 
    else:
188
 
        level = logging.INFO
189
 
 
190
183
    _stderr_handler.setLevel(logging.INFO)
191
 
 
192
184
    if not _file_handler:
193
185
        open_tracefile()
194
 
 
 
186
    _trace_file = _bzr_log_file
195
187
    if _file_handler:
196
 
        _file_handler.setLevel(level)
197
 
 
198
 
    _bzr_logger.setLevel(level) 
 
188
        _file_handler.setLevel(logging.DEBUG)
 
189
    _bzr_logger.setLevel(logging.DEBUG) 
 
190
 
 
191
 
 
192
 
 
193
def be_quiet(quiet=True):
 
194
    global _stderr_handler, _stderr_quiet
 
195
    
 
196
    _stderr_quiet = quiet
 
197
    if quiet:
 
198
        _stderr_handler.setLevel(logging.WARNING)
 
199
    else:
 
200
        _stderr_handler.setLevel(logging.INFO)
 
201
 
 
202
 
 
203
def is_quiet():
 
204
    global _stderr_quiet
 
205
    return _stderr_quiet
 
206
 
199
207
 
200
208
def disable_default_logging():
201
209
    """Turn off default log handlers.
208
216
    l.removeHandler(_stderr_handler)
209
217
    if _file_handler:
210
218
        l.removeHandler(_file_handler)
 
219
    _trace_file = None
211
220
 
212
221
 
213
222
def enable_test_log(to_file):
214
223
    """Redirect logging to a temporary file for a test"""
215
224
    disable_default_logging()
216
 
    global _test_log_hdlr
 
225
    global _test_log_hdlr, _trace_file
217
226
    hdlr = logging.StreamHandler(to_file)
218
227
    hdlr.setLevel(logging.DEBUG)
219
228
    hdlr.setFormatter(logging.Formatter('%(levelname)8s  %(message)s'))
220
 
    logging.getLogger('').addHandler(hdlr)
221
 
    logging.getLogger('').setLevel(logging.DEBUG)
 
229
    _bzr_logger.addHandler(hdlr)
 
230
    _bzr_logger.setLevel(logging.DEBUG)
222
231
    _test_log_hdlr = hdlr
 
232
    _trace_file = to_file
223
233
 
224
234
 
225
235
def disable_test_log():
226
 
    logging.getLogger('').removeHandler(_test_log_hdlr)
 
236
    _bzr_logger.removeHandler(_test_log_hdlr)
 
237
    _trace_file = None
227
238
    enable_default_logging()
228
239
 
229
240