From d42f32cc61c6d9921f9407dac6fd1831f4738b9c Mon Sep 17 00:00:00 2001 From: Omar Griffin Date: Fri, 7 Dec 2018 10:23:43 -0800 Subject: [PATCH] feat: optionally save complete performance log in chrome benchpress tests (#27551) If RAW_PERFLOG_PATH is passed in as an option, benchpress saves chrome's performance log to a json file. This allows developers to download the json file and upload it to their browser to get a breakdown of chrome-side resource usage during a test. PR Close #27551 --- packages/benchpress/src/common_options.ts | 4 ++- .../src/webdriver/chrome_driver_extension.ts | 25 +++++++++++++------ .../webdriver/chrome_driver_extension_spec.ts | 3 ++- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/packages/benchpress/src/common_options.ts b/packages/benchpress/src/common_options.ts index 12125c962b..15e63e0314 100644 --- a/packages/benchpress/src/common_options.ts +++ b/packages/benchpress/src/common_options.ts @@ -26,6 +26,7 @@ export class Options { static RECEIVED_DATA = new InjectionToken('Options.receivedData'); static REQUEST_COUNT = new InjectionToken('Options.requestCount'); static CAPTURE_FRAMES = new InjectionToken('Options.frameCapture'); + static RAW_PERFLOG_PATH = new InjectionToken('Options.rawPerflogPath'); static DEFAULT_PROVIDERS = [ {provide: Options.DEFAULT_DESCRIPTION, useValue: {}}, {provide: Options.SAMPLE_DESCRIPTION, useValue: {}}, @@ -36,7 +37,8 @@ export class Options { {provide: Options.RECEIVED_DATA, useValue: false}, {provide: Options.REQUEST_COUNT, useValue: false}, {provide: Options.CAPTURE_FRAMES, useValue: false}, - {provide: Options.WRITE_FILE, useValue: writeFile} + {provide: Options.WRITE_FILE, useValue: writeFile}, + {provide: Options.RAW_PERFLOG_PATH, useValue: null} ]; } diff --git a/packages/benchpress/src/webdriver/chrome_driver_extension.ts b/packages/benchpress/src/webdriver/chrome_driver_extension.ts index 066958afd0..9dba35fb28 100644 --- a/packages/benchpress/src/webdriver/chrome_driver_extension.ts +++ b/packages/benchpress/src/webdriver/chrome_driver_extension.ts @@ -7,6 +7,7 @@ */ import {Inject, Injectable, StaticProvider} from '@angular/core'; +import * as fs from 'fs'; import {Options} from '../common_options'; import {WebDriverAdapter} from '../web_driver_adapter'; @@ -23,15 +24,19 @@ import {PerfLogEvent, PerfLogFeatures, WebDriverExtension} from '../web_driver_e export class ChromeDriverExtension extends WebDriverExtension { static PROVIDERS = [{ provide: ChromeDriverExtension, - deps: [WebDriverAdapter, Options.USER_AGENT] + deps: [WebDriverAdapter, Options.USER_AGENT, Options.RAW_PERFLOG_PATH] }]; private _majorChromeVersion: number; private _firstRun = true; + private _rawPerflogPath: string|null; - constructor(private _driver: WebDriverAdapter, @Inject(Options.USER_AGENT) userAgent: string) { + constructor( + private driver: WebDriverAdapter, @Inject(Options.USER_AGENT) userAgent: string, + @Inject(Options.RAW_PERFLOG_PATH) rawPerflogPath: string|null) { super(); this._majorChromeVersion = this._parseChromeVersion(userAgent); + this._rawPerflogPath = rawPerflogPath; } private _parseChromeVersion(userAgent: string): number { @@ -49,16 +54,16 @@ export class ChromeDriverExtension extends WebDriverExtension { return parseInt(v, 10); } - gc() { return this._driver.executeScript('window.gc()'); } + gc() { return this.driver.executeScript('window.gc()'); } async timeBegin(name: string): Promise { if (this._firstRun) { this._firstRun = false; // Before the first run, read out the existing performance logs // so that the chrome buffer does not fill up. - await this._driver.logs('performance'); + await this.driver.logs('performance'); } - return this._driver.executeScript(`performance.mark('${name}-bpstart');`); + return this.driver.executeScript(`performance.mark('${name}-bpstart');`); } timeEnd(name: string, restartName: string|null = null): Promise { @@ -66,7 +71,7 @@ export class ChromeDriverExtension extends WebDriverExtension { if (restartName) { script += `performance.mark('${restartName}-bpstart');`; } - return this._driver.executeScript(script); + return this.driver.executeScript(script); } // See [Chrome Trace Event @@ -74,8 +79,8 @@ export class ChromeDriverExtension extends WebDriverExtension { readPerfLog(): Promise { // TODO(tbosch): Chromedriver bug https://code.google.com/p/chromedriver/issues/detail?id=1098 // Need to execute at least one command so that the browser logs can be read out! - return this._driver.executeScript('1+1') - .then((_) => this._driver.logs('performance')) + return this.driver.executeScript('1+1') + .then((_) => this.driver.logs('performance')) .then((entries) => { const events: PerfLogEvent[] = []; entries.forEach((entry: any) => { @@ -87,6 +92,10 @@ export class ChromeDriverExtension extends WebDriverExtension { throw new Error('The DevTools trace buffer filled during the test!'); } }); + + if (this._rawPerflogPath && events.length) { + fs.appendFileSync(this._rawPerflogPath, JSON.stringify(events)); + } return this._convertPerfRecordsToEvents(events); }); } diff --git a/packages/benchpress/test/webdriver/chrome_driver_extension_spec.ts b/packages/benchpress/test/webdriver/chrome_driver_extension_spec.ts index dbe3f589b9..988352345c 100644 --- a/packages/benchpress/test/webdriver/chrome_driver_extension_spec.ts +++ b/packages/benchpress/test/webdriver/chrome_driver_extension_spec.ts @@ -47,7 +47,8 @@ import {TraceEventFactory} from '../trace_event_factory'; provide: WebDriverAdapter, useValue: new MockDriverAdapter(log, perfRecords, messageMethod) }, - {provide: Options.USER_AGENT, useValue: userAgent} + {provide: Options.USER_AGENT, useValue: userAgent}, + {provide: Options.RAW_PERFLOG_PATH, useValue: null} ]) .get(ChromeDriverExtension); return extension;