Chromium Code Reviews| 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 collections import defaultdict | 5 from collections import defaultdict |
| 6 import copy | 6 import copy |
| 7 from datetime import datetime | 7 from datetime import datetime |
| 8 | 8 |
| 9 from google.appengine.api import users | 9 from google.appengine.api import users |
| 10 | 10 |
| 11 from common import constants | 11 from common import constants |
| 12 from common.base_handler import BaseHandler | 12 from common.base_handler import BaseHandler |
| 13 from common.base_handler import Permission | 13 from common.base_handler import Permission |
| 14 from common.waterfall import failure_type | 14 from common.waterfall import failure_type |
| 15 from handlers import handlers_util | 15 from handlers import handlers_util |
| 16 from handlers import result_status | 16 from handlers import result_status |
| 17 from handlers.result_status import NO_TRY_JOB_REASON_MAP | 17 from handlers.result_status import NO_TRY_JOB_REASON_MAP |
| 18 from model import analysis_approach_type | |
| 18 from model import analysis_status | 19 from model import analysis_status |
| 19 from model import cl_confidence | 20 from model.cl_confidence import CLConfidence |
|
stgao
2016/10/06 02:17:38
Maybe SuspectConfidence instead?
chanli
2016/10/08 00:41:10
Done.
| |
| 20 from model import result_status as analysis_result_status | 21 from model import result_status as analysis_result_status |
| 21 from model import suspected_cl_status | 22 from model import suspected_cl_status |
| 22 from model.base_build_model import BaseBuildModel | 23 from model.base_build_model import BaseBuildModel |
| 23 from model.result_status import RESULT_STATUS_TO_DESCRIPTION | 24 from model.result_status import RESULT_STATUS_TO_DESCRIPTION |
| 24 from model.suspected_cl_status import CL_STATUS_TO_DESCRIPTION | 25 from model.suspected_cl_status import CL_STATUS_TO_DESCRIPTION |
| 25 from model.wf_analysis import WfAnalysis | 26 from model.wf_analysis import WfAnalysis |
| 26 from model.wf_suspected_cl import WfSuspectedCL | 27 from model.wf_suspected_cl import WfSuspectedCL |
| 27 from model.wf_try_job import WfTryJob | 28 from model.wf_try_job import WfTryJob |
| 28 from waterfall import build_failure_analysis_pipelines | 29 from waterfall import build_failure_analysis_pipelines |
| 29 from waterfall import buildbot | 30 from waterfall import buildbot |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 323 compile_failure = None | 324 compile_failure = None |
| 324 for failure in analysis.result.get('failures', []): | 325 for failure in analysis.result.get('failures', []): |
| 325 if failure['step_name'] == constants.COMPILE_STEP_NAME: | 326 if failure['step_name'] == constants.COMPILE_STEP_NAME: |
| 326 compile_failure = failure | 327 compile_failure = failure |
| 327 if compile_failure: # pragma: no branch. | 328 if compile_failure: # pragma: no branch. |
| 328 data['first_failure'] = compile_failure['first_failure'] | 329 data['first_failure'] = compile_failure['first_failure'] |
| 329 data['last_pass'] = compile_failure['last_pass'] | 330 data['last_pass'] = compile_failure['last_pass'] |
| 330 data['suspected_cls_by_heuristic'] = compile_failure['suspected_cls'] | 331 data['suspected_cls_by_heuristic'] = compile_failure['suspected_cls'] |
| 331 | 332 |
| 332 | 333 |
| 334 def _GetMostRecentConfidence(): # pragma: no cover. | |
| 335 confidences = CLConfidence.query().order(-CLConfidence.end_date).fetch(1) | |
|
stgao
2016/10/06 02:17:38
As I mentioned in the other CL, making CLConfidenc
lijeffrey
2016/10/06 14:10:33
+1
if we make CLConfidence versioned then this co
chanli
2016/10/08 00:41:10
Done.
| |
| 336 | |
| 337 return confidences[0] if confidences else None | |
| 338 | |
| 339 | |
| 340 def _PercentFormat(float_number): | |
| 341 if not float_number or not isinstance(float_number, float): | |
| 342 return None | |
| 343 return '%.2f%%' % (float_number * 100) | |
|
stgao
2016/10/06 02:17:38
I guess 70% is better than 70.87%.
chanli
2016/10/08 00:41:10
Done.
| |
| 344 | |
| 345 | |
| 346 def _GetConfidence(confidence, cl_build): | |
|
lijeffrey
2016/10/06 14:10:33
nit: rename this _GetConfidencePercentage or _GetC
chanli
2016/10/08 00:41:10
Done.
| |
| 347 | |
| 348 if not confidence: | |
| 349 return None | |
| 350 | |
| 351 if cl_build['failure_type'] == failure_type.COMPILE: | |
| 352 if cl_build['approaches'] == [ | |
| 353 analysis_approach_type.HEURISTIC, analysis_approach_type.TRY_JOB]: | |
| 354 return _PercentFormat(confidence.compile_heuristic_try_job['confidence']) | |
| 355 elif cl_build['approaches'] == [analysis_approach_type.TRY_JOB]: | |
| 356 return _PercentFormat(confidence.compile_try_job['confidence']) | |
| 357 elif (cl_build['approaches'] == [analysis_approach_type.HEURISTIC] and | |
| 358 cl_build['top_score']): | |
| 359 return _PercentFormat( | |
| 360 confidence.compile_heuristic.get( | |
| 361 str(cl_build['top_score']), {}).get('confidence')) | |
| 362 else: | |
| 363 return None | |
| 364 else: | |
| 365 if cl_build['approaches'] == [ | |
| 366 analysis_approach_type.HEURISTIC, analysis_approach_type.TRY_JOB]: | |
| 367 return _PercentFormat(confidence.test_heuristic_try_job['confidence']) | |
| 368 elif cl_build['approaches'] == [analysis_approach_type.TRY_JOB]: | |
| 369 return _PercentFormat(confidence.test_try_job['confidence']) | |
| 370 elif (cl_build['approaches'] == [analysis_approach_type.HEURISTIC] and | |
| 371 cl_build['top_score']): | |
| 372 return _PercentFormat(confidence.test_heuristic.get( | |
| 373 str(cl_build['top_score']), {}).get('confidence')) | |
| 374 else: # pragma: no cover. | |
|
lijeffrey
2016/10/06 14:10:33
why is this one no cover whereas the compile one d
chanli
2016/10/08 00:41:10
Done.
| |
| 375 return None | |
| 376 | |
| 377 | |
| 333 def _GetAllSuspectedCLsAndCheckStatus( | 378 def _GetAllSuspectedCLsAndCheckStatus( |
| 334 master_name, builder_name, build_number, analysis): | 379 master_name, builder_name, build_number, analysis): |
| 335 build_key = BaseBuildModel.CreateBuildId( | 380 build_key = BaseBuildModel.CreateBuildId( |
| 336 master_name, builder_name, build_number) | 381 master_name, builder_name, build_number) |
| 337 suspected_cls = copy.deepcopy(analysis.suspected_cls) | 382 suspected_cls = copy.deepcopy(analysis.suspected_cls) |
| 338 if not suspected_cls: | 383 if not suspected_cls: |
| 339 return [] | 384 return [] |
| 340 | 385 |
| 386 cl_confidences = _GetMostRecentConfidence() | |
| 387 | |
| 341 for cl in suspected_cls: | 388 for cl in suspected_cls: |
| 342 cl['status'] = _ANALYSIS_CL_STATUS_MAP.get(analysis.result_status, None) | 389 cl['status'] = _ANALYSIS_CL_STATUS_MAP.get(analysis.result_status, None) |
| 390 cl['confidence'] = None | |
| 391 | |
| 343 suspected_cl = WfSuspectedCL.Get(cl['repo_name'], cl['revision']) | 392 suspected_cl = WfSuspectedCL.Get(cl['repo_name'], cl['revision']) |
| 344 if not suspected_cl: | 393 if not suspected_cl: |
| 345 continue | 394 continue |
| 346 | 395 |
| 347 build = suspected_cl.builds.get(build_key) | 396 build = suspected_cl.builds.get(build_key) |
| 348 if build: | 397 if build: |
| 349 cl['status'] = build['status'] | 398 cl['status'] = build['status'] |
| 399 cl['confidence'] = _GetConfidence(cl_confidences, build) | |
| 350 | 400 |
| 351 return suspected_cls | 401 return suspected_cls |
| 352 | 402 |
| 353 | 403 |
| 354 class BuildFailure(BaseHandler): | 404 class BuildFailure(BaseHandler): |
| 355 PERMISSION_LEVEL = Permission.ANYONE | 405 PERMISSION_LEVEL = Permission.ANYONE |
| 356 | 406 |
| 357 def _ShowDebugInfo(self): | 407 def _ShowDebugInfo(self): |
| 358 # Show debug info only if the app is run locally during development, if the | 408 # Show debug info only if the app is run locally during development, if the |
| 359 # currently logged-in user is an admin, or if it is explicitly requested | 409 # currently logged-in user is an admin, or if it is explicitly requested |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 461 else: | 511 else: |
| 462 self._PrepareDataForTestFailures( | 512 self._PrepareDataForTestFailures( |
| 463 analysis, build_info, data, self._ShowDebugInfo()) | 513 analysis, build_info, data, self._ShowDebugInfo()) |
| 464 return { | 514 return { |
| 465 'template': 'waterfall/test_failure.html', | 515 'template': 'waterfall/test_failure.html', |
| 466 'data': data | 516 'data': data |
| 467 } | 517 } |
| 468 | 518 |
| 469 def HandlePost(self): # pragma: no cover | 519 def HandlePost(self): # pragma: no cover |
| 470 return self.HandleGet() | 520 return self.HandleGet() |
| OLD | NEW |