| OLD | NEW |
| (Empty) |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 # Use of this source code is governed by a BSD-style license that can be | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 """Process crashes from Chrome crash server and find culprits for them.""" | |
| 6 | |
| 7 import logging | |
| 8 | |
| 9 from common import chromium_deps | |
| 10 from crash import detect_regression_range | |
| 11 from crash import findit_for_crash | |
| 12 from crash.fracas_parser import FracasParser | |
| 13 from crash.project_classifier import ProjectClassifier | |
| 14 from crash.component_classifier import ComponentClassifier | |
| 15 from model.crash.crash_config import CrashConfig | |
| 16 | |
| 17 # TODO(katesonia): Remove the default value after adding validity check to | |
| 18 # config. | |
| 19 _DEFAULT_TOP_N = 7 | |
| 20 | |
| 21 | |
| 22 def FindCulpritForChromeCrash(signature, platform, | |
| 23 stack_trace, crashed_version, historic_metadata): | |
| 24 """Finds culprits for a Chrome crash. | |
| 25 | |
| 26 Args: | |
| 27 platform (str): The platform name, could be 'win', 'mac', 'linux', | |
| 28 'android', 'ios', etc. | |
| 29 signature (str): The signature of a crash on the Chrome crash server. | |
| 30 stack_trace (str): A string containing the stack trace of a crash. | |
| 31 crash_version (str): The version of Chrome in which the crash occurred. | |
| 32 historic_metadata (list): list of dicts mapping from Chrome version to | |
| 33 historic metadata. | |
| 34 | |
| 35 Returns: | |
| 36 (analysis_result_dict, tag_dict) | |
| 37 The analysis result is a dict like below: | |
| 38 { | |
| 39 "found": true, # Indicate whether Findit found any suspects. | |
| 40 "suspected_project": "chromium-v8", # Which project is most suspected. | |
| 41 "feedback_url": "https://.." | |
| 42 "suspected_cls": [ | |
| 43 { | |
| 44 "revision": "commit-hash", | |
| 45 "url": "https://chromium.googlesource.com/chromium/src/+/ha...", | |
| 46 "review_url": "https://codereview.chromium.org/issue-number", | |
| 47 "project_path": "third_party/pdfium", | |
| 48 "author": "who@chromium.org", | |
| 49 "time": "2015-08-17 03:38:16", | |
| 50 "reason": "a plain string with '\n' as line break to explain..." | |
| 51 "reason": [('MinDistance', 1, 'minimum distance is 0.'), | |
| 52 ('TopFrame', 0.9, 'top frame is2nd frame.')], | |
| 53 "changed_files": [ | |
| 54 {"file": "file_name1.cc", | |
| 55 "blame_url": "https://...", | |
| 56 "info": "minimum distance (LOC) 0, frame #2"}, | |
| 57 {"file": "file_name2.cc", | |
| 58 "blame_url": "https://...", | |
| 59 "info": "minimum distance (LOC) 20, frame #4"}, | |
| 60 ... | |
| 61 ], | |
| 62 "confidence": 0.60 | |
| 63 }, | |
| 64 ..., | |
| 65 ], | |
| 66 "regression_range": [ # Detected regression range. | |
| 67 "53.0.2765.0", | |
| 68 "53.0.2766.0" | |
| 69 ], | |
| 70 "suspected_components": [ # A list of crbug components to file bugs. | |
| 71 "Blink>JavaScript" | |
| 72 ] | |
| 73 } | |
| 74 | |
| 75 The code review url might not always be available, because not all commits | |
| 76 go through code review. In that case, commit url should be used instead. | |
| 77 | |
| 78 The tag dict are allowed key/value pairs to tag the analysis result for | |
| 79 query and monitoring purpose on Findit side. For allowed keys, please | |
| 80 refer to crash_analysis.py and fracas_crash_analysis.py: | |
| 81 For results with normal culprit-finding algorithm: { | |
| 82 'found_suspects': True, | |
| 83 'has_regression_range': True, | |
| 84 'solution': 'core_algorithm', | |
| 85 } | |
| 86 For results using git blame without a regression range: { | |
| 87 'found_suspects': True, | |
| 88 'has_regression_range': False, | |
| 89 'solution': 'blame', | |
| 90 } | |
| 91 If nothing is found: { | |
| 92 'found_suspects': False, | |
| 93 } | |
| 94 """ | |
| 95 crash_deps = chromium_deps.GetChromeDependency(crashed_version, platform) | |
| 96 stacktrace = FracasParser().Parse(stack_trace, crash_deps, signature) | |
| 97 if not stacktrace: | |
| 98 logging.warning('Failed to parse the stacktrace %s', stack_trace) | |
| 99 return {'found': False}, {'found_suspects': False, | |
| 100 'has_regression_range': False} | |
| 101 | |
| 102 regression_deps_rolls = {} | |
| 103 regression_versions = detect_regression_range.DetectRegressionRange( | |
| 104 historic_metadata) | |
| 105 | |
| 106 if regression_versions: | |
| 107 last_good_version, first_bad_version = regression_versions | |
| 108 logging.info('Find regression range %s:%s', last_good_version, | |
| 109 first_bad_version) | |
| 110 | |
| 111 # Get regression deps and crash deps. | |
| 112 regression_deps_rolls = chromium_deps.GetDEPSRollsDict( | |
| 113 last_good_version, first_bad_version, platform) | |
| 114 | |
| 115 crash_config = CrashConfig.Get() | |
| 116 culprit_results = findit_for_crash.FindItForCrash( | |
| 117 stacktrace, regression_deps_rolls, crash_deps, crash_config.fracas.get( | |
| 118 'top_n', _DEFAULT_TOP_N)) | |
| 119 | |
| 120 crash_stack = stacktrace.crash_stack | |
| 121 suspected_project = ProjectClassifier().Classify( | |
| 122 culprit_results, crash_stack) | |
| 123 suspected_components = ComponentClassifier().Classify( | |
| 124 culprit_results, crash_stack) | |
| 125 | |
| 126 culprit_results_list = [result.ToDict() for result in culprit_results] | |
| 127 | |
| 128 return ( | |
| 129 { | |
| 130 'found': (bool(suspected_project) or bool(suspected_components) or | |
| 131 bool(culprit_results_list)), | |
| 132 'regression_range': regression_versions, | |
| 133 'suspected_project': suspected_project, | |
| 134 'suspected_components': suspected_components, | |
| 135 'suspected_cls': culprit_results_list, | |
| 136 }, | |
| 137 { | |
| 138 'found_suspects': bool(culprit_results_list), | |
| 139 'has_regression_range': bool(regression_versions), | |
| 140 'solution': 'core_algorithm', | |
| 141 } | |
| 142 ) | |
| OLD | NEW |