#!/usr/bin/python import bz2, gzip, os, re, sys separator = '------' class Log(object): date_re = re.compile(r'(\d{4}-\d\d-\d\d)[ T]([0-2]\d(:[0-5]\d){2}(,\d{3})?)') def __init__(self, path, prefix): if path == '-': self.file = sys.stdin elif path.endswith('.gz'): self.file = gzip.GzipFile(path) elif path.endswith('.bz2'): self.file = bz2.BZ2File(path) else: self.file = open(path) self.prefix = prefix def read(self): self.msg = [] for line in self.file: while line and line[-1] in '\r\n': line = line[:-1] if line != separator: self.msg.append(line) elif self.msg: break if self.msg: match = self.date_re.match(self.msg[0]) if match: self.date = match.group(1), match.group(2) return True def write(self): print '%s %s\n%s' % (self.prefix, '\n'.join(self.msg), separator) def __cmp__(self, other): return cmp(self.date, other.date) def main(): if len(sys.argv) > 2: log_set = set() index = 0 for log in sys.argv[1:]: if log in ('-h', '--help'): break index += 1 log = Log(log, '%02i' % index) if log.read(): log_set.add(log) else: while log_set: log = min(log_set) log.write() if not log.read(): log_set.remove(log) return 0 cmd = sys.argv and os.path.basename(sys.argv[0]) or 'merge_zlogs' print """merge_zlogs -- Merge Zope logs sorting lines by time. Usage: %(cmd)s [log]... hyphen-minus (-) is a shortcut for /dev/stdin Each output line is prefixed by a 2-digit index of the log where it comes from, starting from 1. Example to gather logs from several hosts: %(cmd)s <(ssh host1 '%(cmd)s %(event_logs)s') \\ %(_)s <(ssh host2 '%(cmd)s %(event_logs)s')""" % { 'cmd': cmd, '_': ' ' * len(cmd), 'event_logs': '/var/lib/zope/zeo_client?/log/event.log', } if __name__ == '__main__': sys.exit(main())