import logging; log = logging.getLogger('pvl.syslog.filter')
import re # XXX
import os.path, fnmatch
class SyslogFilter (object) :
"""
Match syslog messages fields against given patterns.
"""
def __init__ (self, **filters) :
"""
Match using given { field: regex }.
"""
self.filters = filters
def match_prog (self, attr, glob, prog=None) :
"""
XXX: Match given prog as glob?
"""
if not glob :
# ignore
return None
# normalize
prog = prog.strip().lower()
_, prog = os.path.split(prog)
# match
if fnmatch.fnmatch(prog, glob) :
return { attr: prog }
else :
return False
def match (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 = ''
else :
# normalize; XXX: unicode?
value = str(value).strip()
# match
match = regex.match(value)
if not match :
return False
# as match-values
matches = match.groupdict()
matches[attr] = match.group(0) # whole match
# TODO match.expand?
return matches
def filter (self, item) :
"""
Match given item. Returns any matched values (including regexp capture groups) across all fields.
"""
matches = {}
for attr in self.filters :
# lookup match-func
match = getattr(self, 'match_{attr}'.format(attr=attr), self.match)
# filter
filter = self.filters[attr]
# apply match
if attr in item :
match = match(attr, filter, item[attr])
else :
match = match(attr, filter)
log.debug("%s: %s", attr, match)
if match :
# match
matches.update(match)
elif match is None :
# ignore
continue
else :
# reject
return
# XXX: test last match, in case they were all None
if match is None :
# XXX: empty filter!?
return True
else :
return matches
def process (self, items) :
for item in items:
match = self.filter(item)
if match :
yield item
__call__ = process