Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(154)

Side by Side Diff: infra/services/builder_alerts/__main__.py

Issue 2186673003: Remove logging and metrics from builder alerts code (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Also remove in chromium_try_flakes Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2014 The Chromium Authors. All rights reserved. 2 # Copyright 2014 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 import argparse 6 import argparse
7 import contextlib 7 import contextlib
8 import cStringIO 8 import cStringIO
9 import datetime 9 import datetime
10 import gzip 10 import gzip
11 import json 11 import json
12 import logging 12 import logging
13 import multiprocessing 13 import multiprocessing
14 import os 14 import os
15 import sys 15 import sys
16 import threading 16 import threading
17 import traceback 17 import traceback
18 18
19 import requests 19 import requests
20 import requests_cache 20 import requests_cache
21 21
22 from infra_libs import logs 22 from infra_libs import logs
23 from infra_libs import ts_mon
24 from infra.libs.service_utils import outer_loop 23 from infra.libs.service_utils import outer_loop
25 24
26 from infra.services.builder_alerts import alert_builder 25 from infra.services.builder_alerts import alert_builder
27 from infra.services.builder_alerts import analysis 26 from infra.services.builder_alerts import analysis
28 from infra.services.builder_alerts import buildbot 27 from infra.services.builder_alerts import buildbot
29 from infra.services.builder_alerts import crbug_issues 28 from infra.services.builder_alerts import crbug_issues
30 from infra.services.builder_alerts import gatekeeper_extras 29 from infra.services.builder_alerts import gatekeeper_extras
31 from infra.services.builder_alerts import string_helpers 30 from infra.services.builder_alerts import string_helpers
32 31
33 32
(...skipping 20 matching lines...) Expand all
54 class SubProcess(object): 53 class SubProcess(object):
55 54
56 def __init__(self, cache, old_alerts, builder_filter, jobs): 55 def __init__(self, cache, old_alerts, builder_filter, jobs):
57 super(SubProcess, self).__init__() 56 super(SubProcess, self).__init__()
58 self._cache = cache 57 self._cache = cache
59 self._old_alerts = old_alerts 58 self._old_alerts = old_alerts
60 self._builder_filter = builder_filter 59 self._builder_filter = builder_filter
61 self._jobs = jobs 60 self._jobs = jobs
62 61
63 def __call__(self, master_url): 62 def __call__(self, master_url):
64 logging.debug('Thread for master %s has started', master_url)
65 try: 63 try:
66 master_json = buildbot.fetch_master_json(master_url) 64 master_json = buildbot.fetch_master_json(master_url)
67 if not master_json: 65 if not master_json:
68 return (None, None, None, master_url) 66 return (None, None, None, master_url)
69 67
70 master_alerts, stale_master_alert = alert_builder.alerts_for_master( 68 master_alerts, stale_master_alert = alert_builder.alerts_for_master(
71 self._cache, master_url, master_json, self._old_alerts, 69 self._cache, master_url, master_json, self._old_alerts,
72 self._builder_filter, self._jobs) 70 self._builder_filter, self._jobs)
73 71
74 # FIXME: The builder info doesn't really belong here. The builder 72 # FIXME: The builder info doesn't really belong here. The builder
75 # revisions tool uses this and we happen to have the builder json cached 73 # revisions tool uses this and we happen to have the builder json cached
76 # at this point so it's cheap to compute, but it should be moved 74 # at this point so it's cheap to compute, but it should be moved
77 # to a different feed. 75 # to a different feed.
78 data, stale_builder_alerts = ( 76 data, stale_builder_alerts = (
79 buildbot.latest_builder_info_and_alerts_for_master( 77 buildbot.latest_builder_info_and_alerts_for_master(
80 self._cache, master_url, master_json)) 78 self._cache, master_url, master_json))
81 if stale_master_alert: 79 if stale_master_alert:
82 stale_builder_alerts.append(stale_master_alert) 80 stale_builder_alerts.append(stale_master_alert)
83 return (master_alerts, data, stale_builder_alerts, master_url) 81 return (master_alerts, data, stale_builder_alerts, master_url)
84 except: 82 except:
85 # Put all exception text into an exception and raise that so it doesn't 83 # Put all exception text into an exception and raise that so it doesn't
86 # get eaten by the multiprocessing code. 84 # get eaten by the multiprocessing code.
87 msg = '%s for master url %s' % ( 85 msg = '%s for master url %s' % (
88 ''.join(traceback.format_exception(*sys.exc_info())), 86 ''.join(traceback.format_exception(*sys.exc_info())),
89 master_url, 87 master_url,
90 ) 88 )
91 raise Exception(msg) 89 raise Exception(msg)
92 finally:
93 logging.debug('Thread for master %s has finished', master_url)
94 90
95 91
96 def query_findit(findit_api_url, alerts): 92 def query_findit(findit_api_url, alerts):
97 """Get analysis results from Findit for failures in the given alerts. 93 """Get analysis results from Findit for failures in the given alerts.
98 94
99 Args: 95 Args:
100 findit_api_url (str): The URL to findit's api for build failure analysis. 96 findit_api_url (str): The URL to findit's api for build failure analysis.
101 alerts (list): A non-empty list of failure alerts. 97 alerts (list): A non-empty list of failure alerts.
102 98
103 Returns: 99 Returns:
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 182
187 183
188 def gzipped(data): 184 def gzipped(data):
189 s = cStringIO.StringIO() 185 s = cStringIO.StringIO()
190 with contextlib.closing(gzip.GzipFile(fileobj=s, mode='w')) as g: 186 with contextlib.closing(gzip.GzipFile(fileobj=s, mode='w')) as g:
191 g.write(data) 187 g.write(data)
192 return s.getvalue() 188 return s.getvalue()
193 189
194 190
195 def inner_loop(args): 191 def inner_loop(args):
196 logging.debug('Starting inner loop')
197 old_api_endpoint = string_helpers.slash_join(args.api_endpoint_prefix, 192 old_api_endpoint = string_helpers.slash_join(args.api_endpoint_prefix,
198 args.old_api_path) if args.old_api_path else None 193 args.old_api_path) if args.old_api_path else None
199 if not old_api_endpoint: 194 if not old_api_endpoint:
200 logging.warn( 195 logging.warn(
201 'No /data url passed, will write to builder_alerts.json. JSON posted ' 196 'No /data url passed, will write to builder_alerts.json. JSON posted '
202 'to new API endpoints will be written to builder_alerts_<tree>.json ' 197 'to new API endpoints will be written to builder_alerts_<tree>.json '
203 'files.') 198 'files.')
204 199
205 if args.use_cache: 200 if args.use_cache:
206 requests_cache.install_cache('failure_stats') 201 requests_cache.install_cache('failure_stats')
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 ' %s' % (master, builder, step, reason)) 242 ' %s' % (master, builder, step, reason))
248 243
249 old_alerts[alert_key] = alert 244 old_alerts[alert_key] = alert
250 245
251 latest_builder_info = {} 246 latest_builder_info = {}
252 stale_builder_alerts = [] 247 stale_builder_alerts = []
253 missing_masters = [] 248 missing_masters = []
254 alerts = [] 249 alerts = []
255 suspected_cls = [] 250 suspected_cls = []
256 251
257 logging.debug('Processing all masters via process pool')
258 pool = multiprocessing.Pool(processes=args.processes) 252 pool = multiprocessing.Pool(processes=args.processes)
259 master_datas = pool.map(SubProcess(cache, old_alerts, args.builder_filter, 253 master_datas = pool.map(SubProcess(cache, old_alerts, args.builder_filter,
260 args.jobs), master_urls) 254 args.jobs), master_urls)
261 logging.debug('Closing all threads in master process pool')
262 pool.close() 255 pool.close()
263 pool.join() 256 pool.join()
264 logging.debug('Joined all threads in master process pool')
265 257
266 for data in master_datas: 258 for data in master_datas:
267 # TODO(ojan): We should put an alert in the JSON for this master so 259 # TODO(ojan): We should put an alert in the JSON for this master so
268 # we can show that the master is down in the sheriff-o-matic UI. 260 # we can show that the master is down in the sheriff-o-matic UI.
269 if not data[0]: 261 if not data[0]:
270 missing_masters.extend([data[3]]) 262 missing_masters.extend([data[3]])
271 continue 263 continue
272 alerts.extend(data[0]) 264 alerts.extend(data[0])
273 latest_builder_info.update(data[1]) 265 latest_builder_info.update(data[1])
274 stale_builder_alerts.extend(data[2]) 266 stale_builder_alerts.extend(data[2])
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 resp.status_code, resp.reason, resp.content) 337 resp.status_code, resp.reason, resp.content)
346 ret = False 338 ret = False
347 else: 339 else:
348 with open('builder_alerts_%s.json' % tree, 'w') as f: 340 with open('builder_alerts_%s.json' % tree, 'w') as f:
349 f.write(json.dumps(json_data, indent=1)) 341 f.write(json.dumps(json_data, indent=1))
350 else: 342 else:
351 logging.error( 343 logging.error(
352 '--crbug-service-account was not specified, can not get crbug issues') 344 '--crbug-service-account was not specified, can not get crbug issues')
353 ret = False 345 ret = False
354 346
355 logging.debug('Returning from inner loop')
356 return ret 347 return ret
357 348
358 349
359 def main(args): 350 def main(args):
360 parser = argparse.ArgumentParser(prog='run.py %s' % __package__) 351 parser = argparse.ArgumentParser(prog='run.py %s' % __package__)
361 parser.add_argument('data_url', action='store', nargs='*') # Deprecated 352 parser.add_argument('data_url', action='store', nargs='*') # Deprecated
362 parser.add_argument('--use-cache', action='store_true') 353 parser.add_argument('--use-cache', action='store_true')
363 parser.add_argument('--master-filter', action='store') 354 parser.add_argument('--master-filter', action='store')
364 parser.add_argument('--builder-filter', action='store') 355 parser.add_argument('--builder-filter', action='store')
365 parser.add_argument('--processes', default=PARALLEL_TASKS, action='store', 356 parser.add_argument('--processes', default=PARALLEL_TASKS, action='store',
366 type=int) 357 type=int)
367 parser.add_argument('--jobs', default=CONCURRENT_TASKS, action='store', 358 parser.add_argument('--jobs', default=CONCURRENT_TASKS, action='store',
368 type=int) 359 type=int)
369 logs.add_argparse_options(parser) 360 logs.add_argparse_options(parser)
370 outer_loop.add_argparse_options(parser) 361 outer_loop.add_argparse_options(parser)
371 362
372 ts_mon.add_argparse_options(parser)
373 parser.set_defaults(
374 ts_mon_target_type='task',
375 ts_mon_task_service_name='builder-alerts',
376 ts_mon_task_job_name='builder-alerts',
377 )
378
379 gatekeeper_json = os.path.join(build_scripts_dir, 'slave', 'gatekeeper.json') 363 gatekeeper_json = os.path.join(build_scripts_dir, 'slave', 'gatekeeper.json')
380 parser.add_argument('--gatekeeper', action='store', default=gatekeeper_json) 364 parser.add_argument('--gatekeeper', action='store', default=gatekeeper_json)
381 gatekeeper_trees_json = os.path.join(build_scripts_dir, 'slave', 365 gatekeeper_trees_json = os.path.join(build_scripts_dir, 'slave',
382 'gatekeeper_trees.json') 366 'gatekeeper_trees.json')
383 parser.add_argument('--gatekeeper-trees', action='store', 367 parser.add_argument('--gatekeeper-trees', action='store',
384 default=gatekeeper_trees_json) 368 default=gatekeeper_trees_json)
385 369
386 parser.add_argument('--findit-api-url', 370 parser.add_argument('--findit-api-url',
387 help='Query findit results from this url.') 371 help='Query findit results from this url.')
388 parser.add_argument('--crbug-service-account', 372 parser.add_argument('--crbug-service-account',
389 help='Path to a service account JSON file to be used to ' 373 help='Path to a service account JSON file to be used to '
390 'search for relevant issues on crbug.com.') 374 'search for relevant issues on crbug.com.')
391 parser.add_argument('--api-endpoint-prefix', 375 parser.add_argument('--api-endpoint-prefix',
392 help='Endpoint prefix for posting alerts. Old API ' 376 help='Endpoint prefix for posting alerts. Old API '
393 'endpoint will be formed by adding value specified ' 377 'endpoint will be formed by adding value specified '
394 'in --old-api-path to the prefix, new API endpoints ' 378 'in --old-api-path to the prefix, new API endpoints '
395 'will be formed by adding ' 379 'will be formed by adding '
396 '/api/v1/alerts/<tree_name>.') 380 '/api/v1/alerts/<tree_name>.')
397 parser.add_argument('--old-api-path', 381 parser.add_argument('--old-api-path',
398 help='Path to be appended to --api-endpoint-prefix to ' 382 help='Path to be appended to --api-endpoint-prefix to '
399 'form old API endpoint.') 383 'form old API endpoint.')
400 384
401 args = parser.parse_args(args) 385 args = parser.parse_args(args)
402 logs.process_argparse_options(args) 386 logs.process_argparse_options(args)
403 loop_args = outer_loop.process_argparse_options(args) 387 loop_args = outer_loop.process_argparse_options(args)
404 ts_mon.process_argparse_options(args)
405 388
406 # TODO(sergiyb): Remove support for data_url when builder_alerts recipes are 389 # TODO(sergiyb): Remove support for data_url when builder_alerts recipes are
407 # updated and using new syntax to call this script. 390 # updated and using new syntax to call this script.
408 if args.data_url: 391 if args.data_url:
409 if (len(args.data_url) == 1 and args.data_url[0].endswith('alerts') and 392 if (len(args.data_url) == 1 and args.data_url[0].endswith('alerts') and
410 not args.api_endpoint_prefix and not args.old_api_path): 393 not args.api_endpoint_prefix and not args.old_api_path):
411 logging.warn( 394 logging.warn(
412 'You are using positional argument to specify URL to post updates ' 395 'You are using positional argument to specify URL to post updates '
413 'to. Please use --api-endpoint-prefix and --old-api-path instead.') 396 'to. Please use --api-endpoint-prefix and --old-api-path instead.')
414 slash_index = args.data_url[0].rindex('/') 397 slash_index = args.data_url[0].rindex('/')
(...skipping 15 matching lines...) Expand all
430 def filter(record): 413 def filter(record):
431 if record.levelno == logging.INFO: 414 if record.levelno == logging.INFO:
432 return False 415 return False
433 return True 416 return True
434 logging.getLogger('requests.packages.urllib3.connectionpool').addFilter( 417 logging.getLogger('requests.packages.urllib3.connectionpool').addFilter(
435 _ConnectionpoolFilter()) 418 _ConnectionpoolFilter())
436 419
437 def outer_loop_iteration(): 420 def outer_loop_iteration():
438 return inner_loop(args) 421 return inner_loop(args)
439 422
440 logging.debug('Starting outer loop')
441 loop_results = outer_loop.loop( 423 loop_results = outer_loop.loop(
442 task=outer_loop_iteration, 424 task=outer_loop_iteration,
443 sleep_timeout=lambda: 5, 425 sleep_timeout=lambda: 5,
444 **loop_args) 426 **loop_args)
445 logging.debug('Finished outer loop')
446 427
447 logging.debug('Flushing ts_mon starting')
448 ts_mon.flush()
449 logging.debug('Flushing ts_mon completed')
450 return 0 if loop_results.success else 1 428 return 0 if loop_results.success else 1
451 429
452 430
453 if __name__ == '__main__': 431 if __name__ == '__main__':
454 logging.debug('Started main') 432 sys.exit(main(sys.argv[1:]))
455 retcode = main(sys.argv[1:])
456 current_thread_descriptions = [t.name + (' (daemon)' if t.isDaemon() else '')
457 for t in threading.enumerate()
458 if t is not threading.current_thread()]
459 logging.debug(
460 'Leaving main. Threads: %s', ', '.join(current_thread_descriptions))
461 sys.exit(retcode)
OLDNEW
« no previous file with comments | « appengine/chromium_try_flakes/issue_tracker/issue_tracker_api.py ('k') | infra/services/builder_alerts/alert_builder.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698