blackbox: adds a blackbox extension
Adds a blackbox extension that listens to ui.log() and writes the messages to
.hg/blackbox.log. Future commits will use ui.log() to log commands, unhandled
exceptions, incoming changes, and hooks. The extension defaults to logging
everything, but can be configured via blackbox.track to only log certain events.
Log lines are of the format: "date time user> message"
Example log line:
2013/02/09 08:35:19 durham> 1 incoming changes - new heads:
d84ced58aaa
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext/blackbox.py Tue Feb 12 14:08:33 2013 -0800
@@ -0,0 +1,77 @@
+# worker.py - master-slave parallelism support
+#
+# 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.
+Examples:
+
+ [blackbox]
+ track = *
+
+ [blackbox]
+ track = command, commandfinish, commandexception, exthook, pythonhook
+
+ [blackbox]
+ track = incoming
+
+"""
+
+from mercurial import util, cmdutil
+from mercurial.i18n import _
+import os, getpass, re, string
+
+cmdtable = {}
+command = cmdutil.command(cmdtable)
+testedwith = 'internal'
+lastblackbox = None
+
+def wrapui(ui):
+ class blackboxui(ui.__class__):
+ @util.propertycache
+ def track(self):
+ return ui.configlist('blackbox', 'track', ['*'])
+
+ 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
+ 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')
+ user = getpass.getuser()
+ formattedmsg = msg[0] % msg[1:]
+ blackbox.write('%s %s> %s' % (date, user, formattedmsg))
+ lastblackbox = blackbox
+
+ def setrepo(self, repo):
+ self._blackbox = repo.opener('blackbox.log', 'a')
+
+ 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
+
+ ui.setrepo(repo)
--- a/mercurial/ui.py Mon Feb 11 16:15:12 2013 -0800
+++ b/mercurial/ui.py Tue Feb 12 14:08:33 2013 -0800
@@ -739,7 +739,7 @@
else:
self.debug('%s:%s %s%s\n' % (topic, item, pos, unit))
- def log(self, service, message):
+ def log(self, service, *msg, **opts):
'''hook for logging facility extensions
service should be a readily-identifiable subsystem, which will