diff --git a/testing/raptor/raptor/control_server.py b/testing/raptor/raptor/control_server.py index 78d7d41673bf..4e247bd0418d 100644 --- a/testing/raptor/raptor/control_server.py +++ b/testing/raptor/raptor/control_server.py @@ -10,6 +10,7 @@ import BaseHTTPServer import datetime import json import os +import shutil import socket import threading import time @@ -23,7 +24,7 @@ here = os.path.abspath(os.path.dirname(__file__)) def MakeCustomHandlerClass(results_handler, shutdown_browser, - write_raw_gecko_profile, + handle_gecko_profile, background_app, foreground_app): @@ -107,7 +108,7 @@ def MakeCustomHandlerClass(results_handler, def __init__(self, *args, **kwargs): self.results_handler = results_handler self.shutdown_browser = shutdown_browser - self.write_raw_gecko_profile = write_raw_gecko_profile + self.handle_gecko_profile = handle_gecko_profile self.background_app = background_app self.foreground_app = foreground_app super(MyHandler, self).__init__(*args, **kwargs) @@ -175,12 +176,11 @@ def MakeCustomHandlerClass(results_handler, MyHandler.wait_after_messages[wait_key] = True if data['type'] == "webext_gecko_profile": - # received gecko profiling results - _test = str(data['data'][0]) - _pagecycle = str(data['data'][1]) - _raw_profile = data['data'][2] - LOG.info("received gecko profile for test %s pagecycle %s" % (_test, _pagecycle)) - self.write_raw_gecko_profile(_test, _pagecycle, _raw_profile) + # received file name of the saved gecko profile + filename = str(data['data']) + LOG.info("received gecko profile filename: {}".format(filename)) + self.handle_gecko_profile(filename) + elif data['type'] == 'webext_results': LOG.info("received " + data['type'] + ": " + str(data['data'])) self.results_handler.add(data['data']) @@ -282,6 +282,7 @@ class RaptorControlServer(): self.app_name = None self.gecko_profile_dir = None self.debug_mode = debug_mode + self.user_profile = None def start(self): config_dir = os.path.join(here, 'tests') @@ -297,7 +298,7 @@ class RaptorControlServer(): server_class = ThreadedHTTPServer handler_class = MakeCustomHandlerClass(self.results_handler, self.shutdown_browser, - self.write_raw_gecko_profile, + self.handle_gecko_profile, self.background_app, self.foreground_app) @@ -325,17 +326,12 @@ class RaptorControlServer(): self.kill_thread.daemon = True self.kill_thread.start() - def write_raw_gecko_profile(self, test, pagecycle, profile): - profile_file = '%s_pagecycle_%s.profile' % (test, pagecycle) - profile_path = os.path.join(self.gecko_profile_dir, profile_file) - LOG.info("writing raw gecko profile to disk: %s" % str(profile_path)) - - try: - with open(profile_path, 'w') as profile_file: - json.dump(profile, profile_file) - profile_file.close() - except Exception: - LOG.critical("Encountered an exception whie writing raw gecko profile to disk") + def handle_gecko_profile(self, filename): + # Move the stored profile to a location outside the Firefox profile + source_path = os.path.join(self.user_profile.profile, "profiler", filename) + target_path = os.path.join(self.gecko_profile_dir, filename) + shutil.move(source_path, target_path) + LOG.info("moved gecko profile to {}".format(target_path)) def is_app_in_background(self): # Get the app view state: foreground->False, background->True diff --git a/testing/raptor/raptor/raptor.py b/testing/raptor/raptor/raptor.py index 1321a20fc0a4..665adac63b70 100644 --- a/testing/raptor/raptor/raptor.py +++ b/testing/raptor/raptor/raptor.py @@ -135,11 +135,11 @@ class Raptor(object): LOG.info("main raptor init, config is: %s" % str(self.config)) - # create results holder + # setup the control server self.results_handler = RaptorResultsHandler() + self.start_control_server() self.build_browser_profile() - self.start_control_server() @property def profile_data_dir(self): @@ -267,8 +267,9 @@ class Raptor(object): LOG.info("Merging profile: {}".format(path)) self.profile.merge(path) - # add profile dir to our config + # share the profile dir with the config and the control server self.config['local_profile_dir'] = self.profile.profile + self.control_server.user_profile = self.profile def start_control_server(self): self.control_server = RaptorControlServer(self.results_handler, self.debug_mode) @@ -519,6 +520,7 @@ class RaptorDesktop(Raptor): def start_runner_proc(self): # launch the browser via our previously-created runner self.runner.start() + proc = self.runner.process_handler self.output_handler.proc = proc @@ -665,9 +667,10 @@ class RaptorDesktopFirefox(RaptorDesktop): # if geckoProfile is enabled, initialize it if self.config['gecko_profile'] is True: self._init_gecko_profiling(test) - # tell the control server the gecko_profile dir; the control server will - # receive the actual gecko profiles from the web ext and will write them - # to disk; then profiles are picked up by gecko_profile.symbolicate + # tell the control server the gecko_profile dir; the control server + # will receive the filename of the stored gecko profile from the web + # extension, and will move it out of the browser user profile to + # this directory; where it is picked-up by gecko_profile.symbolicate self.control_server.gecko_profile_dir = self.gecko_profiler.gecko_profile_dir diff --git a/testing/raptor/webext/raptor/runner.js b/testing/raptor/webext/raptor/runner.js index fbaf0ca01ff1..5c75513aea90 100644 --- a/testing/raptor/webext/raptor/runner.js +++ b/testing/raptor/webext/raptor/runner.js @@ -360,15 +360,15 @@ async function stopGeckoProfiling() { } async function getGeckoProfile() { - // get the profile and send to control server - postToControlServer("status", "retrieving gecko profile"); - let arrayBuffer = await browser.geckoProfiler.getProfileAsArrayBuffer(); - let textDecoder = new TextDecoder(); - let profile = JSON.parse(textDecoder.decode(arrayBuffer)); - raptorLog(profile); - postToControlServer("gecko_profile", [testName, pageCycle, profile]); - // stop the profiler; must stop so it clears before next cycle + // trigger saving the gecko profile, and send the file name to the control server + postToControlServer("status", "saving gecko profile"); + let fileName = `${testName}_pagecycle_${pageCycle}.profile`; + await browser.geckoProfiler.dumpProfileToFile(fileName); + postToControlServer("gecko_profile", fileName); + + // must stop the profiler so it clears the buffer before next cycle await stopGeckoProfiling(); + // resume if we have more pagecycles left if (pageCycle + 1 <= pageCycles) { await startGeckoProfiling();