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