Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests(lantern): use TraceEngine directly in test fixtures #16057

Merged
merged 3 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ module.exports = {
vars: 'all',
args: 'after-used',
argsIgnorePattern: '(^reject$|^_+$)',
varsIgnorePattern: '(^_$|^LH$|^Lantern$)',
varsIgnorePattern: '(^_$|^LH$|^Lantern$|^TraceEngine$)',
}],
'no-cond-assign': 2,
'space-infix-ops': 2,
Expand Down
2 changes: 1 addition & 1 deletion core/computed/metrics/lantern-metric.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ async function getComputationDataParamsFromTrace(data, context) {

const graph = await PageDependencyGraph.request({...data, fromTrace: true}, context);
const traceEngineResult = await TraceEngineResult.request(data, context);
const processedNavigation = createProcessedNavigation(traceEngineResult);
const processedNavigation = createProcessedNavigation(traceEngineResult.data);
const simulator = data.simulator || (await LoadSimulator.request(data, context));

return {simulator, graph, processedNavigation};
Expand Down
5 changes: 3 additions & 2 deletions core/computed/page-dependency-graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ class PageDependencyGraph {

if (data.fromTrace) {
const traceEngineResult = await TraceEngineResult.request({trace}, context);
const requests = TraceEngineComputationData.createNetworkRequests(trace, traceEngineResult);
const traceEngineData = traceEngineResult.data;
const requests = TraceEngineComputationData.createNetworkRequests(trace, traceEngineData);
const graph =
TraceEngineComputationData.createGraph(requests, trace, traceEngineResult, URL);
TraceEngineComputationData.createGraph(requests, trace, traceEngineData, URL);
return graph;
}

Expand Down
25 changes: 5 additions & 20 deletions core/computed/trace-engine-result.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,6 @@ import {CumulativeLayoutShift} from './metrics/cumulative-layout-shift.js';
import {ProcessedTrace} from './processed-trace.js';
import * as LH from '../../types/lh.js';

/** @typedef {typeof ENABLED_HANDLERS} EnabledHandlers */

const ENABLED_HANDLERS = {
AuctionWorklets: TraceEngine.TraceHandlers.AuctionWorklets,
Initiators: TraceEngine.TraceHandlers.Initiators,
LayoutShifts: TraceEngine.TraceHandlers.LayoutShifts,
NetworkRequests: TraceEngine.TraceHandlers.NetworkRequests,
Renderer: TraceEngine.TraceHandlers.Renderer,
Samples: TraceEngine.TraceHandlers.Samples,
Screenshots: TraceEngine.TraceHandlers.Screenshots,
PageLoadMetrics: TraceEngine.TraceHandlers.PageLoadMetrics,
Workers: TraceEngine.TraceHandlers.Workers,
};

/**
* @fileoverview Processes trace with the shared trace engine.
*/
Expand All @@ -33,15 +19,14 @@ class TraceEngineResult {
* @return {Promise<LH.Artifacts.TraceEngineResult>}
*/
static async runTraceEngine(traceEvents) {
const engine = new TraceEngine.TraceProcessor(ENABLED_HANDLERS);
const processor = TraceEngine.TraceProcessor.createWithAllHandlers();
// eslint-disable-next-line max-len
await engine.parse(/** @type {import('@paulirish/trace_engine').Types.TraceEvents.TraceEventData[]} */ (
await processor.parse(/** @type {import('@paulirish/trace_engine').Types.TraceEvents.TraceEventData[]} */ (
traceEvents
));
// TODO: use TraceEngine.TraceProcessor.createWithAllHandlers above.
if (!engine.traceParsedData) throw new Error('No data');
if (!engine.insights) throw new Error('No insights');
return {data: engine.traceParsedData, insights: engine.insights};
if (!processor.traceParsedData) throw new Error('No data');
if (!processor.insights) throw new Error('No insights');
return {data: processor.traceParsedData, insights: processor.insights};
}

/**
Expand Down
1 change: 0 additions & 1 deletion core/gather/gatherers/root-causes.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ class RootCauses extends BaseGatherer {
const rootCausesEngine = new TraceEngine.RootCauses(protocolInterface);
const layoutShiftEvents = traceParsedData.LayoutShifts.clusters.flatMap(c => c.events);
for (const event of layoutShiftEvents) {
// @ts-expect-error The data we do get in the trace processor is still enough here
const r = await rootCausesEngine.layoutShifts.rootCausesForEvent(traceParsedData, event);
if (!r) continue;

Expand Down
36 changes: 19 additions & 17 deletions core/lib/lantern/trace-engine-computation-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* SPDX-License-Identifier: Apache-2.0
*/

import * as TraceEngine from '@paulirish/trace_engine';

import * as Lantern from './types/lantern.js';
import {PageDependencyGraph} from './page-dependency-graph.js';
import {RESOURCE_TYPES} from '../network-request.js';
Expand All @@ -12,13 +14,13 @@ import {RESOURCE_TYPES} from '../network-request.js';
/** @typedef {import('@paulirish/trace_engine/models/trace/handlers/PageLoadMetricsHandler.js').MetricScore} MetricScore */

/**
* @param {LH.Artifacts.TraceEngineResult} traceEngineResult
* @param {TraceEngine.Handlers.Types.TraceParseData} traceEngineData
* @return {Lantern.Simulation.ProcessedNavigation}
*/
function createProcessedNavigation(traceEngineResult) {
const Meta = traceEngineResult.data.Meta;
function createProcessedNavigation(traceEngineData) {
const Meta = traceEngineData.Meta;
const frameId = Meta.mainFrameId;
const scoresByNav = traceEngineResult.data.PageLoadMetrics.metricScoresByFrameId.get(frameId);
const scoresByNav = traceEngineData.PageLoadMetrics.metricScoresByFrameId.get(frameId);
if (!scoresByNav) {
throw new Error('missing metric scores for main frame');
}
Expand Down Expand Up @@ -97,12 +99,12 @@ function findWorkerThreads(trace) {
}

/**
* @param {LH.Artifacts.TraceEngineResult} traceEngineResult
* @param {TraceEngine.Handlers.Types.TraceParseData} traceEngineData
* @param {Map<number, number[]>} workerThreads
* @param {import('@paulirish/trace_engine/models/trace/types/TraceEvents.js').SyntheticNetworkRequest} request
* @return {Lantern.NetworkRequest=}
*/
function createLanternRequest(traceEngineResult, workerThreads, request) {
function createLanternRequest(traceEngineData, workerThreads, request) {
if (request.args.data.connectionId === undefined ||
request.args.data.connectionReused === undefined) {
throw new Error('Trace is too old');
Expand Down Expand Up @@ -134,7 +136,7 @@ function createLanternRequest(traceEngineResult, workerThreads, request) {

// TraceEngine collects worker thread ids in a different manner than `workerThreads` does.
// AFAIK these should be equivalent, but in case they are not let's also check this for now.
if (traceEngineResult.data.Workers.workerIdByThread.has(request.tid)) {
if (traceEngineData.Workers.workerIdByThread.has(request.tid)) {
fromWorker = true;
}

Expand Down Expand Up @@ -295,16 +297,16 @@ function linkInitiators(lanternRequests) {

/**
* @param {LH.Trace} trace
* @param {LH.Artifacts.TraceEngineResult} traceEngineResult
* @param {TraceEngine.Handlers.Types.TraceParseData} traceEngineData
* @return {Lantern.NetworkRequest[]}
*/
function createNetworkRequests(trace, traceEngineResult) {
function createNetworkRequests(trace, traceEngineData) {
const workerThreads = findWorkerThreads(trace);

/** @type {Lantern.NetworkRequest[]} */
const lanternRequests = [];
for (const request of traceEngineResult.data.NetworkRequests.byTime) {
const lanternRequest = createLanternRequest(traceEngineResult, workerThreads, request);
for (const request of traceEngineData.NetworkRequests.byTime) {
const lanternRequest = createLanternRequest(traceEngineData, workerThreads, request);
if (lanternRequest) {
lanternRequests.push(lanternRequest);
}
Expand Down Expand Up @@ -389,11 +391,11 @@ function createNetworkRequests(trace, traceEngineResult) {

/**
* @param {LH.Trace} trace
* @param {LH.Artifacts.TraceEngineResult} traceEngineResult
* @param {TraceEngine.Handlers.Types.TraceParseData} traceEngineData
* @return {LH.TraceEvent[]}
*/
function collectMainThreadEvents(trace, traceEngineResult) {
const Meta = traceEngineResult.data.Meta;
function collectMainThreadEvents(trace, traceEngineData) {
const Meta = traceEngineData.Meta;
const mainFramePids = Meta.mainFrameNavigations.length
? new Set(Meta.mainFrameNavigations.map(nav => nav.pid))
: Meta.topLevelRendererIds;
Expand Down Expand Up @@ -430,11 +432,11 @@ function collectMainThreadEvents(trace, traceEngineResult) {
/**
* @param {Lantern.NetworkRequest[]} requests
* @param {LH.Trace} trace
* @param {LH.Artifacts.TraceEngineResult} traceEngineResult
* @param {TraceEngine.Handlers.Types.TraceParseData} traceEngineData
* @param {LH.Artifacts.URL=} URL
*/
function createGraph(requests, trace, traceEngineResult, URL) {
const mainThreadEvents = collectMainThreadEvents(trace, traceEngineResult);
function createGraph(requests, trace, traceEngineData, URL) {
const mainThreadEvents = collectMainThreadEvents(trace, traceEngineData);

// URL defines the initial request that the Lantern graph starts at (the root node) and the
// main document request. These are equal if there are no redirects.
Expand Down
28 changes: 17 additions & 11 deletions core/test/lib/lantern/metrics/metric-test-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,38 @@
* SPDX-License-Identifier: Apache-2.0
*/

import {TraceEngineResult} from '../../../../computed/trace-engine-result.js';
import * as TraceEngine from '@paulirish/trace_engine';

import {NetworkAnalyzer} from '../../../../lib/lantern/simulator/network-analyzer.js';
import {Simulator} from '../../../../lib/lantern/simulator/simulator.js';
import * as TraceEngineComputationData from '../../../../lib/lantern/trace-engine-computation-data.js';
import * as Lantern from '../../../../lib/lantern/types/lantern.js';

/** @typedef {Lantern.NetworkRequest<import('@paulirish/trace_engine/models/trace/types/TraceEvents.js').SyntheticNetworkRequest>} NetworkRequest */

// TODO(15841): remove usage of Lighthouse code to create test data
/**
* @param {TraceEngine.Types.TraceEvents.TraceEventData[]} traceEvents
*/
async function runTraceEngine(traceEvents) {
const processor = TraceEngine.Processor.TraceProcessor.createWithAllHandlers();
await processor.parse(traceEvents);
if (!processor.traceParsedData) throw new Error('No data');
return processor.traceParsedData;
}

/**
* @param {{trace: LH.Trace, settings?: LH.Config.Settings, URL?: LH.Artifacts.URL}} opts
*/
async function getComputationDataFromFixture({trace, settings, URL}) {
settings = settings ?? /** @type {LH.Config.Settings} */({});
if (!settings.throttlingMethod) settings.throttlingMethod = 'simulate';

const context = {settings, computedCache: new Map()};
const traceEngineResult = await TraceEngineResult.request({trace}, context);
const requests = TraceEngineComputationData.createNetworkRequests(trace, traceEngineResult);
const traceEngineData = await runTraceEngine(
/** @type {TraceEngine.Types.TraceEvents.TraceEventData[]} */ (trace.traceEvents)
);
const requests = TraceEngineComputationData.createNetworkRequests(trace, traceEngineData);
const networkAnalysis = NetworkAnalyzer.analyze(requests);

return {
simulator: Simulator.createSimulator({...settings, networkAnalysis}),
graph: TraceEngineComputationData.createGraph(requests, trace, traceEngineResult, URL),
processedNavigation: TraceEngineComputationData.createProcessedNavigation(traceEngineResult),
graph: TraceEngineComputationData.createGraph(requests, trace, traceEngineData, URL),
processedNavigation: TraceEngineComputationData.createProcessedNavigation(traceEngineData),
};
}

Expand Down
5 changes: 2 additions & 3 deletions types/artifacts.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import speedline from 'speedline-core';
import * as CDTSourceMap from '../core/lib/cdt/generated/SourceMap.js';
import {ArbitraryEqualityMap} from '../core/lib/arbitrary-equality-map.js';
import type { TaskNode as _TaskNode } from '../core/lib/tracehouse/main-thread-tasks.js';
import type {EnabledHandlers} from '../core/computed/trace-engine-result.js';
import AuditDetails from './lhr/audit-details.js'
import Config from './config.js';
import Gatherer from './gatherer.js';
Expand Down Expand Up @@ -511,8 +510,8 @@ declare module Artifacts {
}

interface TraceEngineResult {
data: TraceEngine.Handlers.Types.EnabledHandlerDataWithMeta<EnabledHandlers>;
insights: TraceEngine.Insights.Types.TraceInsightData<EnabledHandlers>;
data: TraceEngine.Handlers.Types.TraceParseData;
insights: TraceEngine.Insights.Types.TraceInsightData<typeof TraceEngine.Handlers.ModelHandlers>;
}

interface TraceEngineRootCauses {
Expand Down
Loading