Skip to content

Commit

Permalink
Trace buckets (#531)
Browse files Browse the repository at this point in the history
* Allow each pass to save its own trace
  • Loading branch information
surma authored and paulirish committed Jul 28, 2016
1 parent 50c3ced commit 1275762
Show file tree
Hide file tree
Showing 16 changed files with 110 additions and 47 deletions.
9 changes: 9 additions & 0 deletions lighthouse-core/audits/audit.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,16 @@
*/
'use strict';

const DEFAULT_TRACE = 'defaultPass';

class Audit {
/**
* @return {!String}
*/
static get DEFAULT_TRACE() {
return DEFAULT_TRACE;
}

/**
* @return {!AuditMeta}
*/
Expand Down
5 changes: 3 additions & 2 deletions lighthouse-core/audits/estimated-input-latency.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ class EstimatedInputLatency extends Audit {
// Use speedline's first paint as start of range for input latency check.
const startTime = artifacts.Speedline.first;

const trace = artifacts.traceContents;
const trace = artifacts.traces[this.DEFAULT_TRACE] &&
artifacts.traces[this.DEFAULT_TRACE].traceContents;
const tracingProcessor = new TracingProcessor();
const model = tracingProcessor.init(artifacts.traceContents);
const model = tracingProcessor.init(trace);
const latencyPercentiles = TracingProcessor.getRiskToResponsiveness(model, trace, startTime);

const ninetieth = latencyPercentiles.find(result => result.percentile === 0.9);
Expand Down
5 changes: 3 additions & 2 deletions lighthouse-core/audits/first-meaningful-paint.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,12 @@ class FirstMeaningfulPaint extends Audit {
*/
static audit(artifacts) {
return new Promise((resolve, reject) => {
if (!artifacts.traceContents || !Array.isArray(artifacts.traceContents)) {
const traceContents = artifacts.traces[this.DEFAULT_TRACE].traceContents;
if (!traceContents || !Array.isArray(traceContents)) {
throw new Error(FAILURE_MESSAGE);
}

const evts = this.collectEvents(artifacts.traceContents);
const evts = this.collectEvents(traceContents);

const navStart = evts.navigationStart;
const fCP = evts.firstContentfulPaint;
Expand Down
5 changes: 3 additions & 2 deletions lighthouse-core/audits/time-to-interactive.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ class TTIMetric extends Audit {

// Process the trace
const tracingProcessor = new TracingProcessor();
const model = tracingProcessor.init(artifacts.traceContents);
const traceContents = artifacts.traces[Audit.DEFAULT_TRACE].traceContents;
const model = tracingProcessor.init(traceContents);
const endOfTraceTime = model.bounds.max;

// TODO: Wait for DOMContentLoadedEndEvent
Expand Down Expand Up @@ -109,7 +110,7 @@ class TTIMetric extends Audit {
}
// Get our expected latency for the time window
const latencies = TracingProcessor.getRiskToResponsiveness(
model, artifacts.traceContents, startTime, endTime, percentiles);
model, traceContents, startTime, endTime, percentiles);
const estLatency = latencies[0].time.toFixed(2);
foundLatencies.push({
estLatency: estLatency,
Expand Down
8 changes: 5 additions & 3 deletions lighthouse-core/audits/user-timings.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,14 @@ class UserTimings extends Audit {
*/
static audit(artifacts) {
return new Promise((resolve, reject) => {
if (!artifacts.traceContents || !Array.isArray(artifacts.traceContents)) {
const traceContents =
artifacts.traces[this.DEFAULT_TRACE] &&
artifacts.traces[this.DEFAULT_TRACE].traceContents;
if (!traceContents || !Array.isArray(traceContents)) {
throw new Error(FAILURE_MESSAGE);
}

const userTimings = filterTrace(artifacts.traceContents);

const userTimings = filterTrace(traceContents);
resolve(UserTimings.generateAuditResult({
rawValue: userTimings.length,
extendedInfo: {
Expand Down
5 changes: 1 addition & 4 deletions lighthouse-core/closure/typedefs/Artifacts.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,7 @@ Artifacts.prototype.HTMLWithoutJavaScript;
Artifacts.prototype.HTTPS;

/** @type {!Array<!Object>} */
Artifacts.prototype.networkRecords;

/** @type {?} */
Artifacts.prototype.traceContents;
Artifacts.prototype.traces;

/** @type {!ManifestNode<(!Manifest|undefined)>} */
Artifacts.prototype.Manifest;
Expand Down
1 change: 0 additions & 1 deletion lighthouse-core/config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"passes": [{
"network": true,
"trace": true,
"loadDataName": "first-pass",
"loadPage": true,
"gatherers": [
"url",
Expand Down
9 changes: 7 additions & 2 deletions lighthouse-core/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,13 @@ function expandArtifacts(artifacts) {
const expandedArtifacts = Object.assign({}, artifacts);

// currently only trace logs and performance logs should be imported
if (artifacts.traceContents) {
expandedArtifacts.traceContents = require(artifacts.traceContents);
if (artifacts.traces) {
Object.keys(artifacts.traces).forEach(key => {
if (artifacts.traces[key].traceContents) {
expandedArtifacts.traces[key].traceContents =
require(artifacts.traces[key].traceContents);
}
});
}
if (artifacts.performanceLog) {
expandedArtifacts.CriticalRequestChains =
Expand Down
23 changes: 16 additions & 7 deletions lighthouse-core/driver/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
'use strict';

const log = require('../lib/log.js');
const Audit = require('../audits/audit');

class Driver {

static loadPage(driver, options) {
// Since a Page.reload command does not let a service worker take over, we
// navigate away and then come back to reload. We do not `waitForLoad` on
Expand Down Expand Up @@ -107,15 +107,19 @@ class Driver {
const driver = options.driver;
const config = options.config;
const gatherers = config.gatherers;
const loadData = {};
const loadData = {traces: {}};
let pass = Promise.resolve();
let traceName = Audit.DEFAULT_TRACE;
if (config.traceName) {
traceName = config.traceName;
}

if (config.trace) {
pass = pass.then(_ => {
log.log('status', 'Gathering: trace');
log.log('status', `Gathering: trace "${traceName}"`);
return driver.endTrace().then(traceContents => {
loadData.traceContents = traceContents;
log.log('statusEnd', 'Gathering: trace');
loadData.traces[traceName] = {traceContents};
log.log('statusEnd', `Gathering: trace "${traceName}"`);
});
});
}
Expand All @@ -136,6 +140,9 @@ class Driver {
return chain.then(_ => {
const status = `Gathering: ${gatherer.name}`;
log.log('status', status);
if (config.trace) {
loadData.traceContents = loadData.traces[traceName].traceContents;
}
return Promise.resolve(gatherer.afterPass(options, loadData)).then(ret => {
log.log('statusEnd', status);
return ret;
Expand All @@ -155,7 +162,7 @@ class Driver {

static run(passes, options) {
const driver = options.driver;
const tracingData = {};
const tracingData = {traces: {}};

if (typeof options.url !== 'string' || options.url.length === 0) {
return Promise.reject(new Error('You must provide a url to the driver'));
Expand Down Expand Up @@ -190,6 +197,9 @@ class Driver {
.then(_ => this.pass(runOptions))
.then(_ => this.afterPass(runOptions))
.then(loadData => {
// Need to manually merge traces property before
// merging loadDat into tracingData to avoid data loss.
Object.assign(loadData.traces, tracingData.traces);
Object.assign(tracingData, loadData);
})
.then(_ => this.tearDown(runOptions));
Expand All @@ -212,7 +222,6 @@ class Driver {
artifacts[gatherer.name] = gatherer.artifact;
});
});

return artifacts;
});
}
Expand Down
4 changes: 2 additions & 2 deletions lighthouse-core/test/audits/estimated-input-latency.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const traceContents = require('../fixtures/traces/progressive-app.json');
describe('Performance: estimated-input-latency audit', () => {
it('scores a -1 with invalid trace data', () => {
const output = Audit.audit({
traceContents: '[{"pid": 15256,"tid": 1295,"t',
traces: {[Audit.DEFAULT_TRACE]: {traceContents: '[{"pid": 15256,"tid": 1295,"t'}},
Speedline: {
first: 500
}
Expand All @@ -35,7 +35,7 @@ describe('Performance: estimated-input-latency audit', () => {

it('evaluates valid input correctly', () => {
const output = Audit.audit({
traceContents,
traces: {[Audit.DEFAULT_TRACE]: {traceContents}},
Speedline: {
first: 500
}
Expand Down
9 changes: 5 additions & 4 deletions lighthouse-core/test/audits/first-meaningful-paint.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@ describe('Performance: first-meaningful-paint audit', () => {
it('processes a valid trace file', done => {
const traceData = require('../fixtures/traces/progressive-app.json');
assert.doesNotThrow(_ => {
Audit.audit({traceContents: traceData}).then(response => {
fmpResult = response;
done();
});
Audit.audit({traces: {[Audit.DEFAULT_TRACE]: {traceContents: traceData}}})
.then(response => {
fmpResult = response;
done();
});
});
});

Expand Down
14 changes: 10 additions & 4 deletions lighthouse-core/test/audits/time-to-interactive.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ const speedlineGather = new SpeedlineGather();
describe('Performance: time-to-interactive audit', () => {
it('scores a -1 with invalid trace data', () => {
return Audit.audit({
traceContents: '[{"pid": 15256,"tid": 1295,"t',
traces: {
[Audit.DEFAULT_TRACE]: {
traceContents: '[{"pid": 15256,"tid": 1295,"t'
}
},
Speedline: {
first: 500
}
Expand All @@ -37,11 +41,13 @@ describe('Performance: time-to-interactive audit', () => {
});

it('evaluates valid input correctly', () => {
let artifacts = {
traceContents: traceContents
};
let artifacts = {traceContents};
return speedlineGather.afterPass({}, artifacts).then(_ => {
artifacts.Speedline = speedlineGather.artifact;
// This is usually done by the driver
artifacts.traces = {
[Audit.DEFAULT_TRACE]: {traceContents}
};
return Audit.audit(artifacts).then(output => {
assert.equal(output.rawValue, '1105.8');
assert.equal(output.extendedInfo.value.expectedLatencyAtTTI, '20.72');
Expand Down
19 changes: 10 additions & 9 deletions lighthouse-core/test/audits/user-timing.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@ describe('Performance: user-timings audit', () => {
});

it('evaluates valid input correctly', () => {
return Audit.audit({traceContents}).then(response => {
assert.equal(response.score, 2);
assert.ok(!Number.isNaN(response.extendedInfo.value[0].startTime));
assert.ok(typeof response.extendedInfo.value[0].endTime === 'undefined');
assert.ok(typeof response.extendedInfo.value[0].duration === 'undefined');
assert.ok(!Number.isNaN(response.extendedInfo.value[1].startTime));
assert.ok(!Number.isNaN(response.extendedInfo.value[1].endTime));
assert.ok(!Number.isNaN(response.extendedInfo.value[1].duration));
});
return Audit.audit({traces: {[Audit.DEFAULT_TRACE]: {traceContents}}})
.then(response => {
assert.equal(response.score, 2);
assert.ok(!Number.isNaN(response.extendedInfo.value[0].startTime));
assert.ok(typeof response.extendedInfo.value[0].endTime === 'undefined');
assert.ok(typeof response.extendedInfo.value[0].duration === 'undefined');
assert.ok(!Number.isNaN(response.extendedInfo.value[1].startTime));
assert.ok(!Number.isNaN(response.extendedInfo.value[1].endTime));
assert.ok(!Number.isNaN(response.extendedInfo.value[1].duration));
});
});
});
8 changes: 6 additions & 2 deletions lighthouse-core/test/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,16 @@ describe('Config', () => {
it('expands artifacts', () => {
const config = new Config({
artifacts: {
traceContents: path.resolve(__dirname, '../fixtures/traces/trace-user-timings.json'),
traces: {
firstPass: {
traceContents: path.resolve(__dirname, '../fixtures/traces/trace-user-timings.json')
}
},
performanceLog: path.resolve(__dirname, '../fixtures/perflog.json')
}
});
const traceUserTimings = require('../fixtures/traces/trace-user-timings.json');
assert.deepStrictEqual(config.artifacts.traceContents, traceUserTimings);
assert.deepStrictEqual(config.artifacts.traces.firstPass.traceContents, traceUserTimings);
assert.ok(config.artifacts.CriticalRequestChains);
assert.ok(config.artifacts.CriticalRequestChains['93149.1']);
assert.ok(config.artifacts.CriticalRequestChains['93149.1'].request);
Expand Down
26 changes: 24 additions & 2 deletions lighthouse-core/test/driver/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

const Gather = require('../../driver/gatherers/gather');
const Driver = require('../../driver');
const Audit = require('../../audits/audit');
const assert = require('assert');

class TestGatherer extends Gather {
Expand Down Expand Up @@ -159,7 +160,27 @@ describe('Driver', function() {

return Driver.afterPass({driver, config}).then(vals => {
assert.equal(calledTrace, true);
assert.deepEqual(vals.traceContents, {x: 1});
assert.deepEqual(vals.traces[Audit.DEFAULT_TRACE].traceContents, {x: 1});
});
});

it('respects trace names', () => {
const driver = {
endTrace() {
return Promise.resolve({x: 1});
}
};

const config = {
trace: true,
traceName: 'notTheDefaultPass',
gatherers: [{
afterPass() {}
}]
};

return Driver.afterPass({driver, config}).then(vals => {
assert.deepEqual(vals.traces.notTheDefaultPass.traceContents, {x: 1});
});
});

Expand Down Expand Up @@ -221,13 +242,14 @@ describe('Driver', function() {
const passes = [{
network: true,
trace: true,
loadDataName: 'first-pass',
traceName: 'firstPass',
loadPage: true,
gatherers: [
t1
]
}, {
loadPage: true,
traceName: 'secondPass',
gatherers: [
t2
]
Expand Down
7 changes: 6 additions & 1 deletion lighthouse-core/test/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
const Runner = require('../runner');
const fakeDriver = require('./driver/fake-driver');
const Config = require('../config');
const Audit = require('../audits/audit');
const assert = require('assert');
const path = require('path');

Expand Down Expand Up @@ -86,8 +87,12 @@ describe('Runner', () => {
],

artifacts: {
traceContents: path.join(__dirname,
traces: {
[Audit.DEFAULT_TRACE]: {
traceContents: path.join(__dirname,
'/fixtures/traces/trace-user-timings.json')
}
}
}
}, flags.auditWhitelist);

Expand Down

0 comments on commit 1275762

Please sign in to comment.