fixbot/logwatch/sources.py
author Tero Marttila <terom@fixme.fi>
Thu, 04 Feb 2010 19:40:51 +0200
changeset 40 b9fdb7710768
parent 21 fixbot/logwatch_sources.py@aa6df8f9c44a
child 48 ba101beeb062
permissions -rw-r--r--
move logwatch*.py to separate fixbot.logwatch package, and move logwatch_sources to etc/fixbot-logwatch.py
from twisted.internet import reactor, protocol
from twisted.python import log

from fixbot import fifo

class LogSource (object) :
    def __init__ (self, name, filters) :
        # set later on
        self.module = None
        
        # what filters to apply
        self.filters = filters
        
        # name, for display purposes
        self.name = name

        # used to gather data together into lines
        self.buf = ""

    def setModule (self, module) :
        self.module = module

    def handleError (self, msg) :
        log.err(msg)
        self.module.error(msg)

    def handleData (self, data) :
        data = self.buf + data
        
        while "\n" in data :
            line, data = data.split("\n", 1)

            self.handleLine(line)

        self.buf = data

    def handleLine (self, line) :
        log.msg("Matching line `%s'..." % line)

        for filter in self.filters :
            # let the filter process the line
            out = filter.test(line)

            if out :
                # positive match, send
                log.msg("\t%s: %s" % (filter.event_type, out))
                self.module.sendEvent(filter.event_type, out)

                break

            elif out is False :
                # negative match, stop processing
                return

            else :  # None
                # no match
                continue

class File (LogSource, protocol.ProcessProtocol) :
    """
        Stream lines from a regular file using /usr/bin/tail -f
    """

    def __init__ (self, name, path, filters) :
        super(File, self).__init__(name, filters)

        self.path = path

        log.msg("spawning tail process for %s:%s" % (name, path))

        reactor.spawnProcess(self, "/usr/bin/tail", ["tail", "-n0", "--follow=name", path])

    def errReceived (self, data) :
        self.handleError("tail for %s: %s" % (self.name, data))

    def outReceived (self, data) :
        self.handleData(data)

    def processEnded (self, reason) :
        self.handleError("tail process for %s quit: %s" % (self.name, reason.getErrorMessage()))

class Fifo (LogSource, fifo.Fifo) :
    """
        Stream lines from a fifo object.
    """

    def __init__ (self, name, path, filters) :
        LogSource.__init__(self, name, filters)

        log.msg("opening fifo for %s:%s" % (name, path))

        fifo.Fifo.__init__(self, path)
    
    def dataReceived (self, data) :
        self.handleData(data)

    def handleEOF (self) :
        self.handleError("!!! EOF on fifo %s, re-opening" % self.name)
        self.reopen()
    
    def connectionLost (self, reason) :
        super(Fifo, self).connectionLost(reason)
        self.handleError("lost fifo for %s: %s" % (self.name, reason.getErrorMessage()))