def follow_log(self): """Reads a logfile continuously and updates internal graph if new step is found""" # Server needs to be up and running before starting sending POST requests time.sleep(5) try: if self.remote: logger.debug('Logfile in remote host!') cl = client.SSHClient() # Try to load system keys cl.load_system_host_keys() cl.connect(self.remote['host'], port=self.remote.get('port', 22), username=self.remote.get('username', None), \ password=self.remote.get('password', None)) sftp = cl.open_sftp() f = sftp.open(self.logfile, 'r') else: f = open(self.logfile, 'r') except IOError: raise RuntimeError("Provided logfile does not exist or its not readable") self.analysis_finished = False last_line_read = False while not self.analysis_finished: line = f.readline() if not line: if not last_line_read: self.update_frontend({'finished_reading': True}) if self.update: self.update_frontend(self._last_message) last_line_read = True time.sleep(1) continue parsed_line = ps.parse_log_line(line) self._last_message = parsed_line self.analysis_finished = (parsed_line['step'] == 'finished') or (parsed_line['step'] == 'error') # If this is a new step, update internal data if parsed_line['step'] and not parsed_line['step'] == 'error': logger.debug('New step \"{}\" detected'.format(parsed_line['step'])) self._steps.append(parsed_line) node_id = '_'.join(parsed_line['step'].lower().split()) self.node(node_id, parsed_line['step']) self._nodes.append(node_id) n_nodes = len(self._nodes) if n_nodes > 1: self.edge(self._nodes[n_nodes - 2], self._nodes[n_nodes -1]) # Update frontend only if its a new step _or_ the update flag is set to true and we are # not loading the log for the first time if (last_line_read and self.update) or parsed_line['step']: self.update_frontend(parsed_line) f.close()
def follow_log(self): """Reads a logfile continuously and updates internal graph if new step is found""" # Server needs to be up and running before starting sending POST requests time.sleep(5) try: if self.remote: logger.debug('Logfile in remote host!') cl = client.SSHClient() # Try to load system keys cl.load_system_host_keys() cl.connect(self.remote['host'], port=self.remote.get('port', 22), username=self.remote.get('username', None), \ password=self.remote.get('password', None)) sftp = cl.open_sftp() f = sftp.open(self.logfile, 'r') f.settimeout(5) # Set 5 seconds timeout for read operations else: f = open(self.logfile, 'r') except IOError: raise RuntimeError("Provided logfile does not exist or its not readable") self.analysis_finished = False last_line_read = False while not self.analysis_finished: try: line = f.readline() except timeout: logger.error("Connection with the server lost, trying to reconnect and continue reading") current_pos = f.tell() try: cl.connect(self.remote['host'], port=self.remote.get('port', 22), username=self.remote.get('username', None), \ password=self.remote.get('password', None), timeout=300, banner_timeout=300) except error: logger.error("Couldn't connect to the server after 5 minutes, aborting.") os._exit(0) else: logger.info("Connection restablished!! Will continue reading the logfile") sftp = cl.open_sftp() f = sftp.open(self.logfile, 'r') f.seek(current_pos) else: if not line: self.finished_reading = True if not last_line_read: self.update_frontend({'finished_reading': True}) if self.update: self.update_frontend(self._last_message) last_line_read = True time.sleep(1) continue parsed_line = ps.parse_log_line(line) self._last_message = parsed_line self.analysis_finished = parsed_line['step'] == 'finished' # If this is a new step, update internal data parsed_line['new_run'] = False if parsed_line['step'] and not parsed_line['step'] == 'error': if self.FIRST_STEP is None: self.FIRST_STEP = parsed_line['step'] elif parsed_line['step'] == self.FIRST_STEP: parsed_line['new_run'] = True self.new_run() node_id = 'run-{}_'.format(self.current_run + 1) + '_'.join(parsed_line['step'].lower().split()) parsed_line['step_id'] = node_id self.runs[self.current_run].steps.append(parsed_line) self.runs[self.current_run].node(node_id, parsed_line['step']) self.runs[self.current_run]._nodes.append(node_id) n_nodes = len(self.runs[self.current_run]._nodes) if n_nodes > 1: self.runs[self.current_run].edge(self.runs[self.current_run]._nodes[n_nodes - 2], self.runs[self.current_run]._nodes[n_nodes -1]) parsed_line['graph_source'] = self.runs[self.current_run].source elif parsed_line['step'] == 'error': self.runs[self.current_run].errored = True # Update frontend only if its a new step _or_ the update flag is set to true and we are # not loading the log for the first time if (last_line_read and self.update) or parsed_line['step']: self.update_frontend(parsed_line) f.close()