X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/820ad7e2efc77d686bb2fa0fe0ca314f93845765..c663e037c8ad2c8dab1f4867a51e3d045357c9f6:/tools/crunchstat-summary/crunchstat_summary/summarizer.py diff --git a/tools/crunchstat-summary/crunchstat_summary/summarizer.py b/tools/crunchstat-summary/crunchstat_summary/summarizer.py index 17af9c70ac..b2f6f1bb70 100644 --- a/tools/crunchstat-summary/crunchstat_summary/summarizer.py +++ b/tools/crunchstat-summary/crunchstat_summary/summarizer.py @@ -37,6 +37,7 @@ WEBCHART_CLASS = crunchstat_summary.dygraphs.DygraphsChart class Task(object): def __init__(self): self.starttime = None + self.finishtime = None self.series = collections.defaultdict(list) @@ -115,12 +116,14 @@ class Summarizer(object): logger.debug('%s: done %s', self.label, uuid) continue - m = re.search(r'^(?P[^\s.]+)(\.\d+)? (?P\S+) \d+ (?P\d+) stderr crunchstat: (?P\S+) (?P.*?)( -- interval (?P.*))?\n$', line) + # 2017-12-02_17:15:08 e51c5-8i9sb-mfp68stkxnqdd6m 63676 0 stderr crunchstat: keepcalls 0 put 2576 get -- interval 10.0000 seconds 0 put 2576 get + m = re.search(r'^(?P[^\s.]+)(\.\d+)? (?P\S+) \d+ (?P\d+) stderr (?Pcrunchstat: )(?P\S+) (?P.*?)( -- interval (?P.*))?\n$', line) if not m: continue else: # crunch2 - m = re.search(r'^(?P\S+) (?P\S+) (?P.*?)( -- interval (?P.*))?\n$', line) + # 2017-12-01T16:56:24.723509200Z crunchstat: keepcalls 0 put 3 get -- interval 10.0000 seconds 0 put 3 get + m = re.search(r'^(?P\S+) (?Pcrunchstat: )?(?P\S+) (?P.*?)( -- interval (?P.*))?\n$', line) if not m: continue @@ -158,15 +161,24 @@ class Summarizer(object): raise ValueError("Cannot parse timestamp {!r}".format( timestamp)) - if not task.starttime: - task.starttime = timestamp + if task.starttime is None: logger.debug('%s: task %s starttime %s', self.label, task_id, timestamp) - task.finishtime = timestamp + if task.starttime is None or timestamp < task.starttime: + task.starttime = timestamp + if task.finishtime is None or timestamp > task.finishtime: + task.finishtime = timestamp - if not self.starttime: + if self.starttime is None or timestamp < task.starttime: self.starttime = timestamp - self.finishtime = timestamp + if self.finishtime is None or timestamp < task.finishtime: + self.finishtime = timestamp + + if (not self.detected_crunch1) and task.starttime is not None and task.finishtime is not None: + elapsed = (task.finishtime - task.starttime).seconds + self.task_stats[task_id]['time'] = {'elapsed': elapsed} + if elapsed > self.stats_max['time']['elapsed']: + self.stats_max['time']['elapsed'] = elapsed this_interval_s = None for group in ['current', 'interval']: @@ -182,10 +194,16 @@ class Summarizer(object): else: stats[stat] = int(val) except ValueError as e: - logger.warning( - 'Error parsing value %r (stat %r, category %r): %r', - val, stat, category, e) - logger.warning('%s', line) + # If the line doesn't start with 'crunchstat:' we + # might have mistaken an error message for a + # structured crunchstat line. + if m.group("crunchstat") is None or m.group("category") == "crunchstat": + logger.warning("%s: log contains message\n %s", self.label, line) + else: + logger.warning( + '%s: Error parsing value %r (stat %r, category %r): %r', + self.label, val, stat, category, e) + logger.warning('%s', line) continue if 'user' in stats or 'sys' in stats: stats['user+sys'] = stats.get('user', 0) + stats.get('sys', 0) @@ -533,7 +551,7 @@ class MultiSummarizer(object): def text_report(self): txt = '' d = self._descendants() - for cname, child in d.iteritems(): + for child in d.itervalues(): if len(d) > 1: txt += '### Summary for {} ({})\n'.format( child.label, child.process['uuid']) @@ -605,7 +623,7 @@ class PipelineSummarizer(MultiSummarizer): class ContainerTreeSummarizer(MultiSummarizer): - def __init__(self, root, **kwargs): + def __init__(self, root, skip_child_jobs=False, **kwargs): arv = arvados.api('v1', model=OrderedJsonModel()) label = kwargs.pop('label', None) or root.get('name') or root['uuid'] @@ -626,15 +644,20 @@ class ContainerTreeSummarizer(MultiSummarizer): page_filters = [] while True: - items = arv.container_requests().index( + child_crs = arv.container_requests().index( order=['uuid asc'], filters=page_filters+[ ['requesting_container_uuid', '=', current['uuid']]], - ).execute()['items'] - if not items: + ).execute() + if not child_crs['items']: + break + elif skip_child_jobs: + logger.warning('%s: omitting stats from %d child containers' + ' because --skip-child-jobs flag is on', + label, child_crs['items_available']) break - page_filters = [['uuid', '>', items[-1]['uuid']]] - for cr in items: + page_filters = [['uuid', '>', child_crs['items'][-1]['uuid']]] + for cr in child_crs['items']: if cr['container_uuid']: logger.debug('%s: container req %s', current['uuid'], cr['uuid']) cr['name'] = cr.get('name') or cr['uuid']