| OLD | NEW |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 from datetime import datetime | 5 from datetime import datetime |
| 6 from itertools import chain | 6 from itertools import chain |
| 7 import logging | 7 import logging |
| 8 | 8 |
| 9 import webapp2 | 9 import webapp2 |
| 10 | 10 |
| 11 from model.record import Record | 11 from model.record import Record |
| 12 from shared.config import ( | 12 from shared.config import ( |
| 13 TAG_START, | 13 TAG_START, |
| 14 TAG_STOP, | 14 TAG_STOP, |
| 15 TAG_ISSUE, | 15 TAG_ISSUE, |
| 16 TAG_PATCHSET, | 16 TAG_PATCHSET, |
| 17 TAG_CODEREVIEW_HOSTNAME, | 17 TAG_CODEREVIEW_HOSTNAME, |
| 18 TRYJOBVERIFIER, | 18 TRYJOBVERIFIER, |
| 19 JOB_STATE, | 19 JOB_STATE, |
| 20 ) | 20 ) |
| 21 from shared.parsing import parse_rietveld_timestamp | 21 from shared.parsing import parse_rietveld_timestamp |
| 22 from shared.utils import ( | 22 from shared import utils |
| 23 cross_origin_json, | |
| 24 to_unix_timestamp, | |
| 25 guess_legacy_codereview_hostname, | |
| 26 ) | |
| 27 | 23 |
| 28 | 24 |
| 29 class PatchSummary(webapp2.RequestHandler): | 25 class PatchSummary(webapp2.RequestHandler): |
| 30 @cross_origin_json | 26 @utils.cross_origin_json |
| 27 @utils.read_access |
| 31 def get(self, issue, patch): # pylint: disable=W0221 | 28 def get(self, issue, patch): # pylint: disable=W0221 |
| 32 now = to_unix_timestamp(datetime.utcnow()) | 29 now = utils.to_unix_timestamp(datetime.utcnow()) |
| 33 codereview_hostname = guess_legacy_codereview_hostname(issue) | 30 codereview_hostname = utils.guess_legacy_codereview_hostname(issue) |
| 34 return summarize_patch(codereview_hostname, issue, patch, now) | 31 return summarize_patch(codereview_hostname, issue, patch, now) |
| 35 | 32 |
| 36 | 33 |
| 37 class PatchSummaryV2(webapp2.RequestHandler): | 34 class PatchSummaryV2(webapp2.RequestHandler): |
| 38 @cross_origin_json | 35 @utils.cross_origin_json |
| 36 @utils.read_access |
| 39 def get(self, codereview_hostname, issue, patch): # pylint: disable=W0221 | 37 def get(self, codereview_hostname, issue, patch): # pylint: disable=W0221 |
| 40 now = to_unix_timestamp(datetime.utcnow()) | 38 now = utils.to_unix_timestamp(datetime.utcnow()) |
| 41 return summarize_patch(codereview_hostname, issue, patch, now) | 39 return summarize_patch(codereview_hostname, issue, patch, now) |
| 42 | 40 |
| 43 | 41 |
| 44 def summarize_patch(codereview_hostname, issue, patch, now): | 42 def summarize_patch(codereview_hostname, issue, patch, now): |
| 45 attempts = [ | 43 attempts = [ |
| 46 summarize_attempt(raw_attempt, now) | 44 summarize_attempt(raw_attempt, now) |
| 47 for raw_attempt in get_raw_attempts(codereview_hostname, issue, patch) | 45 for raw_attempt in get_raw_attempts(codereview_hostname, issue, patch) |
| 48 ][::-1] | 46 ][::-1] |
| 49 return { | 47 return { |
| 50 'success': any(attempt['success'] for attempt in attempts), | 48 'success': any(attempt['success'] for attempt in attempts), |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 if TAG_STOP in record.tags: | 84 if TAG_STOP in record.tags: |
| 87 raw_attempts.append(raw_attempt) | 85 raw_attempts.append(raw_attempt) |
| 88 raw_attempt = None | 86 raw_attempt = None |
| 89 if raw_attempt != None and len(raw_attempt) > 0: # pragma: no cover | 87 if raw_attempt != None and len(raw_attempt) > 0: # pragma: no cover |
| 90 raw_attempts.append(raw_attempt) | 88 raw_attempts.append(raw_attempt) |
| 91 return raw_attempts | 89 return raw_attempts |
| 92 | 90 |
| 93 | 91 |
| 94 def summarize_attempt(raw_attempt, now): | 92 def summarize_attempt(raw_attempt, now): |
| 95 assert len(raw_attempt) > 0 | 93 assert len(raw_attempt) > 0 |
| 96 start_timestamp = to_unix_timestamp(raw_attempt[0].timestamp) | 94 start_timestamp = utils.to_unix_timestamp(raw_attempt[0].timestamp) |
| 97 summary = blank_attempt_summary() | 95 summary = blank_attempt_summary() |
| 98 job_tracker = AttemptJobTracker(start_timestamp) | 96 job_tracker = AttemptJobTracker(start_timestamp) |
| 99 durations = summary['durations'] | 97 durations = summary['durations'] |
| 100 last_patch_action = None | 98 last_patch_action = None |
| 101 last_patch_timestamp = None | 99 last_patch_timestamp = None |
| 102 verifier_start_timestamp = None | 100 verifier_start_timestamp = None |
| 103 for record in raw_attempt: | 101 for record in raw_attempt: |
| 104 action = record.fields.get('action') | 102 action = record.fields.get('action') |
| 105 # patch_ready_to_commit signals are noisy and not useful. | 103 # patch_ready_to_commit signals are noisy and not useful. |
| 106 if action == 'patch_ready_to_commit': | 104 if action == 'patch_ready_to_commit': |
| 107 continue | 105 continue |
| 108 verifier = record.fields.get('verifier') | 106 verifier = record.fields.get('verifier') |
| 109 timestamp = to_unix_timestamp(record.timestamp) | 107 timestamp = utils.to_unix_timestamp(record.timestamp) |
| 110 if last_patch_action: | 108 if last_patch_action: |
| 111 patch_state_duration = timestamp - last_patch_timestamp | 109 patch_state_duration = timestamp - last_patch_timestamp |
| 112 | 110 |
| 113 # Verifier job updates. | 111 # Verifier job updates. |
| 114 if verifier == TRYJOBVERIFIER: | 112 if verifier == TRYJOBVERIFIER: |
| 115 if action == 'verifier_start': | 113 if action == 'verifier_start': |
| 116 verifier_start_timestamp = timestamp | 114 verifier_start_timestamp = timestamp |
| 117 elif action == 'verifier_jobs_update': | 115 elif action == 'verifier_jobs_update': |
| 118 job_tracker.update_jobs(record) | 116 job_tracker.update_jobs(record) |
| 119 elif (action in ('verifier_pass', 'verifier_fail') and | 117 elif (action in ('verifier_pass', 'verifier_fail') and |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 return min(iterable) | 289 return min(iterable) |
| 292 except ValueError: # pragma: no cover | 290 except ValueError: # pragma: no cover |
| 293 return None | 291 return None |
| 294 | 292 |
| 295 | 293 |
| 296 def maybe_max(iterable): | 294 def maybe_max(iterable): |
| 297 try: | 295 try: |
| 298 return max(iterable) | 296 return max(iterable) |
| 299 except ValueError: # pragma: no cover | 297 except ValueError: # pragma: no cover |
| 300 return None | 298 return None |
| OLD | NEW |