import watcher import annotate import filters import searchengine import parser import traceback import cgi from cStringIO import StringIO import itertools import gzip class Reporter(object): def render_file(self, filenames, watchers, pipeline): if isinstance(filenames, (str, unicode)): filenames = [filenames] open_files = [] log_readers = [] for filename in filenames: if filename.endswith('.gz'): f = gzip.open(filename, 'rb') f.name = filename else: f = open(filename, 'rb') open_files.append(f) log_readers.append(parser.Parser(f)) log_reader = itertools.chain(*log_readers) try: result = self.render(log_reader, watchers, pipeline) return result finally: for f in open_files: f.close() def render(self, log_reader, watchers, pipeline): w = watcher.pass_through(watchers) pipeline.append(w) new_iter = iter(log_reader) for pipe in pipeline: new_iter = iter(pipe.iterlog(new_iter)) for value in new_iter: # The watchers will handle the actual accumulation pass reports = [] for w in watchers: try: report = w.report() except: out = StringIO() traceback.print_exc(file=out) report = '
%s
' % cgi.escape(out.getvalue()) if not report: continue reports.append({ 'name': w.name, 'title': w.title, 'report': report}) return self.format_reports(reports) def format_reports(self, reports): page = [] indexes = [] for report in reports: indexes.append('%s' % (report['name'], report['title'])) page.append('

%s

' % (report['name'], report['title'])) page.append('
%s
' % report['report']) return '
'.join(indexes) + '
' + '\n'.join(page) provides = {} def scan(module): for name in dir(module): value = getattr(module, name) if not hasattr(value, 'provides'): continue for name in value.provides: provides[name] = value scan(watcher) scan(annotate) scan(filters) scan(searchengine) for normal_attr in 'client ident authuser utim method url proto status bytes referer agent'.split(): provides[normal_attr] = None def setup_stack(watchers): has = [] pipeline = [] for w in watchers: has.extend(w.provides) for w in watchers: assert not isinstance(w.require, str), ( "Bad require: %s" % w) for req in w.require: add_require(req, has, pipeline) return watchers, pipeline def add_require(require_name, has, pipeline): if require_name in has: return need = provides[require_name] if need is None: has.append(require_name) return need = need() has.append(require_name) pipeline.append(need) assert not isinstance(need.require, str), ( "Bad require: %s" % need) for req in need.require: add_require(req, has, pipeline)