def __init__(self, args, interactive=False, curses=False, chunksize=10000): if curses: screen.init_curses() elif interactive: screen.init_linebased() self.interactive = interactive self.args = args self.processed_rows = 0 self.oldpct = 0 self.data = [] self.chunksize = chunksize self.complete = Complete() self.crunchlogs() self.interact()
class LoGrok(object): def __init__(self, args, interactive=False, curses=False, chunksize=10000): if curses: screen.init_curses() elif interactive: screen.init_linebased() self.interactive = interactive self.args = args self.processed_rows = 0 self.oldpct = 0 self.data = [] self.chunksize = chunksize self.complete = Complete() self.crunchlogs() self.interact() def crunchlogs(self): global log_regex if self.args.format is not None: logformat = self.args.format else: logformat = logformat.TYPES[self.args.type] print lines = [] for logfile in self.args.logfile: screen.print_mutable("Reading lines from %s:" % logfile.name) lines += logfile.readlines() screen.print_mutable("Reading lines from %s: %d" % (logfile.name, len(lines))) logfile.close() screen.print_mutable("", True) log_regex = re.compile(parse_format_string(logformat)) if self.args.lines: lines = lines[:self.args.lines] st = time.time() self.data = parallel.run(log_match, lines, _print=True) et = time.time() print "%d lines crunched in %0.3f seconds" % (len(lines), (et-st)) def interact(self): if screen.is_curses(): screen.draw_curses_screen(self.data) self.main_loop() elif self.interactive: self.shell() else: self.query(self.args.query) def shell(self): try: history = os.path.expanduser('~/.logrok_history') readline.read_history_file(history) except IOError: pass atexit.register(readline.write_history_file, history) readline.set_history_length(1000) readline.parse_and_bind('tab: complete') readline.set_completer(self.complete.complete) # XXX This is ugly and needs to be more intelligent. Ideally, the # completer would use readline.readline() to contextually switch out # the returned matches self.complete.addopts(['select', 'from log', 'where', 'between', 'order by', 'group by', 'limit', ] + get_sqlfuncs() + self.data[0].keys()) while True: q = raw_input("logrok> ").strip() while not q.endswith(";"): q += raw_input("> ").strip() self.query(q) def query(self, query): semicolon = query.find(';') if semicolon != -1: query = query[:semicolon] if query in ('quit', 'bye', 'exit'): sys.exit(0) if query.startswith('help') or query.startswith('?'): answer = "Use sql syntax against your log, `from` clauses are ignored.\n"\ "Queries can span multiple lines and _must_ end in a semicolon `;`.\n"\ " Try: `show fields;` to see available field names. Press TAB at the\n"\ " beginning of a new line to see all available completions." print answer return if query in ('show fields', 'show headers'): print ', '.join(self.data[0].keys()) return else: try: q = LogQuery(self.data, query) return q.run() except SyntaxError, e: return e.message