pvl.syslog: implement --syslog-facility, implementing proper glob/regexp support in SyslogFilter
--- 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