def get_stats_string(t_start, t_end, total_times, intervals_of_statuses, hostname, num_entries_found, print_each_interval): """Returns string reporting host_history for this host. @param t_start: beginning of time period we are interested in. @param t_end: end of time period we are interested in. @param total_times: dictionary where key=status, value=(time spent in that status) @param intervals_of_statuses: dictionary where keys is tuple (ti, tf), and value is the status along with other metadata. @param hostname: hostname for the host we are interested in (string) @param num_entries_found: Number of entries found for the host in es @param print_each_interval: boolean, whether to print each interval """ delta = t_end - t_start result = 'usage stats for host: %s \n' % (hostname) result += ' %s - %s \n' % (time_utils.epoch_time_to_date_string(t_start), time_utils.epoch_time_to_date_string(t_end)) result += ' Num entries found in this interval: %s\n' % (num_entries_found) for status, value in total_times.iteritems(): spaces = (15 - len(status)) * ' ' result += ' %s: %s %.2f %%\n' % (status, spaces, 100 * value / delta) result += '- -- --- ---- ----- ---- --- -- -\n' if print_each_interval: for interval, status_info in intervals_of_statuses.iteritems(): t0, t1 = interval t0_string = time_utils.epoch_time_to_date_string(t0) t1_string = time_utils.epoch_time_to_date_string(t1) status = status_info['status'] delta = int(t1 - t0) id_info = status_info['metadata'].get( 'task_id', status_info['metadata'].get('job_id', '')) result += (' %s : %s %-15s %-10s %ss\n' % (t0_string, t1_string, status, id_info, delta)) return result
def main(): """main script. """ t_now = time.time() t_now_minus_one_day = t_now - 3600*24 parser = argparse.ArgumentParser() parser.add_argument('-l', type=int, dest='last', help='last days to summary test results across', default=None) parser.add_argument('--start', type=str, dest='start', help=('Enter start time as: yyyy-mm-dd hh:mm:ss,' 'defualts to 24h ago.'), default=time_utils.epoch_time_to_date_string( t_now_minus_one_day)) parser.add_argument('--end', type=str, dest='end', help=('Enter end time in as: yyyy-mm-dd hh:mm:ss,' 'defualts to current time.'), default=time_utils.epoch_time_to_date_string(t_now)) parser.add_argument('-t', type=int, dest='top', help='Print the top x of large result folders.', default=0) parser.add_argument('-r', action='store_true', dest='report_stat', default=False, help='True to report total size to statsd.') options = parser.parse_args() if options.last: start_time = t_now - 3600*24*options.last end_time = t_now else: start_time = time_utils.to_epoch_time(options.start) end_time = time_utils.to_epoch_time(options.end) get_summary(start_time=start_time, end_time=end_time, top=options.top, report_stat=options.report_stat)
def get_stats_string_aggregate(labels, t_start, t_end, aggregated_stats, num_hosts): """Returns string reporting overall host history for a group of hosts. @param labels: A list of labels useful for describing the group of hosts these overall stats represent. @param t_start: beginning of time period we are interested in. @param t_end: end of time period we are interested in. @param aggregated_stats: A dictionary where keys are string, e.g. 'status' value is total time spent in that status among all hosts. @returns: string representing the aggregate stats report. """ result = 'Overall stats for hosts: %s \n' % (', '.join(labels)) result += ' %s - %s \n' % (time_utils.epoch_time_to_date_string(t_start), time_utils.epoch_time_to_date_string(t_end)) result += ' Number of total hosts: %s \n' % (num_hosts) # This is multiplied by time_spent to get percentage_spent multiplication_factor = 100.0 / ((t_end - t_start) * num_hosts) for status, time_spent in aggregated_stats.iteritems(): # Normalize by the total time we are interested in among ALL hosts. spaces = ' ' * (15 - len(status)) percent_spent = multiplication_factor * time_spent result += ' %s: %s %.2f %%\n' % (status, spaces, percent_spent) result += '- -- --- ---- ----- ---- --- -- -\n' return result
def get_results_string(hostname, time_start, time_end, results): """Prints entries from esdb in a readable fashion. @param hostname: Hostname of DUT we are printing result for. @param time_start: Earliest time entry was recorded @param time_end: Latest time entry was recorded @param gte: Lowest reboot_time to return @param lte: Highest reboot_time to return @param size: Max number of entries to return @returns: String reporting reboot times for this host. """ return_string = ' Host: %s \n Number of entries: %s \n' % (hostname, results.total) return_string += ' %s - %s \n' % (time_utils.epoch_time_to_date_string( time_start), time_utils.epoch_time_to_date_string(time_end)) if results.total <= 0: return return_string for result in results.hits: time_recorded = result['time_recorded'][0] time_string = time_utils.epoch_time_to_date_string(time_recorded) reboot_total = result['value'][0] spaces = (15 - len(str(time_string))) * ' ' return_string += ' %s Reboot_time: %.3fs\n' % (time_string, reboot_total) return return_string
def get_hqes(cls, afe, host_id, start_time, end_time): """Return HQEs for a host in a given time range. Return a list of `_TestJobEvent` objects representing all the HQEs of all the jobs that ran on the given host in the given time range. The list is ordered as it was returned by the query (i.e. unordered). @param afe Autotest frontend @param host_id Database host id of the desired host. @param start_time Start time of the range of interest. @param end_time End time of the range of interest. @return A list of `_TestJobEvent` objects. """ query_start = time_utils.epoch_time_to_date_string(start_time) query_end = time_utils.epoch_time_to_date_string(end_time) hqelist = afe.get_host_queue_entries_by_insert_time( host_id=host_id, insert_time_after=query_start, insert_time_before=query_end, started_on__gte=query_start, started_on__lte=query_end, complete=1) return [cls(afe.server, hqe) for hqe in hqelist]
def analyze_suites(start_time, end_time): """ Calculates timing stats (i.e., suite runtime, scheduling overhead) for the suites that finished within the timestamps given by parameters. @param start_time: Beginning timestamp. @param end_time: Ending timestamp. """ print('Analyzing suites from %s to %s...' % (time_utils.epoch_time_to_date_string(start_time), time_utils.epoch_time_to_date_string(end_time))) if _options.bvtonly: batch_constraints = [('suite_name', ['bvt-inline', 'bvt-cq', 'bvt-perbuild'])] else: batch_constraints = [] start_time_epoch = time_utils.to_epoch_time(start_time) end_time_epoch = time_utils.to_epoch_time(end_time) results = autotest_es.query(fields_returned=[ 'suite_name', 'suite_job_id', 'board', 'build', 'num_child_jobs', 'duration' ], equality_constraints=[ ('_type', job_overhead.SUITE_RUNTIME_KEY), ], range_constraints=[ ('time_recorded', start_time_epoch, end_time_epoch) ], sort_specs=[{ 'time_recorded': 'asc' }], batch_constraints=batch_constraints) print('Found %d suites' % (results.total)) for hit in results.hits: suite_job_id = hit['suite_job_id'] try: suite_name = hit['suite_name'] num_child_jobs = int(hit['num_child_jobs']) suite_runtime = float(hit['duration']) print('Suite: %s (%s), Board: %s, Build: %s, Num child jobs: %d' % (suite_name, suite_job_id, hit['board'], hit['build'], num_child_jobs)) suite_stats = get_scheduling_overhead(suite_job_id, num_child_jobs) print('Suite: %s (%s) runtime: %f,' % (suite_name, suite_job_id, suite_runtime)), print_suite_stats(suite_stats) except Exception as e: print('ERROR: Exception is raised while processing suite %s' % (suite_job_id)) print e
def test_start_and_end(self): """Test time bounds with --since and --until.""" start_time = int(self.test_time) - 5 * 3600 start_time_string = time_utils.epoch_time_to_date_string(start_time) end_time = start_time + 4 * 3600 end_time_string = time_utils.epoch_time_to_date_string(end_time) arguments = self._try_parse( ['-s', start_time_string, '-u', end_time_string]) self.assertEqual(arguments.since, start_time) self.assertEqual(arguments.until, end_time)
def test_start_and_end(self): """Test time bounds with --since and --until.""" start_time = int(time.time()) - 5 * 3600 start_time_string = time_utils.epoch_time_to_date_string(start_time) end_time = start_time + 4 * 3600 end_time_string = time_utils.epoch_time_to_date_string(end_time) arguments = self._try_parse( ['--s', start_time_string, '--u', end_time_string]) assert arguments.since == start_time assert arguments.until == end_time
def test_all_options(self): """Test that all three options are a fatal error.""" start_time = int(self.test_time) - 5 * 3600 start_time_string = time_utils.epoch_time_to_date_string(start_time) duration = 4 duration_string = '%d' % duration end_time = start_time + duration * 3600 end_time_string = time_utils.epoch_time_to_date_string(end_time) with self.assertRaises(SystemExit): self._try_parse([ '-s', start_time_string, '-u', end_time_string, '-d', duration_string ])
def main(): """main script. """ parser = argparse.ArgumentParser() parser.add_argument( '--span', type=int, dest='span', default=1, help=('Number of hours that stats should be collected. ' 'If it is set to 24, the end time of stats being ' 'collected will set to the mid of the night. ' 'Default is set to 1 hour.')) parser.add_argument('-e', '--email', dest='email', default=None, help='Email any errors to the given email address.') options = parser.parse_args() boards = host_label_utils.get_all_boards() pools = ['bvt', 'suites', 'cq'] if options.span == 24: today = datetime.combine(date.today(), datetime.min.time()) end_time = time_utils.to_epoch_time(today) else: now = datetime.now() end_time = datetime(year=now.year, month=now.month, day=now.day, hour=now.hour) end_time = time_utils.to_epoch_time(end_time) start_time = end_time - timedelta(hours=options.span).total_seconds() print('Collecting host stats from %s to %s...' % (time_utils.epoch_time_to_date_string(start_time), time_utils.epoch_time_to_date_string(end_time))) errors = [] if not boards: errors.append('Error! No board found in metadb.') for board in boards: for pool in pools: error = report_stats(board, pool, start_time, end_time, options.span) if error: errors.append(error) if options.email and errors: gmail_lib.send_email(options.email, 'Error occured when collecting host stats.', '\n'.join(errors))
def get_host_labels(days_back=0, hostname=None, labels=None): """Get the labels for a given host or all hosts. @param days_back: Get the label info around that number of days back. The default is 0, i.e., the latest label information. @param hostname: Name of the host, if set to None, return labels for all hosts. Default is None. @param labels: A list of labels to filter hosts. @return: A dictionary of host labels, key is the hostname, and value is a list of labels, e.g., {'host1': ['board:daisy', 'pool:bvt']} """ # Search for the latest logged labels before the given days_back. # Default is 0, which means the last time host labels were logged. t_end = time.time() - days_back*24*3600 results = autotest_es.query( fields_returned=['time_index'], equality_constraints=[('_type', _HOST_LABEL_TIME_INDEX_TYPE),], range_constraints=[('time_index', None, t_end)], size=1, sort_specs=[{'time_index': 'desc'}]) t_end_str = time_utils.epoch_time_to_date_string(t_end) if results.total == 0: logging.error('No label information was logged before %s.', t_end_str) return time_index = results.hits[0]['time_index'] logging.info('Host labels were recorded at %s', time_utils.epoch_time_to_date_string(time_index)) # Search for labels for a given host or all hosts, at time_index. equality_constraints=[('_type', _HOST_LABEL_TYPE), ('time_index', time_index),] if hostname: equality_constraints.append(('hostname', hostname)) if labels: for label in labels: equality_constraints.append(('labels', label)) results = autotest_es.query( fields_returned=['hostname', 'labels'], equality_constraints=equality_constraints) host_labels = {} for hit in results.hits: if 'labels' in hit: host_labels[hit['hostname']] = hit['labels'] return host_labels
def test_start_and_duration(self): """Test time bounds with --since and --duration.""" start_time = int(self.test_time) - 5 * 3600 start_time_string = time_utils.epoch_time_to_date_string(start_time) duration = 4 duration_string = '%d' % duration arguments = self._try_parse( ['-s', start_time_string, '-d', duration_string]) self.assertEqual(arguments.since, start_time) self._check_duration(arguments, duration)
def __init__(self, hit): """Retrieve information from a ES query hit. """ self.devserver = hit['devserver'] self.subname = hit['subname'] self.artifacts = hit['artifacts'].split(' ') self.image = hit['image'] self.value = hit['value'] self.time_recorded = time_utils.epoch_time_to_date_string( hit['time_recorded'])
def test_end_and_duration(self): """Test time bounds with --until and --duration.""" end_time = int(self.test_time) - 5 * 3600 end_time_string = time_utils.epoch_time_to_date_string(end_time) duration = 4 duration_string = '%d' % duration arguments = self._try_parse( ['-u', end_time_string, '-d', duration_string]) self.assertEqual(arguments.until, end_time) self._check_duration(arguments, duration)
def test_end_only(self): """Test time bounds with --until only. Also tests that --until and -u are equivalent. """ end_time = int(self.test_time) - 3600 end_time_string = time_utils.epoch_time_to_date_string(end_time) for option in ['--until', '-u']: arguments = self._try_parse([option, end_time_string]) self.assertEqual(arguments.until, end_time) self._check_duration(arguments, dut_status._DEFAULT_DURATION)
def test_start_only(self): """Test time bounds with --since only. Also tests that --since and -s are equivalent. """ end_time = int(self.test_time) start_time = end_time - 3600 start_time_string = time_utils.epoch_time_to_date_string(start_time) for option in ['--since', '-s']: arguments = self._try_parse([option, start_time_string]) self.assertEqual(arguments.until, end_time) self.assertEqual(arguments.since, start_time)
def build_history(hostname, status_intervals): """Get host history information from given state intervals. @param hostname: Hostname of the dut. @param status_intervals: A ordered dictionary with key as (t_start, t_end) and value as (status, metadata) status = status of the host. e.g. 'Repair Failed' t_start is the beginning of the interval where the DUT's has that status t_end is the end of the interval where the DUT has that status metadata: A dictionary of other metadata, e.g., {'task_id':123, 'task_name':'Reset'} @return: A list of host history, e.g., [{'status': 'Resetting' 'start_time': '2014-08-07 10:02:16', 'end_time': '2014-08-07 10:03:16', 'log_url': 'http://autotest/reset-546546/debug', 'task_id': 546546}, {'status': 'Running' 'start_time': '2014-08-07 10:03:18', 'end_time': '2014-08-07 10:13:00', 'log_url': 'http://autotest/afe/#tab_id=view_job&object_id=1683', 'job_id': 1683} ] """ history = [] for time_interval, status_info in status_intervals.items(): start_time = time_utils.epoch_time_to_date_string(time_interval[0]) end_time = time_utils.epoch_time_to_date_string(time_interval[1]) interval = { 'status': status_info['status'], 'start_time': start_time, 'end_time': end_time } interval['log_url'] = get_log_url(hostname, status_info['metadata']) interval.update(status_info['metadata']) history.append(interval) return history
def diagnose_pool(self, board, pool, time_delta_hours, limit=10): """Log diagnostic information about a timeout for a board/pool. @param board: The board for which the current suite was run. @param pool: The pool against which the current suite was run. @param time_delta_hours: The time from which we should log information. This is a datetime.timedelta object, as stored by the JobTimer. @param limit: The maximum number of jobs per host, to log. @raises proxy.JSONRPCException: For exceptions thrown across the wire. """ end_time = datetime.now() start_time = end_time - time_delta_hours labels = labellib.LabelsMapping() labels['board'] = board labels['pool'] = pool host_histories = status_history.HostJobHistory.get_multiple_histories( self.rpc_interface, time_utils.to_epoch_time(start_time), time_utils.to_epoch_time(end_time), labels.getlabels(), ) if not host_histories: logging.error('No hosts found for board:%s in pool:%s', board, pool) return status_map = { status_history.UNUSED: 'Unused', status_history.UNKNOWN: 'No job history', status_history.WORKING: 'Working', status_history.BROKEN: 'Failed repair' } for history in host_histories: count = 0 job_info = '' for job in history: start_time = (time_utils.epoch_time_to_date_string( job.start_time)) job_info += ('%s %s started on: %s status %s\n' % (job.id, job.name, start_time, job.job_status)) count += 1 if count >= limit: break host = history.host logging.error( 'host: %s, status: %s, locked: %s ' 'diagnosis: %s\n' 'labels: %s\nLast %s jobs within %s:\n' '%s', history.hostname, host.status, host.locked, status_map[history.last_diagnosis()[0]], host.labels, limit, time_delta_hours, job_info)
def test_start_only(self): """Test time bounds with --since only. Also tests that --since and -s are equivalent. """ for option in ['--since', '-s']: end_time = int(time.time()) start_time = end_time - 3600 start_time_string = time_utils.epoch_time_to_date_string( start_time) arguments = self._try_parse([option, start_time_string]) self._check_default_end(arguments, end_time) assert arguments.since == start_time
def get_tasks(cls, afe, host_id, start_time, end_time): """Return special tasks for a host in a given time range. Return a list of `_SpecialTaskEvent` objects representing all special tasks that ran on the given host in the given time range. The list is ordered as it was returned by the query (i.e. unordered). @param afe Autotest frontend @param host_id Database host id of the desired host. @param start_time Start time of the range of interest. @param end_time End time of the range of interest. @return A list of `_SpecialTaskEvent` objects. """ query_start = time_utils.epoch_time_to_date_string(start_time) query_end = time_utils.epoch_time_to_date_string(end_time) tasks = afe.get_host_special_tasks(host_id, time_started__gte=query_start, time_finished__lte=query_end, is_complete=1) return [cls(afe.server, t) for t in tasks]
def _init_status_interval(self): """Fill in `self._status_interval`.""" if self._status_interval is not None: return self._init_status_task() self._status_interval = [] if self._status_task is None: return query_end = time_utils.epoch_time_to_date_string(self.end_time) interval = self._afe.get_host_diagnosis_interval( self._host.id, query_end, self._status_diagnosis != WORKING) if not interval: return self._status_interval = self._get_history(parse_time(interval[0]), parse_time(interval[1]))
def get_status_task(cls, afe, host_id, end_time): """Return the task indicating a host's status at a given time. The task returned determines the status of the DUT; the diagnosis on the task indicates the diagnosis for the DUT at the given `end_time`. @param afe Autotest frontend @param host_id Database host id of the desired host. @param end_time Find status as of this time. @return A `_SpecialTaskEvent` object for the requested task, or `None` if no task was found. """ query_end = time_utils.epoch_time_to_date_string(end_time) task = afe.get_host_status_task(host_id, query_end) return cls(afe.server, task) if task else None
def get_timestamp_if_finished(self): """Get the timestamp to use for finished jobs. @returns the latest hqe finished_on time. If the finished_on times are null returns the job's created_on time. """ marker_path = os.path.join(self.dirname, _OFFLOAD_MARKER) try: with open(marker_path) as f: ts_string = f.read().strip() except (OSError, IOError) as e: return None try: ts = int(ts_string) return time_utils.epoch_time_to_date_string(ts) except ValueError as e: logging.debug('Error parsing %s for %s: %s', _OFFLOAD_MARKER, self.dirname, e) _marker_parse_error_metric.increment() return None
def generate_status(self): """Generate status logs. 3 important status logs are required for successful parsing: test_name/status - core test status results_dir/status - server job status (has test status in it) status.log - compiled final status log """ current_timestamp = int(time.time()) test_info = { 'test_name': self.test_name, 'timestamp': current_timestamp, 'date': time_utils.epoch_time_to_date_string(current_timestamp, fmt_string='%b %d %H:%M:%S'), } self._write(self.job_status, _SUCCESS_JOB_TEMPLATE % test_info) self._write(self.job_status_log, _SUCCESS_JOB_TEMPLATE % test_info) self._write(self.test_status, _SUCCESS_TEST_TEMPLATE % test_info)
def _print_host_summaries(history_list, arguments): """Print one-line summaries of host history. This function handles the output format of the --oneline option. @param history_list A list of HostHistory objects to be printed. @param arguments Parsed arguments object as returned by ArgumentParser.parse_args(). """ fmt = '%-30s %-2s %-19s %s' print fmt % ('hostname', 'S', 'last checked', 'URL') for history in history_list: status, event = history.last_diagnosis() if not _include_status(status, arguments): continue datestr = '---' url = '---' if event is not None: datestr = time_utils.epoch_time_to_date_string(event.start_time) url = event.job_url print fmt % (history.hostname, _DIAGNOSIS_IDS[status], datestr, url)
def test_epoch_time_to_date_string(self): """Test function epoch_time_to_date_string.""" with set_time_zone('US/Pacific'): time_string = time_utils.epoch_time_to_date_string( self.TIME_SECONDS) self.assertEqual(self.TIME_STRING, time_string)
def main(): """main script. """ t_now = time.time() t_now_minus_one_day = t_now - 3600 * 24 parser = argparse.ArgumentParser() parser.add_argument('-l', type=float, dest='last', help='last hours to search results across', default=None) parser.add_argument( '--start', type=str, dest='start', help=('Enter start time as: yyyy-mm-dd hh-mm-ss,' 'defualts to 24h ago. This option is ignored when' ' -l is used.'), default=time_utils.epoch_time_to_date_string(t_now_minus_one_day)) parser.add_argument( '--end', type=str, dest='end', help=('Enter end time in as: yyyy-mm-dd hh-mm-ss,' 'defualts to current time. This option is ignored' ' when -l is used.'), default=time_utils.epoch_time_to_date_string(t_now)) parser.add_argument('--devservers', nargs='+', dest='devservers', help=('Enter space deliminated devservers. Default are' ' all devservers specified in global config.'), default=[]) parser.add_argument('--artifact_filters', nargs='+', dest='artifact_filters', help=('Enter space deliminated filters on artifact ' 'name. For example "autotest test_suites". The ' 'filter does not support regex.'), default=[]) parser.add_argument('--image_filters', nargs='+', dest='image_filters', help=('Enter space deliminated filters on image name. ' 'For example "nyan 38 6566", search will use ' 'regex to match each filter. Do not use filters ' 'with mixed letter and number, e.g., R38.'), default=[]) parser.add_argument( '-d', '--detect_duplicated_stage', action='store_true', dest='detect_duplicated_stage', help=('Set to True to detect if an artifacts for a same' ' build was staged in multiple devservers. ' 'Default is True.'), default=False) parser.add_argument('-v', action='store_true', dest='verbose', default=False, help='-v to print out ALL entries.') options = parser.parse_args() if options.verbose: logging.getLogger().setLevel(logging.INFO) if options.last: end_time = datetime.datetime.now() start_time = end_time - datetime.timedelta(seconds=3600 * options.last) else: start_time = datetime.datetime.strptime(options.start, time_utils.TIME_FMT) end_time = datetime.datetime.strptime(options.end, time_utils.TIME_FMT) logging.info('Searching devserver calls from %s to %s', start_time, end_time) devservers = options.devservers if not devservers: devserver_urls = global_config.global_config.get_config_value( 'CROS', 'dev_server', type=list, default=[]) devservers = [] for url in devserver_urls: match = re.match('http://([^:]*):*\d*', url) devservers.append(match.groups(0)[0] if match else url) logging.info('Found devservers: %s', devservers) regex_constraints = [] for filter in options.image_filters: regex_constraints.append(('image', '.*%s.*' % filter)) calls = [] for devserver in devservers: calls.extend( get_calls(start_time, end_time, options.artifact_filters, regex_constraints, devserver=devserver)) print_call_details(calls, options.verbose) if options.detect_duplicated_stage: detect_duplicated_stage(calls)
def main(): """main script. """ t_now = time.time() t_now_minus_one_day = t_now - 3600 * 24 parser = argparse.ArgumentParser() parser.add_argument('-v', action='store_true', dest='verbose', default=False, help='-v to print out ALL entries.') parser.add_argument('-l', type=float, dest='last', help='last hours to search results across', default=None) parser.add_argument('--board', type=str, dest='board', help='restrict query by board, not implemented yet', default=None) parser.add_argument('--pool', type=str, dest='pool', help='restrict query by pool, not implemented yet', default=None) parser.add_argument('--hosts', nargs='+', dest='hosts', help='Enter space deliminated hostnames', default=[]) parser.add_argument( '--start', type=str, dest='start', help=('Enter start time as: yyyy-mm-dd hh:mm:ss,' 'defualts to 24h ago.'), default=time_utils.epoch_time_to_date_string(t_now_minus_one_day)) parser.add_argument('--end', type=str, dest='end', help=('Enter end time in as: yyyy-mm-dd hh:mm:ss,' 'defualts to current time.'), default=time_utils.epoch_time_to_date_string(t_now)) options = parser.parse_args() if options.last: start_time = t_now - 3600 * options.last end_time = t_now else: start_time = time_utils.to_epoch_time(options.start) end_time = time_utils.to_epoch_time(options.end) results = get_results(hosts=options.hosts, board=options.board, pool=options.pool, start_time=start_time, end_time=end_time, verbose=options.verbose) labels = [] if options.board: labels.append('board:%s' % (options.board)) if options.pool: labels.append('pool:%s' % (options.pool)) print_all_stats(results, labels, start_time, end_time)
def _print_event_summary(event): """Print a one-line summary of a job or special task.""" start_time = time_utils.epoch_time_to_date_string(event.start_time) print ' %s %s %s' % (start_time, _DIAGNOSIS_IDS[event.diagnosis], event.job_url)