ui: manage logger instances and event filtering by core ui
The setup code in blackbox needs more tweaks since it has lots of black
magics. I'll fix them by follow-up patches.
To be clear, the goal of this series is to provide a proper way for command
server to install its own logger. I need it to debug in-memory repository
cache.
--- a/hgext/blackbox.py Mon Nov 12 21:10:51 2018 +0900
+++ b/hgext/blackbox.py Sun Nov 11 18:08:33 2018 +0900
@@ -53,7 +53,6 @@
pycompat,
registrar,
ui as uimod,
- util,
)
from mercurial.utils import (
dateutil,
@@ -147,9 +146,6 @@
def log(self, ui, event, msg, opts):
global _lastlogger
- if not self.tracked(event):
- return
-
if self._bbvfs:
_lastlogger = self
elif _lastlogger and _lastlogger._bbvfs:
@@ -201,33 +197,20 @@
def wrapui(ui):
class blackboxui(ui.__class__):
- def __init__(self, src=None):
- super(blackboxui, self).__init__(src)
- if src and r'_bblogger' in src.__dict__:
- self._bblogger = src._bblogger
-
- # trick to initialize logger after configuration is loaded, which
- # can be replaced later with blackboxlogger(ui) in uisetup(), where
- # both user and repo configurations should be available.
- @util.propertycache
- def _bblogger(self):
- return blackboxlogger(self)
-
def debug(self, *msg, **opts):
super(blackboxui, self).debug(*msg, **opts)
if self.debugflag:
self.log('debug', '%s', ''.join(msg))
- def log(self, event, *msg, **opts):
- super(blackboxui, self).log(event, *msg, **opts)
- self._bblogger.log(self, event, msg, opts)
-
ui.__class__ = blackboxui
uimod.ui = blackboxui
def uisetup(ui):
wrapui(ui)
+def uipopulate(ui):
+ ui.setlogger(b'blackbox', blackboxlogger(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
@@ -235,7 +218,10 @@
if not repo.local():
return
- logger = getattr(ui, '_bblogger', None)
+ # Since blackbox.log is stored in the repo directory, the logger should be
+ # instantiated per repository.
+ logger = blackboxlogger(ui)
+ ui.setlogger(b'blackbox', logger)
if logger:
logger.setrepo(repo)
--- a/hgext/logtoprocess.py Mon Nov 12 21:10:51 2018 +0900
+++ b/hgext/logtoprocess.py Sun Nov 11 18:08:33 2018 +0900
@@ -38,7 +38,6 @@
from mercurial import (
pycompat,
- util,
)
from mercurial.utils import (
procutil,
@@ -63,9 +62,7 @@
return bool(self._scripts.get(event))
def log(self, ui, event, msg, opts):
- script = self._scripts.get(event)
- if not script:
- return
+ script = self._scripts[event]
env = {
b'EVENT': event,
b'HGPID': os.getpid(),
@@ -77,24 +74,5 @@
fullenv = procutil.shellenviron(env)
procutil.runbgcommand(script, fullenv, shell=True)
-def uisetup(ui):
-
- class logtoprocessui(ui.__class__):
- def __init__(self, src=None):
- super(logtoprocessui, self).__init__(src)
- if src and r'_ltplogger' in src.__dict__:
- self._ltplogger = src._ltplogger
-
- # trick to initialize logger after configuration is loaded, which
- # can be replaced later with processlogger(ui) in uisetup(), where
- # both user and repo configurations should be available.
- @util.propertycache
- def _ltplogger(self):
- return processlogger(self)
-
- def log(self, event, *msg, **opts):
- self._ltplogger.log(self, event, msg, opts)
- return super(logtoprocessui, self).log(event, *msg, **opts)
-
- # Replace the class for this instance and all clones created from it:
- ui.__class__ = logtoprocessui
+def uipopulate(ui):
+ ui.setlogger(b'logtoprocess', processlogger(ui))
--- a/mercurial/ui.py Mon Nov 12 21:10:51 2018 +0900
+++ b/mercurial/ui.py Sun Nov 11 18:08:33 2018 +0900
@@ -235,6 +235,7 @@
self._fmsgout = src._fmsgout
self._fmsgerr = src._fmsgerr
self._finoutredirected = src._finoutredirected
+ self._loggers = src._loggers.copy()
self.pageractive = src.pageractive
self._disablepager = src._disablepager
self._tweaked = src._tweaked
@@ -263,6 +264,7 @@
self._fmsgout = self.fout # configurable
self._fmsgerr = self.ferr # configurable
self._finoutredirected = False
+ self._loggers = {}
self.pageractive = False
self._disablepager = False
self._tweaked = False
@@ -1709,6 +1711,18 @@
'''exists only so low-level modules won't need to import scmutil'''
return scmutil.progress(self, topic, unit, total)
+ def getlogger(self, name):
+ """Returns a logger of the given name; or None if not registered"""
+ return self._loggers.get(name)
+
+ def setlogger(self, name, logger):
+ """Install logger which can be identified later by the given name
+
+ More than one loggers can be registered. Use extension or module
+ name to uniquely identify the logger instance.
+ """
+ self._loggers[name] = logger
+
def log(self, event, *msg, **opts):
'''hook for logging facility extensions
@@ -1720,6 +1734,14 @@
**opts currently has no defined meanings.
'''
+ if not self._loggers:
+ return
+ activeloggers = [l for l in self._loggers.itervalues()
+ if l.tracked(event)]
+ if not activeloggers:
+ return
+ for logger in activeloggers:
+ logger.log(self, event, msg, opts)
def label(self, msg, label):
'''style msg based on supplied label