~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/trace.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2011-08-03 04:57:59 UTC
  • mfrom: (6042.1.2 fix-log-2)
  • Revision ID: pqm@pqm.ubuntu.com-20110803045759-1lrr8eymve8ofldr
(mbp) Log levels are no longer reset to what the log formatter supports (bug
 747958) (Thomi Richards)

Show diffs side-by-side

added added

removed removed

Lines of Context:
54
54
# increased cost of logging.py is not so bad, and we could standardize on
55
55
# that.
56
56
 
 
57
import codecs
57
58
import logging
58
59
import os
59
60
import sys
110
111
 
111
112
    :return: None
112
113
    """
 
114
    # FIXME note always emits utf-8, regardless of the terminal encoding
 
115
    #
113
116
    # FIXME: clearing the ui and then going through the abstract logging
114
117
    # framework is whack; we should probably have a logging Handler that
115
118
    # deals with terminal output if needed.
282
285
    """
283
286
    start_time = osutils.format_local_date(_bzr_log_start_time,
284
287
                                           timezone='local')
 
288
    # create encoded wrapper around stderr
285
289
    bzr_log_file = _open_bzr_log()
286
290
    if bzr_log_file is not None:
287
291
        bzr_log_file.write(start_time.encode('utf-8') + '\n')
290
294
        r'%Y-%m-%d %H:%M:%S')
291
295
    # after hooking output into bzr_log, we also need to attach a stderr
292
296
    # handler, writing only at level info and with encoding
293
 
    stderr_handler = EncodedStreamHandler(sys.stderr,
294
 
        osutils.get_terminal_encoding(), 'replace', level=logging.INFO)
 
297
    term_encoding = osutils.get_terminal_encoding()
 
298
    writer_factory = codecs.getwriter(term_encoding)
 
299
    encoded_stderr = writer_factory(sys.stderr, errors='replace')
 
300
    stderr_handler = logging.StreamHandler(encoded_stderr)
 
301
    stderr_handler.setLevel(logging.INFO)
295
302
    logging.getLogger('bzr').addHandler(stderr_handler)
296
303
    return memento
297
304
 
306
313
    """
307
314
    global _trace_file
308
315
    # make a new handler
309
 
    new_handler = EncodedStreamHandler(to_file, "utf-8", level=logging.DEBUG)
 
316
    new_handler = logging.StreamHandler(to_file)
 
317
    new_handler.setLevel(logging.DEBUG)
310
318
    if log_format is None:
311
319
        log_format = '%(levelname)8s  %(message)s'
312
320
    new_handler.setFormatter(logging.Formatter(log_format, date_format))
483
491
        print_exception(exc_info, err_file)
484
492
        return errors.EXIT_ERROR
485
493
    exc_type, exc_object, exc_tb = exc_info
486
 
    if isinstance(exc_object, KeyboardInterrupt):
 
494
    if (isinstance(exc_object, IOError)
 
495
        and getattr(exc_object, 'errno', None) == errno.EPIPE):
 
496
        err_file.write("bzr: broken pipe\n")
 
497
        return errors.EXIT_ERROR
 
498
    elif isinstance(exc_object, KeyboardInterrupt):
487
499
        err_file.write("bzr: interrupted\n")
488
500
        return errors.EXIT_ERROR
489
501
    elif isinstance(exc_object, MemoryError):
501
513
    elif not getattr(exc_object, 'internal_error', True):
502
514
        report_user_error(exc_info, err_file)
503
515
        return errors.EXIT_ERROR
504
 
    elif osutils.is_environment_error(exc_object):
505
 
        if getattr(exc_object, 'errno', None) == errno.EPIPE:
506
 
            err_file.write("bzr: broken pipe\n")
507
 
            return errors.EXIT_ERROR
 
516
    elif isinstance(exc_object, (OSError, IOError)) or (
 
517
        # GZ 2010-05-20: Like (exc_type is pywintypes.error) but avoid import
 
518
        exc_type.__name__ == "error" and exc_type.__module__ == "pywintypes"):
508
519
        # Might be nice to catch all of these and show them as something more
509
520
        # specific, but there are too many cases at the moment.
510
521
        report_user_error(exc_info, err_file)
548
559
    try:
549
560
        sys.stdout.flush()
550
561
        sys.stderr.flush()
551
 
    except ValueError, e:
552
 
        # On Windows, I get ValueError calling stdout.flush() on a closed
553
 
        # handle
554
 
        pass
555
562
    except IOError, e:
556
563
        import errno
557
564
        if e.errno in [errno.EINVAL, errno.EPIPE]:
567
574
        _trace_file.flush()
568
575
 
569
576
 
570
 
class EncodedStreamHandler(logging.Handler):
571
 
    """Robustly write logging events to a stream using the specified encoding
572
 
 
573
 
    Messages are expected to be formatted to unicode, but UTF-8 byte strings
574
 
    are also accepted. An error during formatting or a str message in another
575
 
    encoding will be quitely noted as an error in the Bazaar log file.
576
 
 
577
 
    The stream is not closed so sys.stdout or sys.stderr may be passed.
578
 
    """
579
 
 
580
 
    def __init__(self, stream, encoding=None, errors='strict', level=0):
581
 
        logging.Handler.__init__(self, level)
582
 
        self.stream = stream
583
 
        if encoding is None:
584
 
            encoding = getattr(stream, "encoding", "ascii")
585
 
        self.encoding = encoding
586
 
        self.errors = errors
587
 
 
588
 
    def flush(self):
589
 
        flush = getattr(self.stream, "flush", None)
590
 
        if flush is not None:
591
 
            flush()
592
 
 
593
 
    def emit(self, record):
594
 
        try:
595
 
            line = self.format(record)
596
 
            if not isinstance(line, unicode):
597
 
                line = line.decode("utf-8")
598
 
            self.stream.write(line.encode(self.encoding, self.errors) + "\n")
599
 
        except Exception:
600
 
            log_exception_quietly()
601
 
            # Try saving the details that would have been logged in some form
602
 
            msg = args = "<Unformattable>"
603
 
            try:
604
 
                msg = repr(record.msg).encode("ascii")
605
 
                args = repr(record.args).encode("ascii")
606
 
            except Exception:
607
 
                pass
608
 
            # Using mutter() bypasses the logging module and writes directly
609
 
            # to the file so there's no danger of getting into a loop here.
610
 
            mutter("Logging record unformattable: %s %% %s", msg, args)
611
 
 
612
 
 
613
577
class Config(object):
614
578
    """Configuration of message tracing in bzrlib.
615
579