[Buildbot-commits] [Buildbot] #1699: Add support for wild-card matching for logfiles parameter in build steps
Buildbot
nobody at buildbot.net
Thu Mar 31 13:25:41 UTC 2011
#1699: Add support for wild-card matching for logfiles parameter in build steps
------------------------+--------------------
Reporter: lantictac | Owner:
Type: enhancement | Status: new
Priority: minor | Milestone: 1.0.+
Version: 0.8.2 | Resolution:
Keywords: |
------------------------+--------------------
Comment (by lantictac):
Sorry for the incredibly slow response (production deadlines got the
better of me). As it happens I did manage to get a hacky implementation
working, which we're using to dynamically pick up multiply log files
without explicitly declaring them in the master. Unfortuantely I might be
missing some key details but here's the basis for the implementation. Make
of it (and take of it) what you will...
On the slave side in runprocess.py...
{{{
# Used to watch for any number of files matching a given wild-card
class WildcardLogFileWatcher:
LIST_INTERVAL = 4
def __init__(self, command, name, logfile, follow=False):
self.command = command
self.name = name
self.logfile = logfile
self.dirPath = os.path.split(logfile)[0]
log.msg("WildcardLogFileWatcher created to watch %s dir %s" %
(logfile, self.dirPath))
self.started = False
# follow the file, only sending back lines
# added since we started watching
self.follow = follow
# every few seconds we check on the directory again
self.dirPoller = task.LoopingCall(self.dirPoll)
# maintain a list of child log file watches (initially empty)
self.logFileWatchers = []
# maintain a set of found log files to compare with the latest
matches
self.logFileSet = set()
def start(self):
self.dirPoller.start(self.LIST_INTERVAL).addErrback(self._cleanupListPoll)
def _cleanupListPoll(self, err):
log.err(err, msg="Polling error for file listing")
self.dirPoller = None
def stop(self):
self.dirPoll()
if self.dirPoller is not None:
self.dirPoller.stop()
for w in self.logFileWatchers:
w.stop()
def listDir(self):
if os.path.exists(self.dirPath):
return set(glob.glob(self.logfile))
return set()
def dirPoll(self):
fileSet = self.listDir()
if fileSet == self.logFileSet:
return # not started yet
# The fileSet is different so add the new files
newFileSet = fileSet - self.logFileSet
for filePath in newFileSet:
# Generate a unique name based on format:
"logname;realfilename"
uniqueName = "%s;%s" % (self.name, os.path.split(filePath)[1])
log.msg('WildcardLogFileWatcher found new file "%s" and
assigned it the name "%s"' % (filePath, uniqueName))
w = LogFileWatcher(self.command,
uniqueName,
filePath,
follow=self.follow)
w.start()
self.logFileWatchers.append(w)
self.logFileSet = self.logFileSet | newFileSet
}}}
And later in RunProcess __init__()
{{{
w = None
if filename.find('*') == -1:
w = LogFileWatcher(self, name,
os.path.join(self.workdir, filename),
follow=follow)
else:
w = WildcardLogFileWatcher(self, name,
os.path.join(self.workdir, filename),
follow=follow)
self.logFileWatchers.append(w)
}}}
While on the master side in buildstep.py:
{{{
def addToLog(self, logname, data):
oldname = logname
realname = logname
isWildCardPath = False
# Wild-card matches are returned encoded in the logname as
"oldname;realname"
# This allow a degree of backwards compatibilty and avoids
altering the protocol
if logname.find(';') != -1:
splitname = logname.split(';')
oldname = splitname[0]
realname = splitname[1]
assert oldname != realname
isWildCardPath = True
# Activate delayed logs on first data.
if oldname in self.delayedLogs and not (realname in self.logs):
(activateCallBack, closeWhenFinished) =
self.delayedLogs[oldname]
# Only wild-card based delayed logs should remain around to
deal with additional matches
if not isWildCardPath:
del self.delayedLogs[oldname]
# Allow the build step to create a new local log instance for
the status
loog = activateCallBack(self, realname)
self.logs[realname] = loog
self._closeWhenFinished[realname] = closeWhenFinished
if realname in self.logs:
self.logs[realname].addStdout(data)
else:
log.msg("%s.addToLog: no such log %s" % (self, realname))
}}}
Pretty ugly I'm sure you'll agree but the best I could throw together at
the time. It seems to work most of the time but I don't doubt there are
issues with this as it stands. Feel free to use and abuse if it might be
of use. Either way I'd love to see official support for this feature in
the near future - it certainly made managing our master.cfg vastly easier.
--
Ticket URL: <http://trac.buildbot.net/ticket/1699#comment:3>
Buildbot <http://buildbot.net/>
Buildbot: build/test automation
More information about the Commits
mailing list