def open_file(self, filename): self._trace_parser = TraceParser(filename, self._parser_event_handler) self._progress_notification_record_block_size = self._trace_parser.end_offset / 10 self._next_redraw_record_count = self._progress_notification_record_block_size self._trace_parser.set_color(True) self._trace_parser.set_relative_ts(False) self._trace_parser.set_indent(True) self._trace_parser.set_show_field_names(False) self._trace_walker.set_parser(self._trace_parser) self._trace_walker.reread() self._footer.set_text(self._footer_text + [' ', filename]) self._edit_line.set_completer( MultipleSelectionCompleter( StringlistCompleter( self._trace_walker.get_completion_names())))
def open_file(self, filename): self._trace_parser = TraceParser(filename) self._trace_parser.set_color(True) self._trace_parser.set_relative_ts(False) self._trace_parser.set_indent(True) self._trace_walker.set_parser(self._trace_parser) self._trace_walker.reread() self._footer.set_text(self._footer_text + [' ', filename]) self._edit_line.set_completer(MultipleSelectionCompleter(StringlistCompleter(self._trace_walker.get_completion_names())))
def open_file(self, filename): self._trace_parser = TraceParser(filename, self._parser_event_handler) self._progress_notification_record_block_size = self._trace_parser.end_offset / 10 self._next_redraw_record_count = self._progress_notification_record_block_size self._trace_parser.set_color(True) self._trace_parser.set_relative_ts(False) self._trace_parser.set_indent(True) self._trace_parser.set_show_field_names(False) self._trace_walker.set_parser(self._trace_parser) self._trace_walker.reread() self._footer.set_text(self._footer_text + [' ', filename]) self._edit_line.set_completer(MultipleSelectionCompleter(StringlistCompleter(self._trace_walker.get_completion_names())))
class TraceReaderUI(object): _footer_text = [ ('title', "Trace reader " + __version__), " ", ] def __init__(self): self._trace_walker = TraceWalker() self._trace_view = AlwaysOnTopListBox(self._trace_walker) self._edit_line = AdvancedEdit() self._info_line = urwid.Text('') self._footer = AnsiText(self._footer_text) self._command_indicator = urwid.Text('') self._command_indicator_string = '--> ' self._command_mode = None self._last_command = None self._last_filter = None self._hex = False self._show_field_names = False self._cancel_operation = False self._progress_notification_record_multiple = 0 footer_columns = urwid.AttrMap( urwid.Columns([self._footer, self._info_line]), 'foot') wrapped_edit_line = urwid.Columns([ ('fixed', len(self._command_indicator_string), self._command_indicator), self._edit_line ]) footer = urwid.Pile([footer_columns, wrapped_edit_line]) self._main_frame = urwid.Frame(urwid.AttrWrap(self._trace_view, 'body'), footer=footer) def _metadata_updated_handler(self): self._edit_line.set_completer( MultipleSelectionCompleter( StringlistCompleter( self._trace_walker.get_completion_names()))) def _get_progress_line(self, records_processed, current_offset): if not self._command_mode: return None if 'forward' in self._command_mode or 'filter' in self._command_mode: end_offset = self._trace_parser.end_offset else: end_offset = 0 remaining_records_to_process = abs(current_offset - end_offset) remaining_percent = remaining_records_to_process / ( self._trace_parser.end_offset / 100) return '%d%% remaining to process' % (remaining_percent, ) def _parser_event_handler(self, event, **kw): if event == 'metadata_updated': self._metadata_updated_handler() if event == 'operation_in_progress': records_processed = kw['records_processed'] current_offset = kw['current_offset'] if records_processed >= self._next_redraw_record_count: progress_line = self._get_progress_line( records_processed, current_offset) if progress_line: self._info_line.set_text(progress_line) self.loop.draw_screen() self._next_redraw_record_count += self._progress_notification_record_block_size if self._cancel_operation: self._trace_parser.cancel_ongoing_operation() self._cancel_operation = False if event == 'interrupted': self._cancel_operation = True def open_file(self, filename): self._trace_parser = TraceParser(filename, self._parser_event_handler) self._progress_notification_record_block_size = self._trace_parser.end_offset / 10 self._next_redraw_record_count = self._progress_notification_record_block_size self._trace_parser.set_color(True) self._trace_parser.set_relative_ts(False) self._trace_parser.set_indent(True) self._trace_parser.set_show_field_names(False) self._trace_walker.set_parser(self._trace_parser) self._trace_walker.reread() self._footer.set_text(self._footer_text + [' ', filename]) self._edit_line.set_completer( MultipleSelectionCompleter( StringlistCompleter( self._trace_walker.get_completion_names()))) def _clear_edit_line(self): self._edit_line.set_edit_text('') self._command_indicator.set_text('') def _dumb_search(self, search_string): i = 0 _, pos = self._trace_walker.get_focus() if 'forward' in self._command_mode: walker = self._trace_walker.get_next op = operator.add else: walker = self._trace_walker.get_prev op = operator.sub while not self._cancel_operation: record, _ = walker(op(pos, i)) i += 1 if not record: return 'expression not found' record_text = record.get_text()[0] if record_text.find(str(search_string)) != -1: break def _set_info_line(self, text): self._info_line.set_text(text) def _goto_end_of_edit_line(self): self._edit_line.edit_pos = 5 def _handle_search_expression(self, matcher): start_time = time.time() _, pos = self._trace_view.get_focus() if self._command_mode == 'search_forward': result = self._trace_walker.find_next_by_expression(matcher) self._trace_view.set_focus(0, 'above') else: self._trace_walker.get_prev(pos) result = self._trace_walker.find_previous_by_expression(matcher) self._trace_view.set_focus(0, 'below') end_time = time.time() search_time = end_time - start_time if result: result = 'search succeeded after %f seconds' % (search_time, ) else: result = 'search failed after %f seconds' % (search_time, ) return result def _handle_search_command_string(self, command_str): self._cancel_operation = False matcher = self._trace_walker.get_matcher_from_string(command_str) if command_str == 'focus': return self._trace_walker.get_focus() result = self._trace_walker.seek_to_time(command_str) if result: return result elif matcher: return self._handle_search_expression(matcher) else: return self._dumb_search(command_str) def _handle_filter_command_string(self, command_str): if self._last_filter == command_str: return 'filter unchanged ' result = self._trace_walker.set_filter(command_str) self._last_filter = command_str if result: return 'Filter set' else: return 'Error setting filter' def _seek_to_top(self): self._trace_walker.seek_to_pos(self._trace_view.get_top_position()) def _handle_command_string(self, command_str): self._last_command = (self._command_mode, command_str) self._next_redraw_record_count = self._progress_notification_record_block_size self._seek_to_top() if self._command_mode in ('search_backward', 'search_forward'): status = self._handle_search_command_string(command_str) elif self._command_mode == 'filter': status = self._handle_filter_command_string(command_str) if status: self._set_info_line(str(status)) self._command_mode = None self._trace_view.set_focus_to_top_widget() def _handle_command(self): text = self._edit_line.get_edit_text().strip() self._clear_edit_line() self._handle_command_string(text) def _do_search_input(self, direction): self._main_frame.set_focus('footer') self._command_mode = 'search_' + direction self._command_indicator.set_text(self._command_indicator_string) def _do_filter(self, new_filter=False): self._main_frame.set_focus('footer') self._command_mode = 'filter' if not new_filter: self._goto_end_of_edit_line() if self._last_filter: self._edit_line.set_edit_text(self._last_filter) self._edit_line.keypress((100, ), 'end') self._command_indicator.set_text(self._command_indicator_string) def _run_command(self, command_mode, command_str): self._command_mode = command_mode self._handle_command_string(command_str) def _repeat_last_command(self): if not self._last_command: return command_mode, command_str = self._last_command self._run_command(command_mode, command_str) def _search_leave(self): command_mode = 'search_forward' command_str = 'nesting == %d and tid == %d' % ( self._trace_walker.get_raw_record_at_focus().nesting, self._trace_walker.get_raw_record_at_focus().tid) self._run_command(command_mode, command_str) def _search_caller(self, input): directions = {'c': 'forward', 'C': 'backward'} command_mode = 'search_' + directions[input] nesting = self._trace_walker.get_raw_record_at_focus().nesting - 1 command_str = 'nesting == %d and tid == %d' % ( nesting, self._trace_walker.get_raw_record_at_focus().tid) self._run_command(command_mode, command_str) def _search_error(self, input): directions = {'e': 'forward', 'E': 'backward'} command_mode = 'search_' + directions[input] command_str = 'severity == ERROR' self._run_command(command_mode, command_str) def _search_info(self, input): directions = {'i': 'forward', 'I': 'backward'} command_mode = 'search_' + directions[input] command_str = 'severity == INFO' self._run_command(command_mode, command_str) def _search_warn(self, input): directions = {'w': 'forward', 'W': 'backward'} command_mode = 'search_' + directions[input] command_str = 'severity == WARN' self._run_command(command_mode, command_str) def _search_debug(self, input): directions = {'d': 'forward', 'D': 'backward'} command_mode = 'search_' + directions[input] command_str = 'severity == DEBUG' self._run_command(command_mode, command_str) def _toggle_hex(self): self._hex = not self._hex self._trace_parser.set_always_hex(self._hex) self._seek_to_top() def _toggle_field_names(self): self._show_field_names = not self._show_field_names self._trace_parser.set_show_field_names(self._show_field_names) self._seek_to_top() def _handle_input(self, input): if input in ('q', 'Q'): raise urwid.ExitMainLoop() if input in ('s', 'S'): if input == 's': self._do_search_input('forward') elif input == 'S': self._do_search_input('backward') if input in ('f', ): self._do_filter(False) if input in ('F', ): self._do_filter(True) if input in ('n', 'N'): self._repeat_last_command() if input in ('e', 'E'): self._search_error(input) if input in ('d', 'D'): self._search_debug(input) if input in ('w', 'W'): self._search_warn(input) if input in ('i', 'I'): self._search_info(input) if input in ('c', 'C'): self._search_caller(input) if input in ('l'): self._search_leave() if input in ('x'): self._toggle_field_names() if input in ('o'): self._toggle_hex() if input == 'end': self._trace_walker.seek_to_end() self._trace_view.set_focus(0, 'above') if input == 'home': self._trace_walker.seek_to_start() self._trace_view.set_focus(0, 'below') if input == 'enter' and self._main_frame.get_focus() == 'footer': self._handle_command() self._main_frame.set_focus('body') self._trace_view.set_focus_to_top_widget() self._trace_view.set_focus_valign('top') def _cancel_pending_commands(self): if self._command_mode: self._cancel_operation = True self._set_info_line('Cancelled') self._clear_edit_line() self._main_frame.set_focus('body') def _handle_keyboard_interrupt(self): self._cancel_pending_commands() def _handle_sigint(self, signal, frame): self._handle_keyboard_interrupt() def run(self, filename): signal.signal(signal.SIGINT, self._handle_sigint) self.loop = urwid.MainLoop(self._main_frame, AnsiText.get_palette() + palette, handle_mouse=False, unhandled_input=self._handle_input) self.open_file(filename) self.loop.run()
class TraceReaderUI(object): _footer_text = [ ('title', "Trace reader " + __version__), " ", ] def __init__(self): self._trace_walker = TraceWalker() self._trace_view = AlwaysOnTopListBox(self._trace_walker) self._edit_line = AdvancedEdit() self._info_line = urwid.Text('') self._footer = AnsiText(self._footer_text) self._command_indicator = urwid.Text('') self._command_indicator_string = '--> ' self._command_mode = None self._last_command = None self._last_filter = None self._hex = False self._show_field_names = False self._cancel_operation = False self._progress_notification_record_multiple = 0 footer_columns = urwid.AttrMap(urwid.Columns([self._footer, self._info_line]), 'foot') wrapped_edit_line = urwid.Columns([('fixed', len(self._command_indicator_string), self._command_indicator), self._edit_line]) footer = urwid.Pile([footer_columns, wrapped_edit_line]) self._main_frame = urwid.Frame(urwid.AttrWrap(self._trace_view, 'body'), footer = footer) def _metadata_updated_handler(self): self._edit_line.set_completer(MultipleSelectionCompleter(StringlistCompleter(self._trace_walker.get_completion_names()))) def _get_progress_line(self, records_processed, current_offset): if not self._command_mode: return None if 'forward' in self._command_mode or 'filter' in self._command_mode: end_offset = self._trace_parser.end_offset else: end_offset = 0; remaining_records_to_process = abs(current_offset - end_offset) remaining_percent = remaining_records_to_process / (self._trace_parser.end_offset / 100) return '%d%% remaining to process' % (remaining_percent,) def _parser_event_handler(self, event, **kw): if event == 'metadata_updated': self._metadata_updated_handler() if event == 'operation_in_progress': records_processed = kw['records_processed'] current_offset = kw['current_offset'] if records_processed >= self._next_redraw_record_count: progress_line = self._get_progress_line(records_processed, current_offset) if progress_line: self._info_line.set_text(progress_line) self.loop.draw_screen() self._next_redraw_record_count += self._progress_notification_record_block_size if self._cancel_operation: self._trace_parser.cancel_ongoing_operation() self._cancel_operation = False if event == 'interrupted': self._cancel_operation = True def open_file(self, filename): self._trace_parser = TraceParser(filename, self._parser_event_handler) self._progress_notification_record_block_size = self._trace_parser.end_offset / 10 self._next_redraw_record_count = self._progress_notification_record_block_size self._trace_parser.set_color(True) self._trace_parser.set_relative_ts(False) self._trace_parser.set_indent(True) self._trace_parser.set_show_field_names(False) self._trace_walker.set_parser(self._trace_parser) self._trace_walker.reread() self._footer.set_text(self._footer_text + [' ', filename]) self._edit_line.set_completer(MultipleSelectionCompleter(StringlistCompleter(self._trace_walker.get_completion_names()))) def _clear_edit_line(self): self._edit_line.set_edit_text('') self._command_indicator.set_text('') def _dumb_search(self, search_string): i = 0 _, pos = self._trace_walker.get_focus() if 'forward' in self._command_mode: walker = self._trace_walker.get_next op = operator.add else: walker = self._trace_walker.get_prev op = operator.sub while not self._cancel_operation: record, _ = walker(op(pos, i)) i += 1 if not record: return 'expression not found' record_text = record.get_text()[0] if record_text.find(str(search_string)) != -1: break def _set_info_line(self, text): self._info_line.set_text(text) def _goto_end_of_edit_line(self): self._edit_line.edit_pos = 5 def _handle_search_expression(self, matcher): start_time = time.time() _, pos = self._trace_view.get_focus() if self._command_mode == 'search_forward': result = self._trace_walker.find_next_by_expression(matcher) self._trace_view.set_focus(0, 'above') else: self._trace_walker.get_prev(pos) result = self._trace_walker.find_previous_by_expression(matcher) self._trace_view.set_focus(0, 'below') end_time = time.time() search_time = end_time - start_time if result: result = 'search succeeded after %f seconds' % (search_time,) else: result = 'search failed after %f seconds' % (search_time,) return result def _handle_search_command_string(self, command_str): self._cancel_operation = False matcher = self._trace_walker.get_matcher_from_string(command_str) if command_str == 'focus': return self._trace_walker.get_focus() result = self._trace_walker.seek_to_time(command_str) if result: return result elif matcher: return self._handle_search_expression(matcher) else: return self._dumb_search(command_str) def _handle_filter_command_string(self, command_str): if self._last_filter == command_str: return 'filter unchanged ' result = self._trace_walker.set_filter(command_str) self._last_filter = command_str if result: return 'Filter set' else: return 'Error setting filter' def _seek_to_top(self): self._trace_walker.seek_to_pos(self._trace_view.get_top_position()) def _handle_command_string(self, command_str): self._last_command = (self._command_mode, command_str) self._next_redraw_record_count = self._progress_notification_record_block_size self._seek_to_top() if self._command_mode in ('search_backward', 'search_forward'): status = self._handle_search_command_string(command_str) elif self._command_mode == 'filter': status = self._handle_filter_command_string(command_str) if status: self._set_info_line(str(status)) self._command_mode = None self._trace_view.set_focus_to_top_widget() def _handle_command(self): text = self._edit_line.get_edit_text().strip() self._clear_edit_line() self._handle_command_string(text) def _do_search_input(self, direction): self._main_frame.set_focus('footer') self._command_mode = 'search_' + direction self._command_indicator.set_text(self._command_indicator_string) def _do_filter(self, new_filter = False): self._main_frame.set_focus('footer') self._command_mode = 'filter' if not new_filter: self._goto_end_of_edit_line() if self._last_filter: self._edit_line.set_edit_text(self._last_filter) self._edit_line.keypress((100,), 'end') self._command_indicator.set_text(self._command_indicator_string) def _run_command(self, command_mode, command_str): self._command_mode = command_mode self._handle_command_string(command_str) def _repeat_last_command(self): if not self._last_command: return command_mode, command_str = self._last_command self._run_command(command_mode, command_str) def _search_leave(self): command_mode = 'search_forward' command_str = 'nesting == %d and tid == %d' % (self._trace_walker.get_raw_record_at_focus().nesting, self._trace_walker.get_raw_record_at_focus().tid) self._run_command(command_mode, command_str) def _search_caller(self, input): directions = {'c' : 'forward', 'C' : 'backward'} command_mode = 'search_' + directions[input] nesting = self._trace_walker.get_raw_record_at_focus().nesting - 1 command_str = 'nesting == %d and tid == %d' % (nesting, self._trace_walker.get_raw_record_at_focus().tid) self._run_command(command_mode, command_str) def _search_error(self, input): directions = {'e' : 'forward', 'E' : 'backward'} command_mode = 'search_' + directions[input] command_str = 'severity == ERROR' self._run_command(command_mode, command_str) def _search_info(self, input): directions = {'i' : 'forward', 'I' : 'backward'} command_mode = 'search_' + directions[input] command_str = 'severity == INFO' self._run_command(command_mode, command_str) def _search_warn(self, input): directions = {'w' : 'forward', 'W' : 'backward'} command_mode = 'search_' + directions[input] command_str = 'severity == WARN' self._run_command(command_mode, command_str) def _search_debug(self, input): directions = {'d' : 'forward', 'D' : 'backward'} command_mode = 'search_' + directions[input] command_str = 'severity == DEBUG' self._run_command(command_mode, command_str) def _toggle_hex(self): self._hex = not self._hex self._trace_parser.set_always_hex(self._hex) self._seek_to_top() def _toggle_field_names(self): self._show_field_names = not self._show_field_names self._trace_parser.set_show_field_names(self._show_field_names) self._seek_to_top() def _handle_input(self, input): if input in ('q', 'Q'): raise urwid.ExitMainLoop() if input in ('s', 'S'): if input == 's': self._do_search_input('forward') elif input == 'S': self._do_search_input('backward') if input in ('f',): self._do_filter(False) if input in ('F',): self._do_filter(True) if input in ('n', 'N'): self._repeat_last_command() if input in ('e', 'E'): self._search_error(input) if input in ('d', 'D'): self._search_debug(input) if input in ('w', 'W'): self._search_warn(input) if input in ('i', 'I'): self._search_info(input) if input in ('c', 'C'): self._search_caller(input) if input in ('l'): self._search_leave() if input in ('x'): self._toggle_field_names() if input in ('o'): self._toggle_hex() if input == 'end': self._trace_walker.seek_to_end() self._trace_view.set_focus(0, 'above') if input == 'home': self._trace_walker.seek_to_start() self._trace_view.set_focus(0, 'below') if input == 'enter' and self._main_frame.get_focus() == 'footer': self._handle_command() self._main_frame.set_focus('body') self._trace_view.set_focus_to_top_widget() self._trace_view.set_focus_valign('top') def _cancel_pending_commands(self): if self._command_mode: self._cancel_operation = True self._set_info_line('Cancelled') self._clear_edit_line() self._main_frame.set_focus('body') def _handle_keyboard_interrupt(self): self._cancel_pending_commands() def _handle_sigint(self, signal, frame): self._handle_keyboard_interrupt() def run(self, filename): signal.signal(signal.SIGINT, self._handle_sigint) self.loop = urwid.MainLoop(self._main_frame, AnsiText.get_palette() + palette, handle_mouse = False, unhandled_input=self._handle_input) self.open_file(filename) self.loop.run()
class TraceReaderUI(object): _footer_text = [ ('title', "Trace reader " + __version__), " ", ] def __init__(self): self._trace_walker = TraceWalker() self._trace_view = urwid.ListBox(self._trace_walker) self._edit_line = AdvancedEdit() self._info_line = urwid.Text('') self._footer = AnsiText(self._footer_text) self._command_indicator = urwid.Text('') self._command_indicator_string = '--> ' self._command_mode = None self._last_command = None self._last_filter = '' self._debug_enabled = True footer_columns = urwid.AttrMap(urwid.Columns([self._footer, self._info_line]), 'foot') wrapped_edit_line = urwid.Columns([('fixed', len(self._command_indicator_string), self._command_indicator), self._edit_line]) footer = urwid.Pile([footer_columns, wrapped_edit_line]) self._main_frame = urwid.Frame(urwid.AttrWrap(self._trace_view, 'body'), footer = footer) def open_file(self, filename): self._trace_parser = TraceParser(filename) self._trace_parser.set_color(True) self._trace_parser.set_relative_ts(False) self._trace_parser.set_indent(True) self._trace_walker.set_parser(self._trace_parser) self._trace_walker.reread() self._footer.set_text(self._footer_text + [' ', filename]) self._edit_line.set_completer(MultipleSelectionCompleter(StringlistCompleter(self._trace_walker.get_completion_names()))) def _clear_edit_line(self): self._edit_line.set_edit_text('') self._command_indicator.set_text('') def _dumb_search(self, search_string): i = 0 _, pos = self._trace_walker.get_focus() while True: record, _ = self._trace_walker.get_next(pos + i) i += 1 if not record: return 'expression not found' if search_string in record.get_text()[0]: self._trace_view.set_focus_valign('top') self._trace_view.set_focus(pos + i) # TODO: Add timing information return 'found record' def _set_info_line(self, text): self._info_line.set_text(text) def _goto_end_of_edit_line(self): self._edit_line.edit_pos = 5 def _handle_search_expression(self, matcher): start_time = time.time() result = self._trace_walker.find_next_by_expression(matcher) end_time = time.time() search_time = end_time - start_time if result: result = 'search succeeded after %f seconds' % (search_time,) else: result = 'search failed after %f seconds' % (search_time,) self._trace_view.set_focus(0) self._trace_view.set_focus_valign('top') return result def _handle_search_command_string(self, command_str): matcher = self._trace_walker.get_matcher_from_string(command_str) if command_str == 'focus': return self._trace_walker.get_focus() result = self._trace_walker.seek_to_time(command_str) if result: return result elif matcher: return self._handle_search_expression(matcher) else: return self._dumb_search(command_str) def _handle_filter_command_string(self, command_str): result = self._trace_walker.set_filter(command_str) if result: return 'Filter set' else: return 'Error setting filter' def _handle_command_string(self, command_str): self._last_command = (self._command_mode, command_str) if self._command_mode == 'search': status = self._handle_search_command_string(command_str) elif self._command_mode == 'filter': self._last_filter = command_str status = self._handle_filter_command_string(command_str) self._set_info_line(str(status)) self._command_mode = None def _handle_command(self): text = self._edit_line.get_edit_text().strip() self._clear_edit_line() self._handle_command_string(text) def _do_search_input(self): self._main_frame.set_focus('footer') self._command_mode = 'search' self._command_indicator.set_text(self._command_indicator_string) def _do_debug_enabled(self): self._debug_enabled = not self._debug_enabled self._trace_walker.set_indent(self._debug_enabled) self._trace_walker.enable_debug(self._debug_enabled) def _do_filter(self, new_filter = False): self._main_frame.set_focus('footer') self._command_mode = 'filter' if not new_filter: self._goto_end_of_edit_line() self._edit_line.set_edit_text(self._last_filter) self._edit_line.keypress((100,), 'end') self._command_indicator.set_text(self._command_indicator_string) def _repeat_last_command(self): if not self._last_command: return command_mode, command_str = self._last_command self._command_mode = command_mode self._handle_command_string(command_str) def _handle_input(self, input): if input in ('q', 'Q'): raise urwid.ExitMainLoop() if input in ('s', 'S'): self._do_search_input() if input in ('f',): self._do_filter(False) if input in ('F',): self._do_filter(True) if input in ('n', 'N'): self._repeat_last_command() if input in ('c', 'C'): import code code.interact(local = locals()) if input == 'end': self._trace_walker.seek_to_end() self._trace_view.set_focus(0, 'above') if input == 'home': self._info_line.set_text(str(self._trace_walker.seek_to_start())) self._trace_view.set_focus(0, 'below') if input == 'enter' and self._main_frame.get_focus() == 'footer': self._handle_command() self._main_frame.set_focus('body') def _cancel_pending_commands(self): if self._command_mode: self._set_info_line('user cancelled search') self._clear_edit_line() self._main_frame.set_focus('body') def _handle_keyboard_interrupt(self): self._cancel_pending_commands() def run(self, filename): self.loop = urwid.MainLoop(self._main_frame, AnsiText.get_palette() + palette, handle_mouse = False, unhandled_input=self._handle_input) self.open_file(filename) while True: try: self.loop.run() break except KeyboardInterrupt: self._handle_keyboard_interrupt()
class TraceReaderUI(object): _footer_text = [("title", "Trace reader " + __version__), " "] def __init__(self): self._trace_walker = TraceWalker() self._trace_view = AlwaysOnTopListBox(self._trace_walker) self._edit_line = AdvancedEdit() self._info_line = urwid.Text("") self._footer = AnsiText(self._footer_text) self._command_indicator = urwid.Text("") self._command_indicator_string = "--> " self._command_mode = None self._last_command = None self._last_filter = None self._hex = False self._show_field_names = False self._cancel_operation = False self._progress_notification_record_multiple = 0 footer_columns = urwid.AttrMap(urwid.Columns([self._footer, self._info_line]), "foot") wrapped_edit_line = urwid.Columns( [("fixed", len(self._command_indicator_string), self._command_indicator), self._edit_line] ) footer = urwid.Pile([footer_columns, wrapped_edit_line]) self._main_frame = urwid.Frame(urwid.AttrWrap(self._trace_view, "body"), footer=footer) def _metadata_updated_handler(self): self._edit_line.set_completer( MultipleSelectionCompleter(StringlistCompleter(self._trace_walker.get_completion_names())) ) def _get_progress_line(self, records_processed, current_offset): if not self._command_mode: return None if "forward" in self._command_mode or "filter" in self._command_mode: end_offset = self._trace_parser.end_offset else: end_offset = 0 remaining_records_to_process = abs(current_offset - end_offset) remaining_percent = remaining_records_to_process / (self._trace_parser.end_offset / 100) return "%d%% remaining to process" % (remaining_percent,) def _parser_event_handler(self, event, **kw): if event == "metadata_updated": self._metadata_updated_handler() if event == "operation_in_progress": records_processed = kw["records_processed"] current_offset = kw["current_offset"] if records_processed >= self._next_redraw_record_count: progress_line = self._get_progress_line(records_processed, current_offset) if progress_line: self._info_line.set_text(progress_line) self.loop.draw_screen() self._next_redraw_record_count += self._progress_notification_record_block_size if self._cancel_operation: self._trace_parser.cancel_ongoing_operation() self._cancel_operation = False if event == "interrupted": self._cancel_operation = True def open_file(self, filename): self._trace_parser = TraceParser(filename, self._parser_event_handler) self._progress_notification_record_block_size = self._trace_parser.end_offset / 10 self._next_redraw_record_count = self._progress_notification_record_block_size self._trace_parser.set_color(True) self._trace_parser.set_relative_ts(False) self._trace_parser.set_indent(True) self._trace_parser.set_show_field_names(False) self._trace_walker.set_parser(self._trace_parser) self._trace_walker.reread() self._footer.set_text(self._footer_text + [" ", filename]) self._edit_line.set_completer( MultipleSelectionCompleter(StringlistCompleter(self._trace_walker.get_completion_names())) ) def _clear_edit_line(self): self._edit_line.set_edit_text("") self._command_indicator.set_text("") def _dumb_search(self, search_string): i = 0 _, pos = self._trace_walker.get_focus() if "forward" in self._command_mode: walker = self._trace_walker.get_next op = operator.add else: walker = self._trace_walker.get_prev op = operator.sub while not self._cancel_operation: record, _ = walker(op(pos, i)) i += 1 if not record: return "expression not found" record_text = record.get_text()[0] if record_text.find(str(search_string)) != -1: break def _set_info_line(self, text): self._info_line.set_text(text) def _goto_end_of_edit_line(self): self._edit_line.edit_pos = 5 def _handle_search_expression(self, matcher): start_time = time.time() _, pos = self._trace_view.get_focus() if self._command_mode == "search_forward": result = self._trace_walker.find_next_by_expression(matcher) self._trace_view.set_focus(0, "above") else: self._trace_walker.get_prev(pos) result = self._trace_walker.find_previous_by_expression(matcher) self._trace_view.set_focus(0, "below") end_time = time.time() search_time = end_time - start_time if result: result = "search succeeded after %f seconds" % (search_time,) else: result = "search failed after %f seconds" % (search_time,) return result def _handle_search_command_string(self, command_str): self._cancel_operation = False matcher = self._trace_walker.get_matcher_from_string(command_str) if command_str == "focus": return self._trace_walker.get_focus() result = self._trace_walker.seek_to_time(command_str) if result: return result elif matcher: return self._handle_search_expression(matcher) else: return self._dumb_search(command_str) def set_filter(self, filter): result = self._trace_walker.set_filter(filter) if not result: raise InvalidFilter(filter) def _handle_filter_command_string(self, command_str): if self._last_filter == command_str: return "filter unchanged " result = self._trace_walker.set_filter(command_str) self._last_filter = command_str if result: return "Filter set" else: return "Error setting filter" def _seek_to_top(self): self._trace_walker.seek_to_pos(self._trace_view.get_top_position()) def _handle_command_string(self, command_str): self._last_command = (self._command_mode, command_str) self._next_redraw_record_count = self._progress_notification_record_block_size self._seek_to_top() if self._command_mode in ("search_backward", "search_forward"): status = self._handle_search_command_string(command_str) elif self._command_mode == "filter": status = self._handle_filter_command_string(command_str) if status: self._set_info_line(str(status)) self._command_mode = None self._trace_view.set_focus_to_top_widget() def _handle_command(self): text = self._edit_line.get_edit_text().strip() self._clear_edit_line() self._handle_command_string(text) def _do_search_input(self, direction): self._main_frame.set_focus("footer") self._command_mode = "search_" + direction self._command_indicator.set_text(self._command_indicator_string) def _do_filter(self, new_filter=False): self._main_frame.set_focus("footer") self._command_mode = "filter" if not new_filter: self._goto_end_of_edit_line() if self._last_filter: self._edit_line.set_edit_text(self._last_filter) self._edit_line.keypress((100,), "end") self._command_indicator.set_text(self._command_indicator_string) def _run_command(self, command_mode, command_str): self._command_mode = command_mode self._handle_command_string(command_str) def _repeat_last_command(self): if not self._last_command: return command_mode, command_str = self._last_command self._run_command(command_mode, command_str) def _search_leave(self): command_mode = "search_forward" command_str = "nesting == %d and tid == %d" % ( self._trace_walker.get_raw_record_at_focus().nesting, self._trace_walker.get_raw_record_at_focus().tid, ) self._run_command(command_mode, command_str) def _search_caller(self, input): directions = {"c": "forward", "C": "backward"} command_mode = "search_" + directions[input] nesting = self._trace_walker.get_raw_record_at_focus().nesting - 1 command_str = "nesting == %d and tid == %d" % (nesting, self._trace_walker.get_raw_record_at_focus().tid) self._run_command(command_mode, command_str) def _search_error(self, input): directions = {"e": "forward", "E": "backward"} command_mode = "search_" + directions[input] command_str = "severity == ERROR" self._run_command(command_mode, command_str) def _search_info(self, input): directions = {"i": "forward", "I": "backward"} command_mode = "search_" + directions[input] command_str = "severity == INFO" self._run_command(command_mode, command_str) def _search_warn(self, input): directions = {"w": "forward", "W": "backward"} command_mode = "search_" + directions[input] command_str = "severity == WARN" self._run_command(command_mode, command_str) def _search_debug(self, input): directions = {"d": "forward", "D": "backward"} command_mode = "search_" + directions[input] command_str = "severity == DEBUG" self._run_command(command_mode, command_str) def _toggle_hex(self): self._hex = not self._hex self._trace_parser.set_always_hex(self._hex) self._seek_to_top() def _toggle_field_names(self): self._show_field_names = not self._show_field_names self._trace_parser.set_show_field_names(self._show_field_names) self._seek_to_top() def _handle_input(self, input): if input in ("q", "Q"): raise urwid.ExitMainLoop() if input in ("s", "S"): if input == "s": self._do_search_input("forward") elif input == "S": self._do_search_input("backward") if input in ("f",): self._do_filter(False) if input in ("F",): self._do_filter(True) if input in ("n", "N"): self._repeat_last_command() if input in ("e", "E"): self._search_error(input) if input in ("d", "D"): self._search_debug(input) if input in ("w", "W"): self._search_warn(input) if input in ("i", "I"): self._search_info(input) if input in ("c", "C"): self._search_caller(input) if input in ("l"): self._search_leave() if input in ("x"): self._toggle_field_names() if input in ("o"): self._toggle_hex() if input in ("t"): self._seek_to_top() if input == "end": self._trace_walker.seek_to_end() self._trace_view.set_focus(0, "above") if input == "home": self._trace_walker.seek_to_start() self._trace_view.set_focus(0, "below") if input == "enter" and self._main_frame.get_focus() == "footer": self._handle_command() self._main_frame.set_focus("body") def _cancel_pending_commands(self): if self._command_mode: self._cancel_operation = True self._set_info_line("Cancelled") self._clear_edit_line() self._main_frame.set_focus("body") def _handle_keyboard_interrupt(self): self._cancel_pending_commands() def _handle_sigint(self, signal, frame): self._handle_keyboard_interrupt() def run(self, filename, initial_filter=None): signal.signal(signal.SIGINT, self._handle_sigint) self.loop = urwid.MainLoop( self._main_frame, AnsiText.get_palette() + palette, handle_mouse=False, unhandled_input=self._handle_input ) self.open_file(filename) if initial_filter: self.set_filter(initial_filter) self.loop.run() def _exit_on_signal(self, signal): sys.exit(1) def dump(self, filename, initial_filter=None): self.open_file(filename) if initial_filter: print "kaka" self.set_filter(initial_filter) signal.signal(signal.SIGINT, signal.SIG_DFL) self._trace_parser.dump_file()