#!/usr/bin/env python from optparse import OptionParser, Option import time, sys, os __cmdParser__ = OptionParser() __cmdParser__.add_option("-i", "--input", action="append", \ dest="logfiles", type="string", \ help="system log to parse") __cmdParser__.add_option("-v", "--verbose", action="count", \ dest="verbosity", \ help="How obnoxious we're being about telling the user what we're doing.") (__cmdLineOpts__, __cmdLineArgs__)=__cmdParser__.parse_args() class host_class: def __init__(self): self.logs = [] self.log_idx = 0 # first log self.log_ptr = 0 # first char def add_log(self, logfile): # if not logfile == logfile_class: # raise "InvalidLogfile" for inc in range(0,len(self.logs)): if logfile.time_end() < self.logs[inc].time_begin(): self.logs.insert(inc, logfile) break else: self.logs.append(logfile) def hostname(self): try: return self.logs[0].hostname() except: return None def tell(self): sumsize = 0 if self.log_idx > 0: for inc in range(0, self.log_idx): sumsize += self.logs[inc].size() try: sumsize += self.fp().tell() except TypeError: pass return sumsize def size(self): sumsize = 0 for inc in range(0, len(self.logs)): sumsize += self.logs[inc].size() return sumsize def eof(self): if self.tell() >= self.size(): return True return False def seek(self, offset, whence = 0): if whence == 1: offset = self.tell() + offset elif whence == 2: offset = self.size() + offset sumsize = 0 for inc in range(0, len(self.logs)): if offset <= sumsize + self.logs[inc].size(): offset -= sumsize self.log_idx = inc self.log_ptr = offset self.logs[inc].seek(offset) return True sumsize += self.logs[inc].size() raise "Off_Boundaries" def time(self): pos = self.tell() try: toret = time.strptime(self.readline()[0:15], "%b %d %H:%M:%S") except ValueError: toret = None self.seek(pos) return toret def fp(self): return self.logs[self.log_idx] def readline(self): if self.eof(): return "" while True: toret = self.fp().readline() if len(toret) == 0: if self.log_idx < len(self.logs): self.log_idx += 1 self.fp().seek(0) continue else: sys.exit("HOST IS EOF") return "" if self.validate_line(toret) or toret == "": return toret else: print "invalid line" def validate_line(self, line): try: time.strptime(line[0:15], "%b %d %H:%M:%S") except: return False return True def readmsg(self): toret = self.readline() if toret: return toret[18:] class logfile_class: def __init__(self,fname): self.events = [] self.fname = fname self.fp = open(fname) def hostname(self): pos = self.fp.tell() toret = self.fp.readline()[16:].split(" ")[0] self.fp.seek(pos) return toret def time_begin(self): pos = self.fp.tell() self.fp.seek(0) toret = time.strptime(self.fp.readline()[0:15], "%b %d %H:%M:%S") self.fp.seek(pos) return toret def time_end(self): pos = self.fp.tell() bs = 1024 self.fp.seek(-bs, 2) line = self.fp.read(bs) toret = time.strptime(line[line.rfind("\n", 0, bs - 1) + 1:][0:15], "%b %d %H:%M:%S") self.fp.seek(pos) return toret def size(self): return os.path.getsize(self.fname) def eof(self): return self.fp.tell() > self.size() def readline(self): return self.fp.readline() def seek(self,pos): self.fp.seek(pos) def tell(self): return self.fp.tell() def parse(self): self.seek(0) while not self.eof: self.readline() self.parse_line() self.seek(0) def parse_line(self): # is valid log line ? if not self.time_current(): return # store hostname, if we don't already have it if len(self.hostname) == 0: self.curline.split()[3] # system is booting if self.curmessage().startswith("kernel: Linux version"): self.add_event("system boot") # hostname has changed if len(self.hostname) and self.hostname != self.curline.split()[3]: self.add_event("hostname changed") self.hostname = self.curline.split()[3] # the clock is wrong wrong if self.prevline and time.strptime(self.prevline[0:15], "%b %d %H:%M:%S") > self.time_current(): self.add_event("clock is messed up") def add_event(self, message): self.events.append( (self.curline_pos,len(self.curline),message) ) def time_current(self): if len(self.curline) == 0: return None try: return time.strptime(self.curline[0:15], "%b %d %H:%M:%S") except ValueError: print "could not parse time", self.curline return False hosts = {} for logname in __cmdLineOpts__.logfiles: log = logfile_class(logname) hostname = log.hostname() if not hosts.has_key(hostname): hosts[hostname] = host_class() hosts[hostname].add_log(log) #print hosts["moka"].readline() #print hosts["moka"].readline() #print "DIRECT", hosts["moka"].fp().fp.tell() #print "HOST TELL", hosts["moka"].tell() #print hosts["moka"].readline() #print hosts["moka"].time() #print hosts["moka"].readline() #print hosts["moka"].time() #print hosts["moka"].readline() print """ """ #print '' print """ """ previous_date = None inc = 0 while True: # who is next ? lowest_date = None for host in hosts: if hosts[host].eof(): continue if lowest_date == None or hosts[host].time() < lowest_date: lowest_date = hosts[host].time() if lowest_date == None: # all logs are EOF break if inc == 0 or inc % 200 == 0: print """""" if not previous_date or time.strftime("%b %d", previous_date) != time.strftime("%b %d", lowest_date): print """""" % time.strftime("%A, %B %d", lowest_date) if inc % 2 == 0: row_class = "spec" else: row_class = "specalt" # FIXME: if this tick has an event, add if not previous_date or previous_date != lowest_date: print """""" % (row_class, time.strftime("%H:%M:%S", lowest_date) ) else: print """""" % (row_class, time.strftime("%H:%M:%S", lowest_date) ) for host in hosts: if hosts[host].time() == lowest_date: # print " " % hosts[host].tell() print " " # print " " % hosts[host].tell() else: print " " print " " previous_date = lowest_date inc += 1 print "
Generated by SOS htmlogger 1.0 on March 16th 2008
Timenode-1node-2node-3
%s
%s
%s%d" + hosts[host].readmsg() + "%d
"