168
168
:param args: A list of substitution variables.
170
170
outf = StringIO()
171
if stacklevel is None:
174
limit = stacklevel + 1
175
traceback.print_stack(limit=limit, file=outf)
171
traceback.print_stack(limit=stacklevel + 1, file=outf)
176
172
formatted_lines = outf.getvalue().splitlines()
177
173
formatted_stack = '\n'.join(formatted_lines[:-2])
178
174
mutter(fmt + "\nCalled from:\n%s", *(args + (formatted_stack,)))
235
231
def enable_default_logging():
236
232
"""Configure default logging: messages to stderr and debug to .bzr.log
238
234
This should only be called once per process.
240
236
Non-command-line programs embedding bzrlib do not need to call this. They
241
237
can instead either pass a file to _push_log_file, or act directly on
242
238
logging.getLogger("bzr").
244
240
Output can be redirected away by calling _push_log_file.
246
# Do this before we open the log file, so we prevent
247
# get_terminal_encoding() from mutter()ing multiple times
248
term_encoding = osutils.get_terminal_encoding()
249
start_time = time.strftime('%Y-%m-%d %H:%M:%S\n',
250
time.localtime(_bzr_log_start_time))
251
242
# create encoded wrapper around stderr
252
243
bzr_log_file = _open_bzr_log()
253
bzr_log_file.write(start_time)
254
244
push_log_file(bzr_log_file,
255
245
r'[%(process)5d] %(asctime)s.%(msecs)03d %(levelname)s: %(message)s',
256
246
r'%Y-%m-%d %H:%M:%S')
257
247
# after hooking output into bzr_log, we also need to attach a stderr
258
248
# handler, writing only at level info and with encoding
259
writer_factory = codecs.getwriter(term_encoding)
249
writer_factory = codecs.getwriter(osutils.get_terminal_encoding())
260
250
encoded_stderr = writer_factory(sys.stderr, errors='replace')
261
251
stderr_handler = logging.StreamHandler(encoded_stderr)
262
252
stderr_handler.setLevel(logging.INFO)
397
_short_fields = ('VmPeak', 'VmSize', 'VmRSS')
399
def debug_memory(message='', short=True):
400
"""Write out a memory dump."""
402
status_file = file('/proc/%s/status' % os.getpid(), 'rb')
406
status = status_file.read()
411
for line in status.splitlines():
415
for field in _short_fields:
416
if line.startswith(field):
421
387
def report_exception(exc_info, err_file):
422
388
"""Report an exception to err_file (typically stderr) and to .bzr.log.
435
401
elif isinstance(exc_object, KeyboardInterrupt):
436
402
err_file.write("bzr: interrupted\n")
437
403
return errors.EXIT_ERROR
438
elif isinstance(exc_object, ImportError) \
439
and str(exc_object).startswith("No module named "):
440
report_user_error(exc_info, err_file,
441
'You may need to install this Python library separately.')
442
return errors.EXIT_ERROR
443
404
elif not getattr(exc_object, 'internal_error', True):
444
405
report_user_error(exc_info, err_file)
445
406
return errors.EXIT_ERROR
464
425
# TODO: Should these be specially encoding the output?
465
def report_user_error(exc_info, err_file, advice=None):
426
def report_user_error(exc_info, err_file):
466
427
"""Report to err_file an error that's not an internal error.
468
429
These don't get a traceback unless -Derror was given.
470
:param exc_info: 3-tuple from sys.exc_info()
471
:param advice: Extra advice to the user to be printed following the
474
431
if 'error' in debug.debug_flags:
475
432
print_exception(exc_info, err_file)
477
434
err_file.write("bzr: ERROR: %s\n" % (exc_info[1],))
479
err_file.write("%s\n" % (advice,))
482
437
def report_bug(exc_info, err_file):