| OLD | NEW |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 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 import argparse | 5 import argparse |
| 6 import json | 6 import json |
| 7 import logging | 7 import logging |
| 8 import os | 8 import os |
| 9 import pickle |
| 9 import sys | 10 import sys |
| 10 import threading | 11 import threading |
| 11 import traceback | 12 import traceback |
| 13 import zlib |
| 12 | 14 |
| 13 _SCRIPT_DIR = os.path.join(os.path.dirname(__file__), os.path.pardir, | 15 _SCRIPT_DIR = os.path.join(os.path.dirname(__file__), os.path.pardir, |
| 14 os.path.pardir) | 16 os.path.pardir) |
| 15 sys.path.insert(1, _SCRIPT_DIR) | 17 sys.path.insert(1, _SCRIPT_DIR) |
| 16 | 18 |
| 17 import script_util | 19 import script_util |
| 18 script_util.SetUpSystemPaths() | 20 script_util.SetUpSystemPaths() |
| 19 | 21 |
| 20 from common.chrome_dependency_fetcher import ChromeDependencyFetcher | 22 from common.chrome_dependency_fetcher import ChromeDependencyFetcher |
| 21 from crash.crash_pipeline import FinditForClientID | 23 from crash.crash_pipeline import FinditForClientID |
| 22 from crash.crash_report import CrashReport | 24 from crash.crash_report import CrashReport |
| 23 from crash.culprit import Culprit | 25 from crash.culprit import Culprit |
| 24 from crash.detect_regression_range import DetectRegressionRange | 26 from crash.detect_regression_range import DetectRegressionRange |
| 25 from crash.findit_for_chromecrash import FinditForChromeCrash | 27 from crash.findit_for_chromecrash import FinditForChromeCrash |
| 26 from crash.type_enums import CrashClient | 28 from crash.type_enums import CrashClient |
| 27 from crash_queries.delta_test import delta_util | 29 from crash_queries.delta_test import delta_util |
| 28 from git_checkout.local_git_repository import LocalGitRepository | 30 from git_checkout.local_git_repository import LocalGitRepository |
| 29 from model.crash.crash_config import CrashConfig | 31 from model.crash.crash_config import CrashConfig |
| 30 import remote_api | 32 import remote_api |
| 31 | 33 |
| 32 _FRACAS_FEEDBACK_URL_TEMPLATE = ( | 34 _FRACAS_FEEDBACK_URL_TEMPLATE = ( |
| 33 'https://%s.appspot.com/crash/fracas-result-feedback?key=%s') | 35 'https://%s.appspot.com/crash/fracas-result-feedback?key=%s') |
| 34 | 36 |
| 35 | 37 |
| 36 def StoreResults(crash, client_id, app_id, id_to_culprits, lock, config, | 38 def StoreResults(crash, client_id, app_id, id_to_culprits, lock, config, |
| 37 verbose=False): | 39 verbose=False): |
| 38 """Stores findit result of crash into id_to_culprits dict.""" | 40 """Stores predator result of crash into id_to_culprits dict.""" |
| 39 crash_url = _FRACAS_FEEDBACK_URL_TEMPLATE % (app_id, crash['id']) | 41 crash_id = crash.key.urlsafe() |
| 42 crash_url = _FRACAS_FEEDBACK_URL_TEMPLATE % (app_id, crash_id) |
| 40 try: | 43 try: |
| 41 findit = FinditForClientID(client_id, LocalGitRepository, config) | 44 findit = FinditForClientID(client_id, LocalGitRepository, config) |
| 42 stacktrace = findit._stacktrace_parser.Parse( | 45 culprit = findit.FindCulprit(crash.ToCrashReport()) |
| 43 crash['stack_trace'], | |
| 44 ChromeDependencyFetcher(LocalGitRepository.Factory()).GetDependency( | |
| 45 crash['crashed_version'], | |
| 46 crash['platform'])) | |
| 47 if stacktrace: | |
| 48 culprit = findit._predator.FindCulprit(CrashReport( | |
| 49 crashed_version=crash['crashed_version'], | |
| 50 signature=crash['signature'], | |
| 51 platform=crash['platform'], | |
| 52 stacktrace=stacktrace, | |
| 53 regression_range=crash['regression_range'])) | |
| 54 else: | |
| 55 culprit = None | |
| 56 with lock: | 46 with lock: |
| 57 id_to_culprits[crash['id']] = culprit | 47 id_to_culprits[crash_id] = culprit |
| 58 if verbose: | 48 if verbose: |
| 59 print '\n\nCrash:', crash_url | 49 print '\n\nCrash:', crash_url |
| 60 print json.dumps(culprit.ToDicts()[0] if culprit else {'found': False}, | 50 print json.dumps(culprit.ToDicts()[0] if culprit else {'found': False}, |
| 61 indent=4, sort_keys=True) | 51 indent=4, sort_keys=True) |
| 62 except Exception: | 52 except Exception: |
| 63 with lock: | 53 with lock: |
| 64 id_to_culprits[crash['id']] = None | 54 id_to_culprits[crash_id] = None |
| 65 print '\n\nCrash:', crash_url | 55 print '\n\nCrash:', crash_url |
| 66 print traceback.format_exc() | 56 print traceback.format_exc() |
| 67 | 57 |
| 68 | 58 |
| 69 def GetCulprits(crashes, client_id, app_id, verbose=False): | 59 def GetCulprits(crashes, client_id, app_id, verbose=False): |
| 70 """Run predator analysis on crashes locally.""" | 60 """Run predator analysis on crashes locally.""" |
| 71 # Enable remote access to app engine services. | 61 # Enable remote access to app engine services. |
| 72 remote_api.EnableRemoteApi(app_id) | 62 remote_api.EnableRemoteApi(app_id) |
| 73 id_to_culprits = {} | 63 id_to_culprits = {} |
| 74 tasks = [] | 64 tasks = [] |
| 75 lock = threading.Lock() | 65 lock = threading.Lock() |
| 76 config = CrashConfig.Get() | 66 config = CrashConfig.Get() |
| 77 for crash in crashes: | 67 for crash in crashes: |
| 78 crash['regression_range'] = DetectRegressionRange( | |
| 79 crash['historical_metadata']) | |
| 80 tasks.append({ | 68 tasks.append({ |
| 81 'function': StoreResults, | 69 'function': StoreResults, |
| 82 'args': [crash, client_id, app_id, id_to_culprits, lock, config], | 70 'args': [crash, client_id, app_id, id_to_culprits, lock, config], |
| 83 'kwargs': {'verbose': verbose} | 71 'kwargs': {'verbose': verbose} |
| 84 }) | 72 }) |
| 85 script_util.RunTasks(tasks) | 73 script_util.RunTasks(tasks) |
| 86 | 74 |
| 87 return id_to_culprits | 75 return id_to_culprits |
| 88 | 76 |
| 89 | 77 |
| 90 def RunPredator(): | 78 def RunPredator(): |
| 91 """Runs delta testing between 2 different Findit versions.""" | 79 """Runs delta testing between 2 different Findit versions.""" |
| 92 argparser = argparse.ArgumentParser( | 80 argparser = argparse.ArgumentParser( |
| 93 description='Run Predator on a batch of crashes.') | 81 description='Run Predator on a batch of crashes.') |
| 82 argparser.add_argument('input_path', help='Path to read crash infos from') |
| 94 argparser.add_argument('result_path', help='Path to store results') | 83 argparser.add_argument('result_path', help='Path to store results') |
| 95 argparser.add_argument('client', help=('Possible values are: fracas, cracas, ' | 84 argparser.add_argument('client', help=('Possible values are: fracas, cracas, ' |
| 96 'clusterfuzz. Right now, only fracas ' | 85 'clusterfuzz. Right now, only fracas ' |
| 97 'is supported.')) | 86 'is supported.')) |
| 98 argparser.add_argument('app', help='App engine id to get config from.') | 87 argparser.add_argument('app', help='App engine id to get config from.') |
| 99 argparser.add_argument( | 88 argparser.add_argument( |
| 100 '--verbose', | 89 '--verbose', |
| 101 '-v', | 90 '-v', |
| 102 action='store_true', | 91 action='store_true', |
| 103 default=False, | 92 default=False, |
| 104 help='Print findit results.') | 93 help='Print findit results.') |
| 105 args = argparser.parse_args() | 94 args = argparser.parse_args() |
| 106 | 95 |
| 107 crashes = json.loads(raw_input()) | 96 with open(args.input_path) as f: |
| 97 crashes = pickle.loads(zlib.decompress(f.read())) |
| 98 |
| 108 if not crashes: | 99 if not crashes: |
| 109 logging.error('Failed to get crashes info.') | 100 logging.error('Failed to get crashes info.') |
| 110 return | 101 return |
| 111 | 102 |
| 112 culprits = GetCulprits(crashes, args.client, args.app, args.verbose) | 103 culprits = GetCulprits(crashes, args.client, args.app, args.verbose) |
| 113 delta_util.FlushResult(culprits, args.result_path) | 104 delta_util.FlushResult(culprits, args.result_path) |
| 114 | 105 |
| 115 | 106 |
| 116 if __name__ == '__main__': | 107 if __name__ == '__main__': |
| 117 # Disable the trivial loggings inside predator. | 108 # Disable the trivial loggings inside predator. |
| 118 logging.basicConfig(level=logging.ERROR) | 109 logging.basicConfig(level=logging.ERROR) |
| 119 RunPredator() | 110 RunPredator() |
| OLD | NEW |