pvl.syslog: split out SyslogFilter
authorTero Marttila <terom@fixme.fi>
Thu, 03 Jan 2013 00:56:28 +0200
changeset 44 977442ccb72d
parent 43 9d13b101beab
child 45 10dfa434da77
pvl.syslog: split out SyslogFilter
pvl/syslog/args.py
pvl/syslog/filter.py
pvl/syslog/parser.py
pvl/syslog/syslog.py
--- a/pvl/syslog/args.py	Thu Jan 03 00:38:26 2013 +0200
+++ b/pvl/syslog/args.py	Thu Jan 03 00:56:28 2013 +0200
@@ -1,6 +1,7 @@
 import optparse, sys
 
 from pvl.syslog.parser import SyslogParser
+from pvl.syslog.filter import SyslogFilter
 from pvl.syslog.syslog import SyslogSource
 from pvl.syslog import fifo, tail
 
@@ -62,14 +63,18 @@
     else :
         log.error("No --syslog source given")
         sys.exit(2)
-    
+
     parser = SyslogParser(
         raw     = options.syslog_raw,
+    )
+
+    filter = SyslogFilter(
         prog    = options.syslog_prog,
     )
 
     # build
     return SyslogSource(source, parser,
-            poll    = poll
+            filter  = filter,
+            poll    = poll,
     )
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pvl/syslog/filter.py	Thu Jan 03 00:56:28 2013 +0200
@@ -0,0 +1,55 @@
+import logging; log = logging.getLogger('pvl.syslog.filter')
+
+class SyslogFilter (object) :
+    """
+        Filter syslog messages.
+    """
+
+    def __init__ (self, prog=None) :
+        """
+            prog        - match tag (process name)
+        """
+
+        self.prog = prog
+
+    def match_prog (self, prog) :
+        """
+            Match given prog?
+        """
+
+        # normalize
+        prog = prog.lower()
+
+        if prog.startswith('/') :
+            # base
+            prog = prog.split('/')[-1]
+
+        # match
+        if not prog :
+            # never matches non-tagged lines
+            return False
+
+        elif self.prog.endswith('*') :
+            # prefix match
+            return prog.startswith(self.prog[:-1])
+
+        else :
+            return prog == self.prog
+
+    def filter (self, item) :
+        """
+            Match given item?
+        """
+
+        if self.prog and not self.match_prog(item['prog']) :
+            log.debug("prog: %s: %r", self.prog, item['prog'])
+
+        else :
+            # ok
+            return True
+
+    def __call__ (self, items) :
+        for item in items:
+            if self.filter(item) :
+                yield item
+
--- a/pvl/syslog/parser.py	Thu Jan 03 00:38:26 2013 +0200
+++ b/pvl/syslog/parser.py	Thu Jan 03 00:56:28 2013 +0200
@@ -1,7 +1,3 @@
-"""
-    Parse syslog lines in text format.
-"""
-
 import datetime, time
 import re
 
@@ -9,7 +5,7 @@
 
 class SyslogParser (object) :
     """
-        A source of syslog items.
+        Parse syslog lines in text format, as used in logfiles/fifos.
     """
     
     # default syslogd format
@@ -23,13 +19,12 @@
 
     TIMESTAMP_FMT = '%b %d %H:%M:%S'
 
-    def __init__ (self, raw=False, prog=None) :
+    def __init__ (self, raw=False) :
         """
             Using given underlying line source.
         """
 
         self.raw = raw
-        self.prog = prog
 
     def parse_timestamp (self, match) :
         """
@@ -53,18 +48,11 @@
 
         prog = match.group('program')
 
-        if not prog :
+        if prog :
+            return prog
+        else :
             # no tag
             return None
-        
-        # normalize
-        prog = prog.lower()
-
-        if prog.startswith('/') :
-            # base
-            prog = prog.split('/')[-1]
-
-        return prog
 
     def parse (self, line) :
         """
@@ -83,7 +71,7 @@
             return dict(
                 timestamp   = datetime.datetime.now(), # XXX: None?
                 host        = None,
-                prog        = self.prog,
+                prog        = None,
                 pid         = None,
                 msg         = line,
             )
@@ -105,37 +93,6 @@
                 msg         = match.group('text'),
             )
     
-    def match_prog (self, prog) :
-        """
-            Match given prog?
-        """
-        
-        if not prog :
-            # never matches non-tagged lines
-            return False
-
-        elif self.prog.endswith('*') :
-            # prefix match
-            return prog.startswith(self.prog[:-1])
-        else :
-            return prog == self.prog
-
-
-    def filter (self, line, item) :
-        """
-            Filter given item?
-        """
-
-        if not item :
-            log.debug("empty: %r", line)
-
-        elif self.prog and not self.match_prog(item['prog']) :
-            log.debug("prog: %r", item)
-
-        else :
-            # ok
-            return True
-
     def process (self, lines) :
         """
             Yield SyslogMessages from given series of lines.
@@ -143,9 +100,8 @@
 
         for line in lines :
             item = self.parse(line)
-            
-            # filter?
-            if self.filter(line, item) :
+
+            if item :
                 yield item
 
     __call__ = process
--- a/pvl/syslog/syslog.py	Thu Jan 03 00:38:26 2013 +0200
+++ b/pvl/syslog/syslog.py	Thu Jan 03 00:56:28 2013 +0200
@@ -11,12 +11,13 @@
         A source of syslog items.
     """
     
-    def __init__ (self, source, parser, poll=None) :
+    def __init__ (self, source, parser, filter=None, poll=None) :
         """
             Using given underlying line source.
 
                 source          - file-like object with poll() and iter()
-                parser          - process() bytes -> messages
+                parser          - process() bytes -> items
+                filter          - filter items
                 poll            - using given polling style:
                     True            - select() source
                     float           - given interval
@@ -25,6 +26,7 @@
 
         self.source = source
         self.parser = parser
+        self.filter = filter
 
         self._poll = poll
 
@@ -34,9 +36,17 @@
         """
         
         # directly iter across source
-        for item in self.parser(self.source) :
-            yield item
+        iter = self.source
         
+        # parse
+        iter = self.parser(iter)
+        
+        # filter ?
+        if self.filter :
+            iter = self.filter(iter)
+        
+        return iter
+
     def poll (self, timeout=None) :
         """
             Poll source for input, with given timeout in seconds (float).