From 97851816bcfc26fc6fb73e0beab28cc89f9b7e94 Mon Sep 17 00:00:00 2001 From: Alexei Filippov Date: Fri, 18 May 2018 18:01:56 -0700 Subject: [PATCH 1/5] core: Support traces with TracingStartedInBrowser event Since version 67 Chrome uses a new schema to describe page frame tree. The tree is encoded within TracingStartedInBrowser trace event. The patch makes lighthouse to support the new event. Legacy TracingStartedInPage event is going to the removed soon. --- .../gather/computed/trace-of-tab.js | 39 +++++++++++---- .../threeframes-blank_content_more.json | 2 +- .../test/gather/computed/trace-of-tab-test.js | 50 +++++++++++++++++++ typings/externs.d.ts | 6 +++ 4 files changed, 87 insertions(+), 10 deletions(-) diff --git a/lighthouse-core/gather/computed/trace-of-tab.js b/lighthouse-core/gather/computed/trace-of-tab.js index 62b6ce86f3e4..dc381f57a6ab 100644 --- a/lighthouse-core/gather/computed/trace-of-tab.js +++ b/lighthouse-core/gather/computed/trace-of-tab.js @@ -42,21 +42,42 @@ class TraceOfTab extends ComputedArtifact { // *must* be stable to keep events correctly nested. /** @type Array */ const keyEvents = trace.traceEvents - .filter(e => { - return e.cat.includes('blink.user_timing') || + .filter(e => + e.cat.includes('blink.user_timing') || e.cat.includes('loading') || e.cat.includes('devtools.timeline') || - e.name === 'TracingStartedInPage'; - }) + e.cat === '__metadata') // @ts-ignore - stableSort added to Array by WebInspector. .stableSort((event0, event1) => event0.ts - event1.ts); - // The first TracingStartedInPage in the trace is definitely our renderer thread of interest - // Beware: the tracingStartedInPage event can appear slightly after a navigationStart - const startedInPageEvt = keyEvents.find(e => e.name === 'TracingStartedInPage'); + // Find out the inspected page frame. + /** @type {LH.TraceEvent|undefined} */ + let startedInPageEvt; + const startedInBrowserEvt = keyEvents.find(e => e.name === 'TracingStartedInBrowser'); + if (startedInBrowserEvt && startedInBrowserEvt.args.data && + startedInBrowserEvt.args.data.persistentIds) { + const mainFrame = (startedInBrowserEvt.args.data.frames || []).find(frame => !frame.parent); + const pid = mainFrame && mainFrame.processId; + const threadNameEvt = keyEvents.find(e => e.pid === pid && e.ph === 'M' && + e.cat === '__metadata' && e.name === 'thread_name' && + // @ts-ignore - property chain exists for 'thread_name' event. + e.args.name === 'CrRendererMain'); + startedInPageEvt = mainFrame && threadNameEvt ? + Object.assign({}, startedInBrowserEvt, { + pid, tid: threadNameEvt.tid, name: 'TracingStartedInPage', + args: {data: {page: mainFrame.frame}}}) : + undefined; + } + // Support legacy browser versions that do not emit TracingStartedInBrowser event. + if (!startedInPageEvt) { + // The first TracingStartedInPage in the trace is definitely our renderer thread of interest + // Beware: the tracingStartedInPage event can appear slightly after a navigationStart + startedInPageEvt = keyEvents.find(e => e.name === 'TracingStartedInPage'); + } if (!startedInPageEvt) throw new LHError(LHError.errors.NO_TRACING_STARTED); // @ts-ignore - property chain exists for 'TracingStartedInPage' event. const frameId = startedInPageEvt.args.data.page; + // Filter to just events matching the frame ID for sanity const frameEvents = keyEvents.filter(e => e.args.frame === frameId); @@ -106,12 +127,12 @@ class TraceOfTab extends ComputedArtifact { // stable-sort events to keep them correctly nested. /** @type Array */ const processEvents = trace.traceEvents - .filter(e => e.pid === startedInPageEvt.pid) + .filter(e => e.pid === /** @type {LH.TraceEvent} */ (startedInPageEvt).pid) // @ts-ignore - stableSort added to Array by WebInspector. .stableSort((event0, event1) => event0.ts - event1.ts); const mainThreadEvents = processEvents - .filter(e => e.tid === startedInPageEvt.tid); + .filter(e => e.tid === /** @type {LH.TraceEvent} */ (startedInPageEvt).tid); const traceEnd = trace.traceEvents.reduce((max, evt) => { return max.ts > evt.ts ? max : evt; diff --git a/lighthouse-core/test/fixtures/traces/threeframes-blank_content_more.json b/lighthouse-core/test/fixtures/traces/threeframes-blank_content_more.json index 38dfee3ca248..ab528381c16c 100644 --- a/lighthouse-core/test/fixtures/traces/threeframes-blank_content_more.json +++ b/lighthouse-core/test/fixtures/traces/threeframes-blank_content_more.json @@ -20,7 +20,7 @@ "tid": 1295, "ts": 900000000000, "ph": "X", - "cat": "toplevel", + "cat": "devtools.timeline", "name": "TracingStartedInPage", "args": { "data": { diff --git a/lighthouse-core/test/gather/computed/trace-of-tab-test.js b/lighthouse-core/test/gather/computed/trace-of-tab-test.js index cc0d281db0f1..77ca29474ca9 100644 --- a/lighthouse-core/test/gather/computed/trace-of-tab-test.js +++ b/lighthouse-core/test/gather/computed/trace-of-tab-test.js @@ -112,6 +112,56 @@ describe('Trace of Tab computed artifact:', () => { assert.equal(trace.firstMeaningfulPaintEvt, undefined, 'bad fmp'); }); + it('handles traces with TracingStartedInBrowser events', async () => { + const tracingStartedInBrowserTrace = { + 'traceEvents': [{ + 'pid': 69850, + 'tid': 69850, + 'ts': 2193564729582, + 'ph': 'I', + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'TracingStartedInBrowser', + 'args': {'data': { + 'frameTreeNodeId': 1, + 'persistentIds': true, + 'frames': [{ + 'frame': 'B192D1F3355A6F961EC8F0B01623C1FB', + 'url': 'http://www.example.com/', + 'name': '', + 'processId': 69920, + }], + }}, + 'tts': 1085165, + 's': 't', + }, { + 'pid': 69920, + 'tid': 1, + 'ts': 2193564790059, + 'ph': 'R', + 'cat': 'blink.user_timing', + 'name': 'navigationStart', + 'args': { + 'frame': 'B192D1F3355A6F961EC8F0B01623C1FB', + 'data': { + 'documentLoaderURL': 'http://www.example.com/', + 'isLoadingMainFrame': true, + }, + }, + 'tts': 141371, + }, { + 'pid': 69920, + 'tid': 1, + 'ts': 0, + 'ph': 'M', + 'cat': '__metadata', + 'name': 'thread_name', + 'args': {'name': 'CrRendererMain'}, + }]}; + const trace = await traceOfTab.compute_(tracingStartedInBrowserTrace); + assert.equal(trace.startedInPageEvt.ts, 2193564729582); + assert.equal(trace.navigationStartEvt.ts, 2193564790059); + }); + it('stably sorts events', async () => { const traceJson = fs.readFileSync(__dirname + '/../../fixtures/traces/tracingstarted-after-navstart.json', 'utf8'); diff --git a/typings/externs.d.ts b/typings/externs.d.ts index 1b6a67dc16b5..c6bd70afb923 100644 --- a/typings/externs.d.ts +++ b/typings/externs.d.ts @@ -137,6 +137,12 @@ declare global { cat: string; args: { data?: { + persistentIds?: boolean; + frames?: { + frame: string; + parent?: string; + processId?: number; + }[]; page?: string; readyState?: number; requestId?: string; From 328cd03905365f221976ad9cb6fd1c70a87b41ea Mon Sep 17 00:00:00 2001 From: Patrick Hulce Date: Mon, 4 Jun 2018 10:50:04 -0700 Subject: [PATCH 2/5] add name to externs --- typings/externs.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/typings/externs.d.ts b/typings/externs.d.ts index c6bd70afb923..1dc0e3464be6 100644 --- a/typings/externs.d.ts +++ b/typings/externs.d.ts @@ -137,6 +137,7 @@ declare global { cat: string; args: { data?: { + name?: string; persistentIds?: boolean; frames?: { frame: string; From 3678880f446200b41dcce5f5c6063dfc107e0dda Mon Sep 17 00:00:00 2001 From: Patrick Hulce Date: Mon, 4 Jun 2018 10:52:29 -0700 Subject: [PATCH 3/5] brendan's comments --- lighthouse-core/gather/computed/trace-of-tab.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lighthouse-core/gather/computed/trace-of-tab.js b/lighthouse-core/gather/computed/trace-of-tab.js index dc381f57a6ab..1030972f0b39 100644 --- a/lighthouse-core/gather/computed/trace-of-tab.js +++ b/lighthouse-core/gather/computed/trace-of-tab.js @@ -42,11 +42,12 @@ class TraceOfTab extends ComputedArtifact { // *must* be stable to keep events correctly nested. /** @type Array */ const keyEvents = trace.traceEvents - .filter(e => - e.cat.includes('blink.user_timing') || + .filter(e => { + return e.cat.includes('blink.user_timing') || e.cat.includes('loading') || e.cat.includes('devtools.timeline') || - e.cat === '__metadata') + e.cat === '__metadata' + }) // @ts-ignore - stableSort added to Array by WebInspector. .stableSort((event0, event1) => event0.ts - event1.ts); @@ -54,14 +55,13 @@ class TraceOfTab extends ComputedArtifact { /** @type {LH.TraceEvent|undefined} */ let startedInPageEvt; const startedInBrowserEvt = keyEvents.find(e => e.name === 'TracingStartedInBrowser'); + // `persistentIds` is a signal that the frame data will be attached, prefer it when available. if (startedInBrowserEvt && startedInBrowserEvt.args.data && startedInBrowserEvt.args.data.persistentIds) { const mainFrame = (startedInBrowserEvt.args.data.frames || []).find(frame => !frame.parent); const pid = mainFrame && mainFrame.processId; const threadNameEvt = keyEvents.find(e => e.pid === pid && e.ph === 'M' && - e.cat === '__metadata' && e.name === 'thread_name' && - // @ts-ignore - property chain exists for 'thread_name' event. - e.args.name === 'CrRendererMain'); + e.cat === '__metadata' && e.name === 'thread_name' && e.args.name === 'CrRendererMain'); startedInPageEvt = mainFrame && threadNameEvt ? Object.assign({}, startedInBrowserEvt, { pid, tid: threadNameEvt.tid, name: 'TracingStartedInPage', From d63f4912ec93c0992d1152b6c1dab7c0e2d0bf20 Mon Sep 17 00:00:00 2001 From: Patrick Hulce Date: Mon, 4 Jun 2018 11:41:26 -0700 Subject: [PATCH 4/5] semicolon --- lighthouse-core/gather/computed/trace-of-tab.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lighthouse-core/gather/computed/trace-of-tab.js b/lighthouse-core/gather/computed/trace-of-tab.js index 1030972f0b39..ac1bbfc5b00b 100644 --- a/lighthouse-core/gather/computed/trace-of-tab.js +++ b/lighthouse-core/gather/computed/trace-of-tab.js @@ -46,7 +46,7 @@ class TraceOfTab extends ComputedArtifact { return e.cat.includes('blink.user_timing') || e.cat.includes('loading') || e.cat.includes('devtools.timeline') || - e.cat === '__metadata' + e.cat === '__metadata'; }) // @ts-ignore - stableSort added to Array by WebInspector. .stableSort((event0, event1) => event0.ts - event1.ts); From 559ae4477ddcc9c0f7275b64066896d28f663efd Mon Sep 17 00:00:00 2001 From: Alexei Filippov Date: Fri, 18 May 2018 18:01:56 -0700 Subject: [PATCH 5/5] core: Support traces with TracingStartedInBrowser event Since version 67 Chrome uses a new schema to describe page frame tree. The tree is encoded within TracingStartedInBrowser trace event. The patch makes lighthouse to support the new event. Legacy TracingStartedInPage event is going to the removed soon. --- lighthouse-core/gather/computed/trace-of-tab.js | 11 +++++------ .../test/gather/computed/trace-of-tab-test.js | 1 - typings/externs.d.ts | 3 +-- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/lighthouse-core/gather/computed/trace-of-tab.js b/lighthouse-core/gather/computed/trace-of-tab.js index ac1bbfc5b00b..b21ba09994a2 100644 --- a/lighthouse-core/gather/computed/trace-of-tab.js +++ b/lighthouse-core/gather/computed/trace-of-tab.js @@ -44,9 +44,9 @@ class TraceOfTab extends ComputedArtifact { const keyEvents = trace.traceEvents .filter(e => { return e.cat.includes('blink.user_timing') || - e.cat.includes('loading') || - e.cat.includes('devtools.timeline') || - e.cat === '__metadata'; + e.cat.includes('loading') || + e.cat.includes('devtools.timeline') || + e.cat === '__metadata'; }) // @ts-ignore - stableSort added to Array by WebInspector. .stableSort((event0, event1) => event0.ts - event1.ts); @@ -55,10 +55,9 @@ class TraceOfTab extends ComputedArtifact { /** @type {LH.TraceEvent|undefined} */ let startedInPageEvt; const startedInBrowserEvt = keyEvents.find(e => e.name === 'TracingStartedInBrowser'); - // `persistentIds` is a signal that the frame data will be attached, prefer it when available. if (startedInBrowserEvt && startedInBrowserEvt.args.data && - startedInBrowserEvt.args.data.persistentIds) { - const mainFrame = (startedInBrowserEvt.args.data.frames || []).find(frame => !frame.parent); + startedInBrowserEvt.args.data.frames) { + const mainFrame = startedInBrowserEvt.args.data.frames.find(frame => !frame.parent); const pid = mainFrame && mainFrame.processId; const threadNameEvt = keyEvents.find(e => e.pid === pid && e.ph === 'M' && e.cat === '__metadata' && e.name === 'thread_name' && e.args.name === 'CrRendererMain'); diff --git a/lighthouse-core/test/gather/computed/trace-of-tab-test.js b/lighthouse-core/test/gather/computed/trace-of-tab-test.js index 77ca29474ca9..d401e6aa0d7d 100644 --- a/lighthouse-core/test/gather/computed/trace-of-tab-test.js +++ b/lighthouse-core/test/gather/computed/trace-of-tab-test.js @@ -123,7 +123,6 @@ describe('Trace of Tab computed artifact:', () => { 'name': 'TracingStartedInBrowser', 'args': {'data': { 'frameTreeNodeId': 1, - 'persistentIds': true, 'frames': [{ 'frame': 'B192D1F3355A6F961EC8F0B01623C1FB', 'url': 'http://www.example.com/', diff --git a/typings/externs.d.ts b/typings/externs.d.ts index 1dc0e3464be6..e5227a0ab55f 100644 --- a/typings/externs.d.ts +++ b/typings/externs.d.ts @@ -137,8 +137,6 @@ declare global { cat: string; args: { data?: { - name?: string; - persistentIds?: boolean; frames?: { frame: string; parent?: string; @@ -155,6 +153,7 @@ declare global { url?: string; }; frame?: string; + name?: string; }; pid: number; tid: number;