terom@31: """ terom@31: Syslog handling. terom@31: """ terom@31: terom@43: import select terom@43: terom@31: import logging; log = logging.getLogger('pvl.syslog.source') terom@31: terom@31: class SyslogSource (object) : terom@31: """ terom@50: Process syslog input from a given source. terom@50: terom@50: Implements an iterable mainloop doing continuous polling on the source, using either a timeout or terom@50: select():able source. terom@31: """ terom@31: terom@60: def __init__ (self, source, parser, filter, poll=None) : terom@31: """ terom@31: Using given underlying line source. terom@50: terom@50: source - source to select() if poll=True terom@50: poll - polling behaviour terom@31: """ terom@50: terom@31: self.source = source terom@60: self.parser = parser terom@60: self.filter = filter terom@60: terom@43: self._poll = poll terom@31: terom@63: def __iter__ (self) : terom@60: """ terom@60: Yield available input. terom@60: """ terom@60: terom@60: return self.filter(self.parser(self.source)) terom@60: terom@50: def poll (self, poll=None) : terom@31: """ terom@50: Poll our source for input, with given polling behaviour: terom@50: True - select() on source terom@50: False - peek on source terom@50: float - timeout in seconds terom@43: terom@43: Returns True if we have input waiting, False on timeout with no input. None on indeterminate. terom@43: """ terom@43: terom@50: reading = writing = () terom@43: terom@50: if poll is True : terom@50: timeout = None # block terom@50: reading += (self.source, ) # file-like object with fileno() terom@43: terom@50: elif not poll : terom@50: timeout = 0.0 # do not block terom@50: terom@50: else : terom@50: timeout = float(poll) terom@43: terom@48: log.debug("%s", timeout) terom@43: terom@43: # select terom@50: readable, writeable, ex = select.select(reading, writing, [], timeout) terom@43: terom@50: if readable : terom@43: return True terom@43: terom@50: elif reading : terom@43: # timeout terom@43: return False terom@43: terom@50: else : terom@50: # unknown terom@50: return None terom@50: terom@50: def main (self, poll=None) : terom@43: """ terom@50: yield items from syslog source, polling as given. terom@43: terom@43: Returns once no more lines are available. terom@43: terom@50: XXX: reconnect? or source takes care of that.. terom@50: TODO: SIGINT -> finish iteration and return? terom@43: """ terom@50: terom@50: if poll is None : terom@50: poll = self._poll terom@43: terom@43: # mainloop terom@43: while True : terom@43: # pull in messages terom@63: for item in self : terom@48: log.debug("%s", item) terom@43: yield item terom@31: terom@43: # poll terom@50: if poll : terom@43: # wait terom@50: self.poll(poll) terom@43: else : terom@43: # done terom@43: break terom@43: terom@43: log.debug("exit") terom@43: