Skip to content

Commit ff6497e

Browse files
finnurbrekiDevtools-frontend LUCI CQ
authored andcommitted
[AskAi]: Agentize the Third Parties Insight.
Example response: https://screenshot.googleplex.com/5i7BMeuqLnUxMb7 Fixed: 405920819 Change-Id: Iea37b557ef735be08bc63075566549fdd64013f4 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6905551 Reviewed-by: Connor Clark <[email protected]> Commit-Queue: Finnur Thorarinsson <[email protected]>
1 parent d6ad612 commit ff6497e

File tree

6 files changed

+137
-2
lines changed

6 files changed

+137
-2
lines changed

front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,3 +842,49 @@ no origins were preconnected.
842842
- https://web.dev/learn/performance/understanding-the-critical-path
843843
- https://developer.chrome.com/docs/lighthouse/performance/uses-rel-preconnect/
844844
=== end content
845+
846+
Title: PerformanceInsightFormatter Third Parties Insight serializes correctly when there are no results
847+
Content:
848+
## Insight Title: 3rd parties
849+
850+
## Insight Summary:
851+
This insight analyzes the performance impact of resources loaded from third-party servers and aggregates the performance cost, in terms of download transfer sizes and total amount of time that third party scripts spent executing on the main thread.
852+
853+
## Detailed analysis:
854+
No 3rd party scripts were found on this page.
855+
856+
## Estimated savings: none
857+
858+
## External resources:
859+
- https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript/
860+
=== end content
861+
862+
Title: PerformanceInsightFormatter Third Parties Insight serializes 3rd party scripts correctly
863+
Content:
864+
## Insight Title: 3rd parties
865+
866+
## Insight Summary:
867+
This insight analyzes the performance impact of resources loaded from third-party servers and aggregates the performance cost, in terms of download transfer sizes and total amount of time that third party scripts spent executing on the main thread.
868+
869+
## Detailed analysis:
870+
The following list contains the largest transfer sizes by a 3rd party script:
871+
872+
- imgix: 172 kB
873+
- Google Tag Manager: 163 kB
874+
- Google Analytics: 20.5 kB
875+
- web.app: 823 B
876+
877+
The following list contains the largest amount spent by a 3rd party script on the main thread:
878+
879+
- Google Tag Manager: 28.1 ms
880+
- Google Analytics: 5.8 ms
881+
- noondiphcddnnabmjcihcjfbhfklnnep: 1.7 ms
882+
- web.app: 0.2 ms
883+
884+
3rd party code can significantly impact load performance. [Reduce and defer loading of 3rd party code](https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript/) to prioritize your page's content.
885+
886+
## Estimated savings: none
887+
888+
## External resources:
889+
- https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript/
890+
=== end content

front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,4 +411,26 @@ describeWithEnvironment('PerformanceInsightFormatter', () => {
411411
snapshotTester.assert(this, output);
412412
});
413413
});
414+
415+
describe('ThirdParties', () => {
416+
it('serializes correctly when there are no results', async function() {
417+
const {parsedTrace, insights} = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz');
418+
assert.isOk(insights);
419+
const firstNav = getFirstOrError(parsedTrace.Meta.navigationsByNavigationId.values());
420+
const insight = getInsightOrError('ThirdParties', insights, firstNav);
421+
const formatter = new PerformanceInsightFormatter(PERF_AGENT_UNIT_FORMATTERS, parsedTrace, insight);
422+
const output = formatter.formatInsight();
423+
snapshotTester.assert(this, output);
424+
});
425+
426+
it('serializes 3rd party scripts correctly', async function() {
427+
const {parsedTrace, insights} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');
428+
assert.isOk(insights);
429+
const firstNav = getFirstOrError(parsedTrace.Meta.navigationsByNavigationId.values());
430+
const insight = getInsightOrError('ThirdParties', insights, firstNav);
431+
const formatter = new PerformanceInsightFormatter(PERF_AGENT_UNIT_FORMATTERS, parsedTrace, insight);
432+
const output = formatter.formatInsight();
433+
snapshotTester.assert(this, output);
434+
});
435+
});
414436
});

front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,53 @@ export class PerformanceInsightFormatter {
319319
return output;
320320
}
321321

322+
/**
323+
* Create an AI prompt string out of the ThirdParties Insight model to use with Ask AI.
324+
* Note: This function accesses the UIStrings within ThirdParties to help build the
325+
* AI prompt, but does not (and should not) call i18nString to localize these strings. They
326+
* should all be sent in English (at least for now).
327+
* @param insight The Third Parties Insight Model to query.
328+
* @returns a string formatted for sending to Ask AI.
329+
*/
330+
formatThirdPartiesInsight(insight: Trace.Insights.Models.ThirdParties.ThirdPartiesInsightModel): string {
331+
let output = '';
332+
333+
const entitySummaries = insight.entitySummaries ?? [];
334+
const firstPartyEntity = insight.firstPartyEntity;
335+
336+
const thirdPartyTransferSizeEntries =
337+
entitySummaries.filter(s => s.entity !== firstPartyEntity).toSorted((a, b) => b.transferSize - a.transferSize);
338+
const thirdPartyMainThreadTimeEntries = entitySummaries.filter(s => s.entity !== firstPartyEntity)
339+
.toSorted((a, b) => b.mainThreadTime - a.mainThreadTime);
340+
341+
if (!thirdPartyTransferSizeEntries.length && !thirdPartyMainThreadTimeEntries.length) {
342+
return `No 3rd party scripts were found on this page.`;
343+
}
344+
345+
if (thirdPartyTransferSizeEntries.length) {
346+
output += `The following list contains the largest transfer sizes by a 3rd party script:\n\n`;
347+
for (const entry of thirdPartyTransferSizeEntries) {
348+
if (entry.transferSize > 0) {
349+
output += `- ${entry.entity.name}: ${this.#unitFormatters.bytes(entry.transferSize)}\n`;
350+
}
351+
}
352+
output += '\n';
353+
}
354+
355+
if (thirdPartyMainThreadTimeEntries.length) {
356+
output += `The following list contains the largest amount spent by a 3rd party script on the main thread:\n\n`;
357+
for (const entry of thirdPartyMainThreadTimeEntries) {
358+
if (entry.mainThreadTime > 0) {
359+
output += `- ${entry.entity.name}: ${this.#formatMilli(entry.mainThreadTime)}\n`;
360+
}
361+
}
362+
output += '\n';
363+
}
364+
365+
output += Trace.Insights.Models.ThirdParties.UIStrings.description;
366+
return output;
367+
}
368+
322369
/**
323370
* Formats and outputs the insight's data.
324371
* Pass `{headingLevel: X}` to determine what heading level to use for the
@@ -579,6 +626,10 @@ ${filesFormatted}`;
579626
return this.formatNetworkDependencyTreeInsight(this.#insight);
580627
}
581628

629+
if (Trace.Insights.Models.ThirdParties.isThirdPartyInsight(this.#insight)) {
630+
return this.formatThirdPartiesInsight(this.#insight);
631+
}
632+
582633
return '';
583634
}
584635

@@ -630,7 +681,7 @@ ${filesFormatted}`;
630681
case 'SlowCSSSelector':
631682
return '';
632683
case 'ThirdParties':
633-
return '';
684+
return '- https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript/';
634685
case 'Viewport':
635686
return '';
636687
case 'Cache':
@@ -700,7 +751,7 @@ It is important that all of these checks pass to minimize the delay between the
700751
case 'SlowCSSSelector':
701752
return '';
702753
case 'ThirdParties':
703-
return '';
754+
return 'This insight analyzes the performance impact of resources loaded from third-party servers and aggregates the performance cost, in terms of download transfer sizes and total amount of time that third party scripts spent executing on the main thread.';
704755
case 'Viewport':
705756
return '';
706757
case 'Cache':

front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,10 @@ Available insights:
849849
estimated wasted bytes: 52.1 kB
850850
example question: How do I decrease the initial loading time of my page?
851851
example question: Did anything slow down the request for this document?
852+
- insight name: ThirdParties
853+
description: 3rd party code can significantly impact load performance. [Reduce and defer loading of 3rd party code](https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript/) to prioritize your page's content.
854+
relevant trace bounds: {min: 1020034871372, max: 1020035171789}
855+
example question: Which third parties are having the largest impact on my page performance?
852856
=== end content
853857

854858
Title: PerformanceTraceFormatter formatTraceSummary yahoo-news.json.gz
@@ -887,6 +891,10 @@ Available insights:
887891
estimated wasted bytes: 97.8 kB
888892
example question: What should I do to improve and optimize the time taken to fetch and display images on the page?
889893
example question: Are all images on my site optimized?
894+
- insight name: ThirdParties
895+
description: 3rd party code can significantly impact load performance. [Reduce and defer loading of 3rd party code](https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript/) to prioritize your page's content.
896+
relevant trace bounds: {min: 157423742399, max: 157427277086}
897+
example question: Which third parties are having the largest impact on my page performance?
890898
- insight name: LegacyJavaScript
891899
description: Polyfills and transforms enable older browsers to use new JavaScript features. However, many aren't necessary for modern browsers. Consider modifying your JavaScript build process to not transpile [Baseline](https://web.dev/articles/baseline-and-polyfills) features, unless you know you must support older browsers. [Learn why most sites can deploy ES6+ code without transpiling](https://philipwalton.com/articles/the-state-of-es5-on-the-web/)
892900
relevant trace bounds: {min: 157423489126, max: 157426132225}

front_end/models/trace/insights/ThirdParties.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ function finalize(partialModel: PartialInsightModel<ThirdPartiesInsightModel>):
7373
};
7474
}
7575

76+
export function isThirdPartyInsight(model: InsightModel): model is ThirdPartiesInsightModel {
77+
return model.insightKey === InsightKeys.THIRD_PARTIES;
78+
}
79+
7680
export function generateInsight(
7781
parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): ThirdPartiesInsightModel {
7882
const entitySummaries =

front_end/panels/timeline/components/insights/ThirdParties.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ export class ThirdParties extends BaseInsightComponent<ThirdPartiesInsightModel>
5151
},
5252
};
5353

54+
protected override hasAskAiSupport(): boolean {
55+
return true;
56+
}
57+
5458
override renderContent(): Lit.LitTemplate {
5559
if (!this.model) {
5660
return Lit.nothing;

0 commit comments

Comments
 (0)