##// END OF EJS Templates
test: pull through http when testing for race conditions...
test: pull through http when testing for race conditions The http server is stateless giving more occasion for race. We switch the test to http before adding extra cases tests.

File last commit:

r25186:80c5b266 default
r25442:9ee395df default
Show More
blackbox.py
162 lines | 5.4 KiB | text/x-python | PythonLexer
Bryan O'Sullivan
blackbox: fix copyright
r18676 # blackbox.py - log repository events to a file for post-mortem debugging
Durham Goode
blackbox: adds a blackbox extension...
r18669 #
Bryan O'Sullivan
blackbox: fix copyright
r18676 # Copyright 2010 Nicolas Dumazet
Durham Goode
blackbox: adds a blackbox extension...
r18669 # Copyright 2013 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
"""log repository events to a blackbox for debugging
Logs event information to .hg/blackbox.log to help debug and diagnose problems.
The events that get logged can be configured via the blackbox.track config key.
Takumi IINO
blackbox: fix literal block syntax
r19162 Examples::
Durham Goode
blackbox: adds a blackbox extension...
r18669
[blackbox]
track = *
[blackbox]
track = command, commandfinish, commandexception, exthook, pythonhook
[blackbox]
track = incoming
Bryan O'Sullivan
blackbox: automatically rotate log files...
r19066 [blackbox]
# limit the size of a log file
maxsize = 1.5 MB
# rotate up to N log files when the current one gets too big
maxfiles = 3
Durham Goode
blackbox: adds a blackbox extension...
r18669 """
from mercurial import util, cmdutil
from mercurial.i18n import _
Bryan O'Sullivan
blackbox: automatically rotate log files...
r19066 import errno, os, re
Durham Goode
blackbox: adds a blackbox extension...
r18669
cmdtable = {}
command = cmdutil.command(cmdtable)
Augie Fackler
extensions: document that `testedwith = 'internal'` is special...
r25186 # Note for extension authors: ONLY specify testedwith = 'internal' for
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
# be specifying the version(s) of Mercurial they are tested with, or
# leave the attribute unspecified.
Durham Goode
blackbox: adds a blackbox extension...
r18669 testedwith = 'internal'
lastblackbox = None
def wrapui(ui):
class blackboxui(ui.__class__):
@util.propertycache
def track(self):
Bryan O'Sullivan
blackbox: fix a case of name capture
r19052 return self.configlist('blackbox', 'track', ['*'])
Durham Goode
blackbox: adds a blackbox extension...
r18669
Bryan O'Sullivan
blackbox: automatically rotate log files...
r19066 def _openlogfile(self):
def rotate(oldpath, newpath):
try:
os.unlink(newpath)
except OSError, err:
if err.errno != errno.ENOENT:
self.debug("warning: cannot remove '%s': %s\n" %
(newpath, err.strerror))
try:
if newpath:
os.rename(oldpath, newpath)
except OSError, err:
if err.errno != errno.ENOENT:
self.debug("warning: cannot rename '%s' to '%s': %s\n" %
(newpath, oldpath, err.strerror))
fp = self._bbopener('blackbox.log', 'a')
maxsize = self.configbytes('blackbox', 'maxsize', 1048576)
if maxsize > 0:
st = os.fstat(fp.fileno())
if st.st_size >= maxsize:
path = fp.name
fp.close()
maxfiles = self.configint('blackbox', 'maxfiles', 7)
for i in xrange(maxfiles - 1, 1, -1):
rotate(oldpath='%s.%d' % (path, i - 1),
newpath='%s.%d' % (path, i))
rotate(oldpath=path,
newpath=maxfiles > 0 and path + '.1')
fp = self._bbopener('blackbox.log', 'a')
return fp
Durham Goode
blackbox: adds a blackbox extension...
r18669 def log(self, event, *msg, **opts):
global lastblackbox
super(blackboxui, self).log(event, *msg, **opts)
if not '*' in self.track and not event in self.track:
return
if util.safehasattr(self, '_blackbox'):
blackbox = self._blackbox
Bryan O'Sullivan
blackbox: defer opening a log file until needed (issue3869)...
r18831 elif util.safehasattr(self, '_bbopener'):
try:
Bryan O'Sullivan
blackbox: automatically rotate log files...
r19066 self._blackbox = self._openlogfile()
Bryan O'Sullivan
blackbox: defer opening a log file until needed (issue3869)...
r18831 except (IOError, OSError), err:
self.debug('warning: cannot write to blackbox.log: %s\n' %
err.strerror)
del self._bbopener
self._blackbox = None
blackbox = self._blackbox
Durham Goode
blackbox: adds a blackbox extension...
r18669 else:
# certain ui instances exist outside the context of
# a repo, so just default to the last blackbox that
# was seen.
blackbox = lastblackbox
if blackbox:
date = util.datestr(None, '%Y/%m/%d %H:%M:%S')
Bryan O'Sullivan
blackbox: use util.getuser for portability...
r18787 user = util.getuser()
Durham Goode
blackbox: adds a blackbox extension...
r18669 formattedmsg = msg[0] % msg[1:]
Bryan O'Sullivan
blackbox: prevent failed I/O from causing hg to abort...
r18786 try:
blackbox.write('%s %s> %s' % (date, user, formattedmsg))
except IOError, err:
self.debug('warning: cannot write to blackbox.log: %s\n' %
err.strerror)
Durham Goode
blackbox: adds a blackbox extension...
r18669 lastblackbox = blackbox
def setrepo(self, repo):
Angel Ezquerra
localrepo: remove all external users of localrepo.opener...
r23877 self._bbopener = repo.vfs
Durham Goode
blackbox: adds a blackbox extension...
r18669
ui.__class__ = blackboxui
def uisetup(ui):
wrapui(ui)
def reposetup(ui, repo):
# During 'hg pull' a httppeer repo is created to represent the remote repo.
# It doesn't have a .hg directory to put a blackbox in, so we don't do
# the blackbox setup for it.
if not repo.local():
return
Durham Goode
blackbox: fix blackbox causing exceptions in tests...
r19230 if util.safehasattr(ui, 'setrepo'):
ui.setrepo(repo)
Durham Goode
blackbox: adds a 'blackbox' command for viewing recent logs...
r18673
@command('^blackbox',
[('l', 'limit', 10, _('the number of events to show')),
],
_('hg blackbox [OPTION]...'))
def blackbox(ui, repo, *revs, **opts):
'''view the recent repository events
'''
if not os.path.exists(repo.join('blackbox.log')):
return
limit = opts.get('limit')
Angel Ezquerra
localrepo: remove all external users of localrepo.opener...
r23877 blackbox = repo.vfs('blackbox.log', 'r')
Durham Goode
blackbox: adds a 'blackbox' command for viewing recent logs...
r18673 lines = blackbox.read().split('\n')
count = 0
output = []
for line in reversed(lines):
if count >= limit:
break
# count the commands by matching lines like: 2013/01/23 19:13:36 root>
if re.match('^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} .*> .*', line):
count += 1
output.append(line)
ui.status('\n'.join(reversed(output)))