/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 bzrlib/trace.py

  • Committer: Martin Pool
  • Date: 2005-08-24 00:34:21 UTC
  • Revision ID: mbp@sourcefrog.net-20050824003421-33dd8e5c739cad2a
- send trace messages out through python logging module

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
 
 
15
 
 
16
"""Messages and logging for bazaar-ng
 
17
 
 
18
Messages are sent out through the Python logging library.
 
19
 
 
20
They can be sent to two places: to stderr, and to ~/.bzr.log.
 
21
 
 
22
~/.bzr.log gets all messages, and tracebacks of all uncaught
 
23
exceptions.
 
24
 
 
25
Normally stderr only gets messages of level INFO and higher, and gets
 
26
only a summary of exceptions, not the traceback.
 
27
"""
 
28
 
 
29
 
 
30
# TODO: in debug mode, stderr should get full tracebacks and also
 
31
# debug messages.  (Is this really needed?)
 
32
 
 
33
# TODO: When running the test suites, we should add an additional
 
34
# logger that sends messages into the test log file.
 
35
 
 
36
 
 
37
import sys
 
38
import os
 
39
import logging
 
40
import traceback
 
41
 
 
42
 
 
43
class QuietFormatter(logging.Formatter):
 
44
    """Formatter that supresses the details of errors.
 
45
 
 
46
    This is used by default on stderr so as not to scare the user.
 
47
    """
 
48
    # At first I tried overriding formatException to suppress the
 
49
    # exception details, but that has global effect: no loggers
 
50
    # can get the exception details is we suppress them here.
 
51
 
 
52
    def format(self, record):
 
53
        s = 'bzr: '
 
54
        if record.levelno >= logging.WARNING:
 
55
            s += record.levelname + ': '
 
56
            
 
57
        s += record.getMessage() 
 
58
            
 
59
        if record.exc_info:
 
60
            # give just a summary of the exception, not the whole thing
 
61
            exinfo = traceback.extract_tb(record.exc_info[2])
 
62
            # the format of this string matches one of the REs
 
63
            s += '\n'
 
64
            s += ('  at %s line %d, in %s()\n' % exinfo[-1][:3])
 
65
            s += '  see ~/.bzr.log for debug information'
 
66
 
 
67
        return s
 
68
        
 
69
################
 
70
# configure default handler to stderr
 
71
 
 
72
_stderr_handler = logging.StreamHandler()
 
73
_stderr_handler.setFormatter(QuietFormatter())
 
74
 
 
75
if os.environ.get('BZR_DEBUG'):
 
76
    _stderr_handler.setLevel(logging.DEBUG)
 
77
else:
 
78
    _stderr_handler.setLevel(logging.INFO)
 
79
 
 
80
logging.getLogger('').addHandler(_stderr_handler)
 
81
 
 
82
 
 
83
 
 
84
################
 
85
# configure convenient aliases for output routines
 
86
 
 
87
_bzr_logger = logging.getLogger('bzr')
 
88
_bzr_logger.setLevel(logging.DEBUG) 
 
89
 
 
90
note =      _bzr_logger.info
 
91
warning =   _bzr_logger.warning
 
92
log_error = _bzr_logger.error
 
93
error =     _bzr_logger.error
 
94
mutter =    _bzr_logger.debug
 
95
debug =     _bzr_logger.debug
 
96
 
 
97
 
 
98
 
 
99
 
 
100
# we do the rollover using this code, rather than the default from python
 
101
# logging, because we only want to rollover at program startup, not on each
 
102
# message.  maybe that's not a good enough reason.
 
103
 
 
104
def _rollover_trace_maybe(trace_fname):
 
105
    import stat
 
106
    try:
 
107
        size = os.stat(trace_fname)[stat.ST_SIZE]
 
108
        if size <= 4 << 20:
 
109
            return
 
110
        old_fname = trace_fname + '.old'
 
111
 
 
112
        try:
 
113
            # must remove before rename on windows
 
114
            os.remove(old_fname)
 
115
        except OSError:
 
116
            pass
 
117
 
 
118
        try:
 
119
            # might fail if in use on windows
 
120
            os.rename(trace_fname, old_fname)
 
121
        except OSError:
 
122
            pass
 
123
    except OSError:
 
124
        return
 
125
 
 
126
 
 
127
 
 
128
def open_tracefile(argv=[], tracefilename='~/.bzr.log'):
 
129
    # Messages are always written to here, so that we have some
 
130
    # information if something goes wrong.  In a future version this
 
131
    # file will be removed on successful completion.
 
132
    global _file_handler
 
133
    import stat, codecs
 
134
 
 
135
    trace_fname = os.path.join(os.path.expanduser(tracefilename))
 
136
    _rollover_trace_maybe(trace_fname)
 
137
 
 
138
    # buffering=1 means line buffered
 
139
    try:
 
140
        tf = codecs.open(trace_fname, 'at', 'utf8', buffering=1)
 
141
 
 
142
        if os.fstat(tf.fileno())[stat.ST_SIZE] == 0:
 
143
            t.write("\nthis is a debug log for diagnosing/reporting problems in bzr\n")
 
144
            t.write("you can delete or truncate this file, or include sections in\n")
 
145
            t.write("bug reports to bazaar-ng@lists.canonical.com\n\n")
 
146
        
 
147
        _file_handler = logging.StreamHandler(tf)
 
148
        fmt = r'[%(process)5d] %(asctime)s.%(msecs)03d %(levelname)s: %(message)s'
 
149
        datefmt = r'%a %H:%M:%S'
 
150
        _file_handler.setFormatter(logging.Formatter(fmt, datefmt))
 
151
        _file_handler.setLevel(logging.DEBUG)
 
152
        logging.getLogger('').addHandler(_file_handler)
 
153
 
 
154
        import bzrlib
 
155
        
 
156
        debug('bzr %s invoked on python %s (%s)'
 
157
              % (bzrlib.__version__,
 
158
                 '.'.join(map(str, sys.version_info)),
 
159
                 sys.platform))
 
160
 
 
161
        debug('  arguments: %r' % argv)
 
162
        debug('  working dir: ' + os.getcwdu())
 
163
    except IOError, e:
 
164
        warning("failed to open trace file: %s" % (e))
 
165
 
 
166
 
 
167
 
 
168
def log_exception(msg=None):
 
169
    """Log the last exception into the trace file.
 
170
 
 
171
    The exception string representation is used as the error
 
172
    summary, unless msg is given.
 
173
    """
 
174
    if msg == None:
 
175
        ei = sys.exc_info()
 
176
        s = str(ei[1])
 
177
        if s[-1] == '\n':
 
178
            s = s[:-1]
 
179
        msg = s
 
180
        
 
181
    _bzr_logger.exception(msg)