UNPKG

lighthouse

Version:

Automated auditing, performance metrics, and best practices for the web.

97 lines (85 loc) 2.8 kB
/** * @license * Copyright 2018 Google LLC * SPDX-License-Identifier: Apache-2.0 */ /** * Generates a chromium trace file from user timing measures * `threadId` can be provided to separate a series of trace events into another thread, useful * if timings do not share the same timeOrigin, but should both be "left-aligned". * Adapted from https://github.com/tdresser/performance-observer-tracing * @param {LH.Artifacts.MeasureEntry[]} entries user timing entries * @param {number=} threadId */ function generateTraceEvents(entries, threadId = 0) { if (!Array.isArray(entries)) return []; /** @type {LH.TraceEvent[]} */ const currentTrace = []; entries.sort((a, b) => a.startTime - b.startTime); entries.forEach((entry, i) => { /** @type {LH.TraceEvent} */ const startEvt = { // 1) Remove 'lh:' for readability // 2) Colons in user_timing names get special handling in traceviewer we don't want. https://goo.gl/m23Vz7 // Replace with a 'Modifier letter colon' ;) name: entry.name.replace('lh:', '').replace(/:/g, '\ua789'), cat: 'blink.user_timing', ts: entry.startTime * 1000, args: {}, dur: 0, pid: 0, tid: threadId, ph: 'b', id: '0x' + (i++).toString(16), }; const endEvt = JSON.parse(JSON.stringify(startEvt)); endEvt.ph = 'e'; endEvt.ts = startEvt.ts + (entry.duration * 1000); currentTrace.push(startEvt); currentTrace.push(endEvt); }); // Add labels /** @type {LH.TraceEvent} */ const metaEvtBase = { pid: 0, tid: threadId, ts: 0, dur: 0, ph: 'M', cat: '__metadata', name: 'process_labels', args: {labels: 'Default'}, }; currentTrace.push(Object.assign({}, metaEvtBase, {args: {labels: 'Lighthouse Timing'}})); // Only inject TracingStartedInBrowser once if (threadId === 0) { currentTrace.push(Object.assign({}, metaEvtBase, { 'cat': 'disabled-by-default-devtools.timeline', 'name': 'TracingStartedInBrowser', 'ph': 'I', 'args': {'data': { 'frameTreeNodeId': 1, 'persistentIds': true, 'frames': [], }}, })); } return currentTrace; } /** * Writes a trace file to disk * @param {LH.Result} lhr * @return {string} */ function createTraceString(lhr) { const gatherEntries = lhr.timing.entries.filter(entry => entry.gather); const entries = lhr.timing.entries.filter(entry => !gatherEntries.includes(entry)); const auditEvents = generateTraceEvents(entries); const gatherEvents = generateTraceEvents(gatherEntries, 10); const events = [...auditEvents, ...gatherEvents]; const jsonStr = `{"traceEvents":[ ${events.map(evt => JSON.stringify(evt)).join(',\n')} ]}`; return jsonStr; } export {generateTraceEvents, createTraceString};