##// END OF EJS Templates
fsmonitor: normalize clock value to bytes...
fsmonitor: normalize clock value to bytes We normalize the value returned by watchman because we perform a number of compares with this value in code. So the easiest path forward is to normalize to bytes so we don't have to update many call sites. With this commit, the fsmonitor extension appears to be working with Python 3! Although there are still some failures in edge cases... Differential Revision: https://phab.mercurial-scm.org/D7213

File last commit:

r43347:687b865b default
r43715:09ab61c0 stable
Show More
blackbox.py
219 lines | 6.2 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.
Valentin Gatien-Baron
blackbox: disable extremely verbose logging (issue6110)...
r42834 The events that get logged can be configured via the blackbox.track and
blackbox.ignore config keys.
timeless
blackbox: log dirty state...
r28246
Takumi IINO
blackbox: fix literal block syntax
r19162 Examples::
Durham Goode
blackbox: adds a blackbox extension...
r18669
[blackbox]
track = *
Valentin Gatien-Baron
blackbox: disable extremely verbose logging (issue6110)...
r42834 ignore = pythonhook
timeless
blackbox: rewrite dirty documentation noting it is expensive
r28303 # dirty is *EXPENSIVE* (slow);
# each log entry indicates `+` if the repository is dirty, like :hg:`id`.
timeless
blackbox: log dirty state...
r28246 dirty = True
timeless
blackbox: optionally log event source
r28305 # record the source of log messages
logsource = True
Durham Goode
blackbox: adds a blackbox extension...
r18669
[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
Matt DeVore
blackbox: add configitem for format of log timestamps...
r40466 [blackbox]
# Include nanoseconds in log entries with %f (see Python function
# datetime.datetime.strftime)
date-format = '%Y-%m-%d @ %H:%M:%S.%f'
Durham Goode
blackbox: adds a blackbox extension...
r18669 """
Gregory Szorc
blackbox: use absolute_import
r28090 from __future__ import absolute_import
import re
Durham Goode
blackbox: adds a blackbox extension...
r18669 from mercurial.i18n import _
timeless
blackbox: log working directory version...
r28245 from mercurial.node import hex
Gregory Szorc
blackbox: use absolute_import
r28090 from mercurial import (
Gregory Szorc
py3: cast error message to localstr in blackbox.py...
r35685 encoding,
Yuya Nishihara
loggingutil: extract openlogfile() and proxylogger to new module...
r40830 loggingutil,
Yuya Nishihara
registrar: move cmdutil.command to registrar module (API)...
r32337 registrar,
Gregory Szorc
blackbox: use absolute_import
r28090 )
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 from mercurial.utils import (
dateutil,
procutil,
)
Durham Goode
blackbox: adds a blackbox extension...
r18669
Augie Fackler
extensions: change magic "shipped with hg" string...
r29841 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
Augie Fackler
extensions: document that `testedwith = 'internal'` is special...
r25186 # 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.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 testedwith = b'ships-with-hg-core'
blackbox: minor code reordering...
r33129
cmdtable = {}
command = registrar.command(cmdtable)
configitems: register 'blackbox.maxsize' as an example of 'configbytes'...
r33130 configtable = {}
configitem = registrar.configitem(configtable)
Augie Fackler
formatting: blacken the codebase...
r43346 configitem(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'blackbox', b'dirty', default=False,
configitems: register the 'blackbox.dirty' config
r33186 )
Augie Fackler
formatting: blacken the codebase...
r43346 configitem(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'blackbox', b'maxsize', default=b'1 MB',
Augie Fackler
formatting: blacken the codebase...
r43346 )
configitem(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'blackbox', b'logsource', default=False,
configitems: register 'blackbox.maxsize' as an example of 'configbytes'...
r33130 )
Augie Fackler
formatting: blacken the codebase...
r43346 configitem(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'blackbox', b'maxfiles', default=7,
configitems: register the 'blackbox.logsource' config
r33187 )
Augie Fackler
formatting: blacken the codebase...
r43346 configitem(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'blackbox', b'track', default=lambda: [b'*'],
Boris Feld
configitems: register the 'blackbox.maxfiles' config
r34746 )
Augie Fackler
formatting: blacken the codebase...
r43346 configitem(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'blackbox',
b'ignore',
default=lambda: [b'chgserver', b'cmdserver', b'extension'],
Valentin Gatien-Baron
blackbox: disable extremely verbose logging (issue6110)...
r42834 )
Augie Fackler
formatting: blacken the codebase...
r43346 configitem(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'blackbox', b'date-format', default=b'%Y/%m/%d %H:%M:%S',
Matt DeVore
blackbox: add configitem for format of log timestamps...
r40466 )
configitems: register 'blackbox.maxsize' as an example of 'configbytes'...
r33130
Yuya Nishihara
loggingutil: extract openlogfile() and proxylogger to new module...
r40830 _lastlogger = loggingutil.proxylogger()
Yuya Nishihara
blackbox: extract global last logger to proxylogger class...
r40795
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
blackbox: unindent "if True" block
r40681 class blackboxlogger(object):
Yuya Nishihara
blackbox: initialize logger with repo instance...
r40797 def __init__(self, ui, repo):
self._repo = repo
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._trackedevents = set(ui.configlist(b'blackbox', b'track'))
self._ignoredevents = set(ui.configlist(b'blackbox', b'ignore'))
self._maxfiles = ui.configint(b'blackbox', b'maxfiles')
self._maxsize = ui.configbytes(b'blackbox', b'maxsize')
Yuya Nishihara
blackbox: resurrect recursion guard...
r41029 self._inlog = False
Yuya Nishihara
blackbox: extract logger class from ui wrapper...
r40680
Yuya Nishihara
blackbox: extract function to test if log event is tracked...
r40684 def tracked(self, event):
Augie Fackler
formatting: blacken the codebase...
r43346 return (
b'*' in self._trackedevents and event not in self._ignoredevents
) or event in self._trackedevents
Yuya Nishihara
blackbox: extract function to test if log event is tracked...
r40684
Yuya Nishihara
blackbox: unindent "if True" block
r40681 def log(self, ui, event, msg, opts):
Yuya Nishihara
blackbox: resurrect recursion guard...
r41029 # self._log() -> ctx.dirty() may create new subrepo instance, which
# ui is derived from baseui. So the recursion guard in ui.log()
# doesn't work as it's local to the ui instance.
if self._inlog:
return
self._inlog = True
try:
self._log(ui, event, msg, opts)
finally:
self._inlog = False
def _log(self, ui, event, msg, opts):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 default = ui.configdate(b'devel', b'default-date')
date = dateutil.datestr(default, ui.config(b'blackbox', b'date-format'))
Yuya Nishihara
blackbox: unindent "if True" block
r40681 user = procutil.getuser()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pid = b'%d' % procutil.getpid()
changed = b''
Yuya Nishihara
blackbox: initialize repo attribute properly...
r40682 ctx = self._repo[None]
Yuya Nishihara
blackbox: unindent "if True" block
r40681 parents = ctx.parents()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 rev = b'+'.join([hex(p.node()) for p in parents])
if ui.configbool(b'blackbox', b'dirty') and ctx.dirty(
Augie Fackler
formatting: blacken the codebase...
r43346 missing=True, merge=False, branch=False
):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 changed = b'+'
if ui.configbool(b'blackbox', b'logsource'):
src = b' [%s]' % event
Yuya Nishihara
blackbox: unindent "if True" block
r40681 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 src = b''
Yuya Nishihara
blackbox: unindent "if True" block
r40681 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fmt = b'%s %s @%s%s (%s)%s> %s'
Yuya Nishihara
ui: pass in formatted message to logger.log()...
r40793 args = (date, user, rev, changed, pid, src, msg)
Yuya Nishihara
loggingutil: extract openlogfile() and proxylogger to new module...
r40830 with loggingutil.openlogfile(
Augie Fackler
formatting: blacken the codebase...
r43346 ui,
self._repo.vfs,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 name=b'blackbox.log',
Augie Fackler
formatting: blacken the codebase...
r43346 maxfiles=self._maxfiles,
maxsize=self._maxsize,
) as fp:
Yuya Nishihara
blackbox: unindent "if True" block
r40681 fp.write(fmt % args)
except (IOError, OSError) as err:
Yuya Nishihara
blackbox: change the way of deactivating the logger on write error...
r40791 # deactivate this to avoid failed logging again
Yuya Nishihara
blackbox: do not nullify repo to deactivate the logger on failure...
r40796 self._trackedevents.clear()
Augie Fackler
formatting: blacken the codebase...
r43346 ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'warning: cannot write to blackbox.log: %s\n'
Augie Fackler
formatting: blacken the codebase...
r43346 % encoding.strtolocal(err.strerror)
)
Yuya Nishihara
blackbox: just try writing to repo.vfs and update lastlogger on success...
r40828 return
_lastlogger.logger = self
Durham Goode
blackbox: adds a blackbox extension...
r18669
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
ui: manage logger instances and event filtering by core ui...
r40761 def uipopulate(ui):
Yuya Nishihara
blackbox: extract global last logger to proxylogger class...
r40795 ui.setlogger(b'blackbox', _lastlogger)
Yuya Nishihara
ui: manage logger instances and event filtering by core ui...
r40761
Augie Fackler
formatting: blacken the codebase...
r43346
Durham Goode
blackbox: adds a blackbox extension...
r18669 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
Yuya Nishihara
ui: manage logger instances and event filtering by core ui...
r40761 # Since blackbox.log is stored in the repo directory, the logger should be
# instantiated per repository.
Yuya Nishihara
blackbox: initialize logger with repo instance...
r40797 logger = blackboxlogger(ui, repo)
Yuya Nishihara
ui: manage logger instances and event filtering by core ui...
r40761 ui.setlogger(b'blackbox', logger)
Jun Wu
blackbox: set lastui even if ui.log is not called (issue5518)...
r34277
Yuya Nishihara
blackbox: extract global last logger to proxylogger class...
r40795 # Set _lastlogger even if ui.log is not called. This gives blackbox a
# fallback place to log
if _lastlogger.logger is None:
_lastlogger.logger = logger
Jun Wu
blackbox: set lastui even if ui.log is not called (issue5518)...
r34277
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo._wlockfreeprefix.add(b'blackbox.log')
Durham Goode
blackbox: adds a 'blackbox' command for viewing recent logs...
r18673
Augie Fackler
formatting: blacken the codebase...
r43346
@command(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'blackbox',
[(b'l', b'limit', 10, _(b'the number of events to show')),],
_(b'hg blackbox [OPTION]...'),
Rodrigo Damazio
help: adding a proper declaration for shortlist/basic commands (API)...
r40331 helpcategory=command.CATEGORY_MAINTENANCE,
Augie Fackler
formatting: blacken the codebase...
r43346 helpbasic=True,
)
Durham Goode
blackbox: adds a 'blackbox' command for viewing recent logs...
r18673 def blackbox(ui, repo, *revs, **opts):
'''view the recent repository events
'''
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not repo.vfs.exists(b'blackbox.log'):
Durham Goode
blackbox: adds a 'blackbox' command for viewing recent logs...
r18673 return
Pulkit Goyal
py3: handle keyword arguments in hgext/blackbox.py...
r34973 limit = opts.get(r'limit')
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fp = repo.vfs(b'blackbox.log', b'r')
lines = fp.read().split(b'\n')
Durham Goode
blackbox: adds a 'blackbox' command for viewing recent logs...
r18673
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>
Gregory Szorc
global: use raw strings for regular expressions with escapes...
r41673 if re.match(br'^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} .*> .*', line):
Durham Goode
blackbox: adds a 'blackbox' command for viewing recent logs...
r18673 count += 1
output.append(line)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(b'\n'.join(reversed(output)))