# HG changeset patch # User Durham Goode # Date 1360706913 28800 # Node ID 18242716a014eea609f09f39b190248fafde4b00 # Parent 4034b8d551b116b882920466e1d209e475a62721 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 diff -r 4034b8d551b1 -r 18242716a014 hgext/blackbox.py --- /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) diff -r 4034b8d551b1 -r 18242716a014 mercurial/ui.py --- 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