/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to brzlib/trace.py

  • Committer: Jelmer Vernooij
  • Date: 2017-05-21 18:06:19 UTC
  • mto: This revision was merged to the branch mainline in revision 6623.
  • Revision ID: jelmer@jelmer.uk-20170521180619-5qoo0470asgdnljt
Fix more tests (all?)

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
Messages are classified by severity levels: critical, error, warning, info,
24
24
and debug.
25
25
 
26
 
They can be sent to two places: to stderr, and to ~/.bzr.log.  For purposes
 
26
They can be sent to two places: to stderr, and to ~/.brz.log.  For purposes
27
27
such as running the test suite, they can also be redirected away from both of
28
28
those two places to another location.
29
29
 
30
 
~/.bzr.log gets all messages, and full tracebacks for uncaught exceptions.
 
30
~/.brz.log gets all messages, and full tracebacks for uncaught exceptions.
31
31
This trace file is always in UTF-8, regardless of the user's default encoding,
32
32
so that we can always rely on writing any message.
33
33
 
92
92
# than push/pop_log_file.
93
93
_trace_file = None
94
94
 
95
 
# Absolute path for ~/.bzr.log.  Not changed even if the log/trace output is
 
95
# Absolute path for ~/.brz.log.  Not changed even if the log/trace output is
96
96
# redirected elsewhere.  Used to show the location in --version.
97
 
_bzr_log_filename = None
 
97
_brz_log_filename = None
98
98
 
99
99
# The time the first message was written to the trace file, so that we can
100
100
# show relative times since startup.
101
 
_bzr_log_start_time = brzlib._start_time
 
101
_brz_log_start_time = brzlib._start_time
102
102
 
103
103
 
104
104
# held in a global for quick reference
105
 
_bzr_logger = logging.getLogger('bzr')
 
105
_brz_logger = logging.getLogger('brz')
106
106
 
107
107
 
108
108
def note(*args, **kwargs):
116
116
    # framework is whack; we should probably have a logging Handler that
117
117
    # deals with terminal output if needed.
118
118
    ui.ui_factory.clear_term()
119
 
    _bzr_logger.info(*args, **kwargs)
 
119
    _brz_logger.info(*args, **kwargs)
120
120
 
121
121
 
122
122
def warning(*args, **kwargs):
123
123
    ui.ui_factory.clear_term()
124
 
    _bzr_logger.warning(*args, **kwargs)
 
124
    _brz_logger.warning(*args, **kwargs)
125
125
 
126
126
 
127
127
def show_error(*args, **kwargs):
129
129
 
130
130
    Don't use this for exceptions, use report_exception instead.
131
131
    """
132
 
    _bzr_logger.error(*args, **kwargs)
 
132
    _brz_logger.error(*args, **kwargs)
133
133
 
134
134
 
135
135
def mutter(fmt, *args):
156
156
    else:
157
157
        out = fmt
158
158
    now = time.time()
159
 
    timestamp = '%0.3f  ' % (now - _bzr_log_start_time,)
 
159
    timestamp = '%0.3f  ' % (now - _brz_log_start_time,)
160
160
    out = timestamp + out + '\n'
161
161
    _trace_file.write(out)
162
162
    # there's no explicit flushing; the file is typically line buffered.
193
193
        return
194
194
 
195
195
 
196
 
def _get_bzr_log_filename():
197
 
    bzr_log = osutils.path_from_environ('BRZ_LOG')
198
 
    if bzr_log:
199
 
        return bzr_log
 
196
def _get_brz_log_filename():
 
197
    brz_log = osutils.path_from_environ('BRZ_LOG')
 
198
    if brz_log:
 
199
        return brz_log
200
200
    home = osutils.path_from_environ('BRZ_HOME')
201
201
    if home is None:
202
202
        # GZ 2012-02-01: Logging to the home dir is bad, but XDG is unclear
203
203
        #                over what would be better. On windows, bug 240550
204
204
        #                suggests LOCALAPPDATA be used instead.
205
205
        home = osutils._get_home_dir()
206
 
    return os.path.join(home, '.bzr.log')
207
 
 
208
 
 
209
 
def _open_bzr_log():
210
 
    """Open the .bzr.log trace file.
 
206
    return os.path.join(home, '.brz.log')
 
207
 
 
208
 
 
209
def _open_brz_log():
 
210
    """Open the .brz.log trace file.
211
211
 
212
212
    If the log is more than a particular length, the old file is renamed to
213
 
    .bzr.log.old and a new file is started.  Otherwise, we append to the
 
213
    .brz.log.old and a new file is started.  Otherwise, we append to the
214
214
    existing file.
215
215
 
216
 
    This sets the global _bzr_log_filename.
 
216
    This sets the global _brz_log_filename.
217
217
    """
218
 
    global _bzr_log_filename
 
218
    global _brz_log_filename
219
219
 
220
220
    def _open_or_create_log_file(filename):
221
221
        """Open existing log file, or create with ownership and permissions
240
240
            else:
241
241
                osutils.copy_ownership_from_path(filename)
242
242
                break
243
 
        return os.fdopen(fd, 'at', 0) # unbuffered
244
 
 
245
 
 
246
 
    _bzr_log_filename = _get_bzr_log_filename()
247
 
    _rollover_trace_maybe(_bzr_log_filename)
 
243
        return os.fdopen(fd, 'at', 0)  # unbuffered
 
244
 
 
245
    _brz_log_filename = _get_brz_log_filename()
 
246
    _rollover_trace_maybe(_brz_log_filename)
248
247
    try:
249
 
        bzr_log_file = _open_or_create_log_file(_bzr_log_filename)
250
 
        bzr_log_file.write('\n')
251
 
        if bzr_log_file.tell() <= 2:
252
 
            bzr_log_file.write("this is a debug log for diagnosing/reporting problems in bzr\n")
253
 
            bzr_log_file.write("you can delete or truncate this file, or include sections in\n")
254
 
            bzr_log_file.write("bug reports to https://bugs.launchpad.net/bzr/+filebug\n\n")
 
248
        brz_log_file = _open_or_create_log_file(_brz_log_filename)
 
249
        brz_log_file.write('\n')
 
250
        if brz_log_file.tell() <= 2:
 
251
            brz_log_file.write("this is a debug log for diagnosing/reporting problems in brz\n")
 
252
            brz_log_file.write("you can delete or truncate this file, or include sections in\n")
 
253
            brz_log_file.write("bug reports to https://bugs.launchpad.net/brz/+filebug\n\n")
255
254
 
256
 
        return bzr_log_file
 
255
        return brz_log_file
257
256
 
258
257
    except EnvironmentError, e:
259
258
        # If we are failing to open the log, then most likely logging has not
260
259
        # been set up yet. So we just write to stderr rather than using
261
260
        # 'warning()'. If we using warning(), users get the unhelpful 'no
262
 
        # handlers registered for "bzr"' when something goes wrong on the
 
261
        # handlers registered for "brz"' when something goes wrong on the
263
262
        # server. (bug #503886)
264
263
        sys.stderr.write("failed to open trace file: %s\n" % (e,))
265
264
    # TODO: What should happen if we fail to open the trace file?  Maybe the
269
268
 
270
269
 
271
270
def enable_default_logging():
272
 
    """Configure default logging: messages to stderr and debug to .bzr.log
 
271
    """Configure default logging: messages to stderr and debug to .brz.log
273
272
 
274
273
    This should only be called once per process.
275
274
 
276
275
    Non-command-line programs embedding brzlib do not need to call this.  They
277
276
    can instead either pass a file to _push_log_file, or act directly on
278
 
    logging.getLogger("bzr").
 
277
    logging.getLogger("brz").
279
278
 
280
279
    Output can be redirected away by calling _push_log_file.
281
280
 
282
281
    :return: A memento from push_log_file for restoring the log state.
283
282
    """
284
 
    start_time = osutils.format_local_date(_bzr_log_start_time,
 
283
    start_time = osutils.format_local_date(_brz_log_start_time,
285
284
                                           timezone='local')
286
 
    bzr_log_file = _open_bzr_log()
287
 
    if bzr_log_file is not None:
288
 
        bzr_log_file.write(start_time.encode('utf-8') + '\n')
289
 
    memento = push_log_file(bzr_log_file,
 
285
    brz_log_file = _open_brz_log()
 
286
    if brz_log_file is not None:
 
287
        brz_log_file.write(start_time.encode('utf-8') + '\n')
 
288
    memento = push_log_file(brz_log_file,
290
289
        r'[%(process)5d] %(asctime)s.%(msecs)03d %(levelname)s: %(message)s',
291
290
        r'%Y-%m-%d %H:%M:%S')
292
 
    # after hooking output into bzr_log, we also need to attach a stderr
 
291
    # after hooking output into brz_log, we also need to attach a stderr
293
292
    # handler, writing only at level info and with encoding
294
293
    stderr_handler = EncodedStreamHandler(sys.stderr,
295
294
        osutils.get_terminal_encoding(), 'replace', level=logging.INFO)
296
 
    logging.getLogger('bzr').addHandler(stderr_handler)
 
295
    logging.getLogger('brz').addHandler(stderr_handler)
297
296
    return memento
298
297
 
299
298
 
312
311
        log_format = '%(levelname)8s  %(message)s'
313
312
    new_handler.setFormatter(logging.Formatter(log_format, date_format))
314
313
    # save and remove any existing log handlers
315
 
    bzr_logger = logging.getLogger('bzr')
316
 
    old_handlers = bzr_logger.handlers[:]
317
 
    del bzr_logger.handlers[:]
 
314
    brz_logger = logging.getLogger('brz')
 
315
    old_handlers = brz_logger.handlers[:]
 
316
    del brz_logger.handlers[:]
318
317
    # set that as the default logger
319
 
    bzr_logger.addHandler(new_handler)
320
 
    bzr_logger.setLevel(logging.DEBUG)
 
318
    brz_logger.addHandler(new_handler)
 
319
    brz_logger.setLevel(logging.DEBUG)
321
320
    # TODO: check if any changes are needed to the root logger
322
321
    #
323
 
    # TODO: also probably need to save and restore the level on bzr_logger.
 
322
    # TODO: also probably need to save and restore the level on brz_logger.
324
323
    # but maybe we can avoid setting the logger level altogether, and just set
325
324
    # the level on the handler?
326
325
    #
341
340
    Takes the memento returned from _push_log_file."""
342
341
    global _trace_file
343
342
    _trace_file = old_trace_file
344
 
    bzr_logger = logging.getLogger('bzr')
345
 
    bzr_logger.removeHandler(new_handler)
 
343
    brz_logger = logging.getLogger('brz')
 
344
    brz_logger.removeHandler(new_handler)
346
345
    # must be closed, otherwise logging will try to close it at exit, and the
347
346
    # file will likely already be closed underneath.
348
347
    new_handler.close()
349
 
    bzr_logger.handlers = old_handlers
 
348
    brz_logger.handlers = old_handlers
350
349
    if new_trace_file is not None:
351
350
        new_trace_file.flush()
352
351
 
390
389
def _update_logging_level(quiet=True):
391
390
    """Hide INFO messages if quiet."""
392
391
    if quiet:
393
 
        _bzr_logger.setLevel(logging.WARNING)
 
392
        _brz_logger.setLevel(logging.WARNING)
394
393
    else:
395
 
        _bzr_logger.setLevel(logging.INFO)
 
394
        _brz_logger.setLevel(logging.INFO)
396
395
 
397
396
 
398
397
def is_quiet():
439
438
def _dump_memory_usage(err_file):
440
439
    try:
441
440
        try:
442
 
            fd, name = tempfile.mkstemp(prefix="bzr_memdump", suffix=".json")
 
441
            fd, name = tempfile.mkstemp(prefix="brz_memdump", suffix=".json")
443
442
            dump_file = os.fdopen(fd, 'w')
444
443
            from meliae import scanner
445
444
            scanner.dump_gc_objects(dump_file)
472
471
 
473
472
 
474
473
def report_exception(exc_info, err_file):
475
 
    """Report an exception to err_file (typically stderr) and to .bzr.log.
 
474
    """Report an exception to err_file (typically stderr) and to .brz.log.
476
475
 
477
476
    This will show either a full traceback or a short message as appropriate.
478
477
 
479
478
    :return: The appropriate exit code for this error.
480
479
    """
481
 
    # Log the full traceback to ~/.bzr.log
 
480
    # Log the full traceback to ~/.brz.log
482
481
    log_exception_quietly()
483
482
    if 'error' in debug.debug_flags:
484
483
        print_exception(exc_info, err_file)
539
538
 
540
539
 
541
540
def report_bug(exc_info, err_file):
542
 
    """Report an exception that probably indicates a bug in bzr"""
 
541
    """Report an exception that probably indicates a bug in brz"""
543
542
    from brzlib.crash import report_bug
544
543
    report_bug(exc_info, err_file)
545
544
 
633
632
    """
634
633
 
635
634
    def __enter__(self):
636
 
        self._original_filename = _bzr_log_filename
 
635
        self._original_filename = _brz_log_filename
637
636
        self._original_state = enable_default_logging()
638
637
        return self # This is bound to the 'as' clause in a with statement.
639
638
 
640
639
    def __exit__(self, exc_type, exc_val, exc_tb):
641
640
        pop_log_file(self._original_state)
642
 
        global _bzr_log_filename
643
 
        _bzr_log_filename = self._original_filename
 
641
        global _brz_log_filename
 
642
        _brz_log_filename = self._original_filename
644
643
        return False # propogate exceptions.