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

Side by Side Diff: experimental/telemetry_mini/telemetry_mini.py

Issue 3002943002: [telemetry_mini] Add story runner options (Closed)
Patch Set: just --repeat Created 3 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
« no previous file with comments | « experimental/telemetry_mini/android_go_stories.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2017 The Chromium Authors. All rights reserved. 2 # Copyright 2017 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 # This is intended to be a very trimmed down, single-file, hackable, and easy 6 # This is intended to be a very trimmed down, single-file, hackable, and easy
7 # to understand version of Telemetry. It's able to run simple user stories on 7 # to understand version of Telemetry. It's able to run simple user stories on
8 # Android, grab traces, and extract metrics from them. May be useful to 8 # Android, grab traces, and extract metrics from them. May be useful to
9 # diagnose issues with Chrome, reproduce regressions or prototype new user 9 # diagnose issues with Chrome, reproduce regressions or prototype new user
10 # stories. 10 # stories.
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 400
401 class ChromiumApp(AndroidApp): 401 class ChromiumApp(AndroidApp):
402 PACKAGE_NAME = 'org.chromium.chrome' 402 PACKAGE_NAME = 'org.chromium.chrome'
403 APK_FILENAME = 'ChromePublic.apk' 403 APK_FILENAME = 'ChromePublic.apk'
404 COMMAND_LINE_FILE = '/data/local/tmp/chrome-command-line' 404 COMMAND_LINE_FILE = '/data/local/tmp/chrome-command-line'
405 TRACE_CONFIG_FILE = '/data/local/chrome-trace-config.json' 405 TRACE_CONFIG_FILE = '/data/local/chrome-trace-config.json'
406 406
407 def __init__(self, *args, **kwargs): 407 def __init__(self, *args, **kwargs):
408 super(ChromiumApp, self).__init__(*args, **kwargs) 408 super(ChromiumApp, self).__init__(*args, **kwargs)
409 self._devtools_local_port = None 409 self._devtools_local_port = None
410 self._browser_flags = None
411 self._trace_config = None
410 self.startup_time = None 412 self.startup_time = None
411 413
412 def RemoveProfile(self): 414 def RemoveProfile(self):
413 # TODO: Path to profile may need to be updated on newer Android versions. 415 # TODO: Path to profile may need to be updated on newer Android versions.
414 profile_dir = posixpath.join('/data/data', self.PACKAGE_NAME) 416 profile_dir = posixpath.join('/data/data', self.PACKAGE_NAME)
415 filenames = self.device.ListPath(profile_dir) 417 filenames = self.device.ListPath(profile_dir)
416 args = ['rm', '-r'] 418 args = ['rm', '-r']
417 args.extend( 419 args.extend(
418 posixpath.join(profile_dir, f) 420 posixpath.join(profile_dir, f)
419 for f in filenames if f not in ['.', '..', 'lib']) 421 for f in filenames if f not in ['.', '..', 'lib'])
420 self.device.RunShellCommand(*args) 422 self.device.RunShellCommand(*args)
421 423
422 @contextlib.contextmanager 424 @contextlib.contextmanager
423 def CommandLineFlags(self, flags): 425 def CommandLineFlags(self):
424 self.device.WriteText(' '.join(['_'] + flags), self.COMMAND_LINE_FILE) 426 command_line = ' '.join(['_'] + self._browser_flags)
427 self.device.WriteText(command_line, self.COMMAND_LINE_FILE)
425 try: 428 try:
426 yield 429 yield
427 finally: 430 finally:
428 self.device.RunShellCommand('rm', '-f', self.COMMAND_LINE_FILE) 431 self.device.RunShellCommand('rm', '-f', self.COMMAND_LINE_FILE)
429 432
433 def SetBrowserFlags(self, browser_flags):
434 self._browser_flags = browser_flags
435
436 def SetTraceConfig(self, trace_config):
437 self._trace_config = trace_config
438
430 def SetDevToolsLocalPort(self, port): 439 def SetDevToolsLocalPort(self, port):
431 self._devtools_local_port = port 440 self._devtools_local_port = port
432 441
433 def GetDevToolsLocalAddr(self, host='localhost'): 442 def GetDevToolsLocalAddr(self, host='localhost'):
434 assert self._devtools_local_port is not None 443 assert self._devtools_local_port is not None
435 return '%s:%d' % (host, self._devtools_local_port) 444 return '%s:%d' % (host, self._devtools_local_port)
436 445
437 def GetDevToolsRemoteAddr(self): 446 def GetDevToolsRemoteAddr(self):
438 return 'localabstract:chrome_devtools_remote' 447 return 'localabstract:chrome_devtools_remote'
439 448
440 @contextlib.contextmanager 449 @contextlib.contextmanager
441 def PortForwarding(self): 450 def PortForwarding(self):
442 """Setup port forwarding to connect with DevTools on remote device.""" 451 """Setup port forwarding to connect with DevTools on remote device."""
443 local = self.GetDevToolsLocalAddr('tcp') 452 local = self.GetDevToolsLocalAddr('tcp')
444 remote = self.GetDevToolsRemoteAddr() 453 remote = self.GetDevToolsRemoteAddr()
445 self.device.RunCommand('forward', '--no-rebind', local, remote) 454 self.device.RunCommand('forward', '--no-rebind', local, remote)
446 try: 455 try:
447 yield 456 yield
448 finally: 457 finally:
449 self.device.RunCommand('forward', '--remove', local) 458 self.device.RunCommand('forward', '--remove', local)
450 459
451 @contextlib.contextmanager 460 @contextlib.contextmanager
452 def StartupTracing(self, trace_config): 461 def StartupTracing(self):
453 self.device.WriteText( 462 self.device.WriteText(
454 json.dumps({'trace_config': trace_config}), self.TRACE_CONFIG_FILE) 463 json.dumps({'trace_config': self._trace_config}),
464 self.TRACE_CONFIG_FILE)
455 try: 465 try:
456 yield 466 yield
457 finally: 467 finally:
458 self.device.RunShellCommand('rm', '-f', self.TRACE_CONFIG_FILE) 468 self.device.RunShellCommand('rm', '-f', self.TRACE_CONFIG_FILE)
459 469
460 @contextlib.contextmanager 470 @contextlib.contextmanager
461 def Session(self, flags, trace_config): 471 def Session(self):
462 """A context manager to guard the lifetime of a browser process. 472 """A context manager to guard the lifetime of a browser process.
463 473
464 Ensures that command line flags and port forwarding are ready, the browser 474 Ensures that command line flags and port forwarding are ready, the browser
465 is not alive before starting, it has a clear profile to begin with, and is 475 is not alive before starting, it has a clear profile to begin with, and is
466 finally closed when done. 476 finally closed when done.
467 477
468 It does not, however, launch the browser itself. This must be done by the 478 It does not, however, launch the browser itself. This must be done by the
469 context managed code. 479 context managed code.
470 480
471 To the extent possible, measurements from browsers launched within 481 To the extent possible, measurements from browsers launched within
472 different sessions are meant to be independent of each other. 482 different sessions are meant to be independent of each other.
473 """ 483 """
474 # Removing the profile breaks Chrome Shortcuts on the Home Screen. 484 # Removing the profile breaks Chrome Shortcuts on the Home Screen.
475 # TODO: Figure out a way to automatically create the shortcuts before 485 # TODO: Figure out a way to automatically create the shortcuts before
476 # running the story. 486 # running the story.
477 # self.RemoveProfile() 487 # self.RemoveProfile()
478 with self.CommandLineFlags(flags): 488 with self.CommandLineFlags():
479 with self.StartupTracing(trace_config): 489 with self.StartupTracing():
480 # Ensure browser is closed after setting command line flags and 490 # Ensure browser is closed after setting command line flags and
481 # trace config to ensure they are read on startup. 491 # trace config to ensure they are read on startup.
482 self.ForceStop() 492 self.ForceStop()
483 with self.PortForwarding(): 493 with self.PortForwarding():
484 try: 494 try:
485 yield 495 yield
486 finally: 496 finally:
487 self.ForceStop() 497 self.ForceStop()
488 498
489 def WaitForCurrentPageReady(self): 499 def WaitForCurrentPageReady(self):
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 logging.warning('Disabling %s', self.PACKAGE_NAME) 560 logging.warning('Disabling %s', self.PACKAGE_NAME)
551 self.device.RunShellCommand('pm', 'disable', self.PACKAGE_NAME) 561 self.device.RunShellCommand('pm', 'disable', self.PACKAGE_NAME)
552 562
553 563
554 class UserStory(object): 564 class UserStory(object):
555 def __init__(self, browser): 565 def __init__(self, browser):
556 self.device = browser.device 566 self.device = browser.device
557 self.browser = browser 567 self.browser = browser
558 self.actions = AndroidActions(self.device) 568 self.actions = AndroidActions(self.device)
559 569
560 def Run(self, browser_flags, trace_config, trace_file): 570 def Run(self, trace_file):
561 with self.browser.Session(browser_flags, trace_config): 571 with self.browser.Session():
562 self.RunPrepareSteps() 572 self.RunPrepareSteps()
563 try: 573 try:
564 self.RunStorySteps() 574 self.RunStorySteps()
565 self.browser.CollectTrace(trace_file) 575 self.browser.CollectTrace(trace_file)
566 except Exception as exc: 576 except Exception as exc:
567 # Helps to pin point in the logs the moment where the story failed, 577 # Helps to pin point in the logs the moment where the story failed,
568 # before any of the finally blocks get to be executed. 578 # before any of the finally blocks get to be executed.
569 logging.error('Aborting story due to %s.', type(exc).__name__) 579 logging.error('Aborting story due to %s.', type(exc).__name__)
570 raise 580 raise
571 finally: 581 finally:
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 if event['ph'] == 'v': 613 if event['ph'] == 'v':
604 # Extract any metrics you may need from the trace. 614 # Extract any metrics you may need from the trace.
605 value = event['args']['dumps']['allocators'][ 615 value = event['args']['dumps']['allocators'][
606 'java_heap/allocated_objects']['attrs']['size'] 616 'java_heap/allocated_objects']['attrs']['size']
607 assert value['units'] == 'bytes' 617 assert value['units'] == 'bytes'
608 processes[event['pid']]['java_heap'] = int(value['value'], 16) 618 processes[event['pid']]['java_heap'] = int(value['value'], 16)
609 elif event['ph'] == 'M' and event['name'] == 'process_name': 619 elif event['ph'] == 'M' and event['name'] == 'process_name':
610 processes[event['pid']]['name'] = event['args']['name'] 620 processes[event['pid']]['name'] = event['args']['name']
611 621
612 return processes.values() 622 return processes.values()
623
624
625 def RunStories(browser, stories, repeat, output_dir):
626 for repeat_idx in range(1, repeat + 1):
627 for story_cls in stories:
628 trace_file = os.path.join(
629 output_dir, 'trace_%s_%d.json' % (story_cls.NAME, repeat_idx))
630 print '[ RUN ]', story_cls.NAME
631 status = '[ OK ]'
632 start = time.time()
633 try:
634 story_cls(browser).Run(trace_file)
635 except Exception: # pylint: disable=broad-except
636 logging.exception('Exception raised while running story')
637 status = '[ FAILED ]'
638 finally:
639 elapsed = '(%.1f secs)' % (time.time() - start)
640 print status, story_cls.NAME, elapsed
OLDNEW
« no previous file with comments | « experimental/telemetry_mini/android_go_stories.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698