terom@21: from twisted.internet import reactor, protocol terom@21: from twisted.python import log terom@21: terom@21: import fifo terom@21: terom@21: class LogSource (object) : terom@21: def __init__ (self, name, filters) : terom@21: # set later on terom@21: self.module = None terom@21: terom@21: # what filters to apply terom@21: self.filters = filters terom@21: terom@21: # name, for display purposes terom@21: self.name = name terom@21: terom@21: # used to gather data together into lines terom@21: self.buf = "" terom@21: terom@21: def setModule (self, module) : terom@21: self.module = module terom@21: terom@21: def handleError (self, msg) : terom@21: log.err(msg) terom@21: self.module.error(msg) terom@21: terom@21: def handleData (self, data) : terom@21: data = self.buf + data terom@21: terom@21: while "\n" in data : terom@21: line, data = data.split("\n", 1) terom@21: terom@21: self.handleLine(line) terom@21: terom@21: self.buf = data terom@21: terom@21: def handleLine (self, line) : terom@21: log.msg("Matching line `%s'..." % line) terom@21: terom@21: for filter in self.filters : terom@21: out = filter.test(line) terom@21: terom@21: if out : terom@21: log.msg("\t%s: %s" % (filter.event_type, out)) terom@21: self.module.sendEvent(filter.event_type, out) terom@21: terom@21: break terom@21: elif out is False : terom@21: return terom@21: else : # None terom@21: continue terom@21: terom@21: class File (LogSource, protocol.ProcessProtocol) : terom@21: def __init__ (self, name, path, filters) : terom@21: super(File, self).__init__(name, filters) terom@21: terom@21: self.path = path terom@21: terom@21: log.msg("spawning tail process for %s:%s" % (name, path)) terom@21: terom@21: reactor.spawnProcess(self, "/usr/bin/tail", ["tail", "-n0", "--follow=name", path]) terom@21: terom@21: def errReceived (self, data) : terom@21: self.handleError("tail for %s: %s" % (self.name, data)) terom@21: terom@21: def outReceived (self, data) : terom@21: self.handleData(data) terom@21: terom@21: def processEnded (self, reason) : terom@21: self.handleError("tail process for %s quit: %s" % (self.name, reason.getErrorMessage())) terom@21: terom@21: class Fifo (LogSource, fifo.Fifo) : terom@21: def __init__ (self, name, path, filters) : terom@21: LogSource.__init__(self, name, filters) terom@21: terom@21: log.msg("opening fifo for %s:%s" % (name, path)) terom@21: terom@21: fifo.Fifo.__init__(self, path) terom@21: terom@21: def dataReceived (self, data) : terom@21: self.handleData(data) terom@21: terom@21: def handleEOF (self) : terom@21: self.handleError("!!! EOF on fifo %s, re-opening" % self.name) terom@21: self.reopen() terom@21: terom@21: def connectionLost (self, reason) : terom@21: super(Fifo, self).connectionLost(reason) terom@21: self.handleError("lost fifo for %s: %s" % (self.name, reason.getErrorMessage())) terom@21: terom@21: