pvl.syslog: implement --syslog-facility, implementing proper glob/regexp support in SyslogFilter
authorTero Marttila <terom@paivola.fi>
Thu, 10 Jan 2013 17:51:53 +0200
changeset 74 952ee07efd7a
parent 73 ef01c4639689
child 75 2e675eda5e33
pvl.syslog: implement --syslog-facility, implementing proper glob/regexp support in SyslogFilter
pvl/syslog/args.py
pvl/syslog/filter.py
pvl/syslog/parser.py
--- a/pvl/syslog/args.py	Thu Jan 10 17:50:10 2013 +0200
+++ b/pvl/syslog/args.py	Thu Jan 10 17:51:53 2013 +0200
@@ -29,6 +29,9 @@
     syslog.add_option('--syslog-raw',           action='store_true',
             help="Parse raw syslog lines without timestamp/etc")
 
+    syslog.add_option('--syslog-facility',      metavar='FACILITY',
+            help="Set/filter by given facility")
+
     syslog.add_option('--syslog-prog',          metavar='PROG',     default=prog,
             help="Filter by given prog: %default")
 
@@ -69,12 +72,14 @@
     
     # options
     parser = SyslogParser(
-        raw     = options.syslog_raw,
+        raw         = options.syslog_raw,
+        facility    = options.syslog_facility,
     )
 
     filter = SyslogFilter(
         # glob pattern
-        prog    = options.syslog_prog,
+        prog        = options.syslog_prog,
+        facility    = options.syslog_facility,
     )
 
     # polling
--- a/pvl/syslog/filter.py	Thu Jan 10 17:50:10 2013 +0200
+++ b/pvl/syslog/filter.py	Thu Jan 10 17:51:53 2013 +0200
@@ -16,38 +16,46 @@
         # drop None's
         self.filters = dict((attr, regex) for attr, regex in filters.iteritems() if regex is not None)
 
-    def match_prog (self, attr, glob, prog=None) :
+    def match_glob (self, attr, glob, value=None) :
         """
-            XXX: Match given prog as glob?
+            Match prog as glob.
         """
 
-        if not glob :
-            # ignore
-            return None
-
-        if not prog :
+        if not value :
             # require
             return False
 
         # normalize
-        prog = prog.strip().lower()
-        _, prog = os.path.split(prog)
+        value = value.strip()
 
         # match
-        if fnmatch.fnmatch(prog, glob) :
-            return { attr: prog }
+        if fnmatch.fnmatch(value, glob) :
+            return { attr: value }
         else :
             return False
+ 
+    match_facility = match_glob
 
-    def match (self, attr, regex, value=None) :
+    def match_prog (self, attr, glob, prog=None) :
+        """
+            Match prog as glob.
+        """
+
+        if prog :
+            # normalize
+            prog = prog.strip().lower()
+            _, prog = os.path.split(prog)
+
+        # match
+        return self.match_glob(attr, glob, prog)
+
+    REGEX_TYPE = type(re.compile(''))
+
+    def match_regex (self, attr, regex, value=None) :
         """
             Match given value against given pattern.
         """
 
-        if not regex :
-            # ignore
-            return None
-
         if not value :
             # XXX: optional = match empty string?
             value = ''
@@ -78,12 +86,25 @@
         matches = {}
 
         for attr in self.filters :
-            # lookup match-func
-            match = getattr(self, 'match_{attr}'.format(attr=attr), self.match)
-
             # filter
             filter = self.filters[attr]
+
+            if not filter :
+                # ignore
+                continue
             
+            # lookup match-func
+            match = getattr(self, 'match_{attr}'.format(attr=attr), None)
+
+            if match :
+                pass
+
+            elif isinstance(filter, self.REGEX_TYPE) :
+                match = self.match_regex
+
+            else :
+                match = self.match_glob
+
             # apply match
             if attr in item :
                 match = match(attr, filter, item[attr])
@@ -96,17 +117,13 @@
                 # match
                 matches.update(match)
             
-            elif match is None :
-                # ignore
-                continue
-
             else :
                 # reject
                 return
         
-        # XXX: test last match, in case they were all None
+        # test last match
         if match is None :
-            # XXX: empty filter!?
+            # empty filter -> all None
             return True
         else :
             return matches
--- a/pvl/syslog/parser.py	Thu Jan 10 17:50:10 2013 +0200
+++ b/pvl/syslog/parser.py	Thu Jan 10 17:51:53 2013 +0200
@@ -119,12 +119,13 @@
         +   r"(?P<message>(?P<tag>(?P<program>[^:\]]+)(?:\[(?P<pid>\d+)\])?: )?(?P<text>.*))\n?"
     )
 
-    def __init__ (self, raw=False) :
+    def __init__ (self, raw=False, facility=None) :
         """
             Using given underlying line source.
         """
 
         self.raw = raw
+        self.facility = facility
 
     def parse_pri (self, match) :
         """
@@ -132,10 +133,10 @@
         """
 
         pri = match.group('pri')
-        facility = match.group('facility')
+        facility = match.group('facility') or self.facility
         severity = match.group('severity')
         
-        if pri.isdigit() :
+        if pri and pri.isdigit() :
             pri = int(pri)
             facility, severity = divmod(pri, 8)
 
@@ -182,9 +183,6 @@
         # ignore whitespace
         line = line.strip()
 
-        # debug
-        log.debug("%s", line)
-
         # timestamp?
         if self.raw :
             # from defaults
@@ -214,8 +212,7 @@
             )
            
             # facility/severity prefix?
-            if match.group('pri') :
-                item.update(self.parse_pri(match))
+            item.update(self.parse_pri(match))
 
             return item
     
@@ -227,6 +224,8 @@
         for line in lines :
             item = self.parse(line)
 
+            log.debug("%s", item)
+
             if item :
                 yield item