chrome-devtools-mcp-for-extension 0.19.2 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Color.js +13 -9
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/ColorConverter.js +9 -7
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Console.js +1 -8
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Debouncer.js +2 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Gzip.js +9 -7
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/MapWithDefault.js +5 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/ParsedURL.js +10 -20
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/ResourceType.js +0 -11
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/ReturnToPanel.js +6 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Revealer.js +5 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/SegmentedRange.js +1 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Settings.js +110 -99
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/StringOutputStream.js +1 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Throttler.js +2 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/common.js +1 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/AidaClient.js +21 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/DispatchHttpRequestClient.js +66 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/GdpClient.js +102 -86
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/InspectorFrontendHost.js +32 -450
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/InspectorFrontendHostAPI.js +32 -29
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/InspectorFrontendHostStub.js +430 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/Platform.js +5 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/ResourceLoader.js +10 -22
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/UserMetrics.js +26 -15
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/host.js +2 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/ArrayUtilities.js +2 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/HostRuntime.js +19 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/StringUtilities.js +34 -32
- package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/api/HostRuntime.js +4 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/api/api.js +5 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/browser/HostRuntime.js +63 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/browser/browser.js +5 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/node/HostRuntime.js +72 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/node/node.js +5 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/platform.js +2 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/CDPConnection.js +17 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/ConnectionTransport.js +12 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/DevToolsCDPConnection.js +138 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/InspectorBackend.js +49 -312
- package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/protocol_client.js +4 -9
- package/build/node_modules/chrome-devtools-frontend/front_end/core/root/DevToolsContext.js +54 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/root/root.js +2 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/AnimationModel.js +2 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CPUThrottlingManager.js +0 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSMatchedStyles.js +51 -17
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSMetadata.js +21 -7
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSModel.js +11 -5
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSProperty.js +4 -7
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSPropertyParser.js +11 -9
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSPropertyParserMatchers.js +34 -24
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSRule.js +52 -10
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSStartingStyle.js +21 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSStyleDeclaration.js +4 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ChildTargetManager.js +39 -35
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/Connections.js +10 -47
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ConsoleModel.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/Cookie.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/DOMModel.js +29 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/DebuggerModel.js +5 -20
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/EnhancedTracesParser.js +17 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/EventBreakpointsModel.js +4 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/HttpReasonPhraseStrings.js +4 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/IOModel.js +1 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkManager.js +428 -121
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkRequest.js +8 -22
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/PageResourceLoader.js +44 -34
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/PreloadingModel.js +64 -19
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/RehydratingConnection.js +139 -12
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/RemoteObject.js +5 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ResourceTreeModel.js +3 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ScopeTreeCache.js +36 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ScreenCaptureModel.js +20 -18
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/Script.js +26 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ServerSentEventsProtocol.js +3 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMap.js +54 -14
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMapCache.js +16 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMapManager.js +19 -7
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMapScopesInfo.js +240 -8
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/Target.js +12 -17
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/TargetManager.js +38 -29
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/TraceObject.js +11 -8
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/sdk-meta.js +80 -31
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/sdk.js +4 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/generated/ARIAProperties.js +1301 -174
- package/build/node_modules/chrome-devtools-frontend/front_end/generated/Deprecation.js +67 -22
- package/build/node_modules/chrome-devtools-frontend/front_end/generated/InspectorBackendCommands.js +62 -91
- package/build/node_modules/chrome-devtools-frontend/front_end/generated/SupportedCSSProperties.js +188 -100
- package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.js +30 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.js +50 -34
- package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.js +152 -101
- package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AICallTree.js +11 -6
- package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AIContext.js +25 -26
- package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AIQueries.js +46 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/CSSWorkspaceBinding.js +10 -8
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/CompilerScriptMapping.js +82 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/DebuggerWorkspaceBinding.js +33 -15
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/ResourceMapping.js +105 -14
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/ResourceScriptMapping.js +38 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/SASSSourceMapping.js +5 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/models/cpu_profile/CPUProfileDataModel.js +9 -7
- package/build/node_modules/chrome-devtools-frontend/front_end/models/cpu_profile/ProfileTreeModel.js +6 -7
- package/build/node_modules/chrome-devtools-frontend/front_end/models/crux-manager/CrUXManager.js +6 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/models/formatter/FormatterWorkerPool.js +16 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/models/network_time_calculator/RequestTimeRanges.js +6 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/models/source_map_scopes/FunctionCodeResolver.js +192 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/source_map_scopes/NamesResolver.js +12 -16
- package/build/node_modules/chrome-devtools-frontend/front_end/models/source_map_scopes/source_map_scopes.js +2 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/models/stack_trace/StackTraceModel.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/stack_trace/Trie.js +8 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/LanternComputationData.js +1 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/ModelImpl.js +6 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/Processor.js +4 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/Styles.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/extras/TraceTree.js +11 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/FramesHandler.js +7 -5
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/LayoutShiftsHandler.js +8 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/MetaHandler.js +4 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/NetworkRequestsHandler.js +29 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/SamplesHandler.js +59 -6
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/ScriptsHandler.js +26 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/UserTimingsHandler.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/helpers.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/helpers/Timing.js +4 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/helpers/Trace.js +18 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/CLSCulprits.js +2 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/Cache.js +2 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/DOMSize.js +2 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/DocumentLatency.js +12 -11
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/DuplicatedJavaScript.js +2 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/FontDisplay.js +2 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/ForcedReflow.js +3 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/INPBreakdown.js +14 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/ImageDelivery.js +2 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/LCPBreakdown.js +13 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/LCPDiscovery.js +2 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/LegacyJavaScript.js +4 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/ModernHTTP.js +2 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/NetworkDependencyTree.js +4 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/RenderBlocking.js +2 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/SlowCSSSelector.js +2 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/ThirdParties.js +2 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/Viewport.js +2 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/types/TraceEvents.js +9 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace_source_maps_resolver/SourceMapsResolver.js +25 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/models/workspace/IgnoreListManager.js +41 -48
- package/build/node_modules/chrome-devtools-frontend/front_end/models/workspace/UISourceCode.js +38 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/workspace/WorkspaceImpl.js +5 -8
- package/build/node_modules/chrome-devtools-frontend/front_end/models/workspace/workspace-meta.js +34 -0
- package/build/src/McpContext.js +8 -1
- package/build/src/tools/bookmarks.js +0 -1
- package/build/src/tools/gemini-web.js +17 -25
- package/build/src/tools/snapshot.js +9 -2
- package/package.json +3 -3
|
@@ -239,7 +239,9 @@ export class PerformanceInsightFormatter {
|
|
|
239
239
|
const rootCauseText = potentialRootCauses.length ? `- Potential root causes:\n ${potentialRootCauses.join('\n')}` :
|
|
240
240
|
'- No potential root causes identified';
|
|
241
241
|
const startTime = Trace.Helpers.Timing.microToMilli(Trace.Types.Timing.Micro(shift.ts - baseTime));
|
|
242
|
-
|
|
242
|
+
const impactedNodeNames = shift.rawSourceEvent.args.data?.impacted_nodes?.map(n => n.debug_name).filter(name => name !== undefined) ?? [];
|
|
243
|
+
const impactedNodeText = impactedNodeNames.length ? `\n- Impacted elements:\n - ${impactedNodeNames.join('\n - ')}\n` : '';
|
|
244
|
+
return `### Layout shift ${index + 1}:${impactedNodeText}
|
|
243
245
|
- Start time: ${millis(startTime)}
|
|
244
246
|
- Score: ${shift.args.data?.weighted_score_delta.toFixed(4)}
|
|
245
247
|
${rootCauseText}`;
|
|
@@ -432,7 +434,7 @@ Duplication grouped by Node modules: ${filesFormatted}`;
|
|
|
432
434
|
output += 'No top-level functions causing forced reflows were identified.\n';
|
|
433
435
|
}
|
|
434
436
|
if (insight.aggregatedBottomUpData.length > 0) {
|
|
435
|
-
output += '\n' + Trace.Insights.Models.ForcedReflow.UIStrings.
|
|
437
|
+
output += '\n' + Trace.Insights.Models.ForcedReflow.UIStrings.reflowCallFrames + ' (including total time):\n';
|
|
436
438
|
for (const data of insight.aggregatedBottomUpData) {
|
|
437
439
|
output += `\n - ${this.#formatMicro(data.totalTime)} in ${callFrameToString(data.bottomUpData)}`;
|
|
438
440
|
}
|
|
@@ -845,55 +847,69 @@ ${this.#links()}`;
|
|
|
845
847
|
.join(', ');
|
|
846
848
|
}
|
|
847
849
|
#links() {
|
|
850
|
+
const links = [];
|
|
851
|
+
if (this.#insight.docs) {
|
|
852
|
+
links.push(this.#insight.docs);
|
|
853
|
+
}
|
|
848
854
|
switch (this.#insight.insightKey) {
|
|
849
855
|
case 'CLSCulprits':
|
|
850
|
-
|
|
851
|
-
|
|
856
|
+
links.push('https://web.dev/articles/cls');
|
|
857
|
+
links.push('https://web.dev/articles/optimize-cls');
|
|
858
|
+
break;
|
|
852
859
|
case 'DocumentLatency':
|
|
853
|
-
|
|
860
|
+
links.push('https://web.dev/articles/optimize-ttfb');
|
|
861
|
+
break;
|
|
854
862
|
case 'DOMSize':
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
return '';
|
|
863
|
+
links.push('https://developer.chrome.com/docs/lighthouse/performance/dom-size/');
|
|
864
|
+
break;
|
|
858
865
|
case 'FontDisplay':
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
866
|
+
links.push('https://web.dev/articles/preload-optional-fonts');
|
|
867
|
+
links.push('https://fonts.google.com/knowledge/glossary/foit');
|
|
868
|
+
links.push('https://developer.chrome.com/blog/font-fallbacks');
|
|
869
|
+
break;
|
|
862
870
|
case 'ForcedReflow':
|
|
863
|
-
|
|
871
|
+
links.push('https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing#avoid-forced-synchronous-layouts');
|
|
872
|
+
break;
|
|
864
873
|
case 'ImageDelivery':
|
|
865
|
-
|
|
874
|
+
links.push('https://developer.chrome.com/docs/lighthouse/performance/uses-optimized-images/');
|
|
875
|
+
break;
|
|
866
876
|
case 'INPBreakdown':
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
return `- https://web.dev/articles/lcp
|
|
873
|
-
- https://web.dev/articles/optimize-lcp`;
|
|
877
|
+
links.push('https://web.dev/articles/inp');
|
|
878
|
+
links.push('https://web.dev/explore/how-to-optimize-inp');
|
|
879
|
+
links.push('https://web.dev/articles/optimize-long-tasks');
|
|
880
|
+
links.push('https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing');
|
|
881
|
+
break;
|
|
874
882
|
case 'LCPBreakdown':
|
|
875
|
-
|
|
876
|
-
- https://web.dev/articles/optimize-lcp`;
|
|
877
|
-
case 'NetworkDependencyTree':
|
|
878
|
-
return `- https://web.dev/learn/performance/understanding-the-critical-path
|
|
879
|
-
- https://developer.chrome.com/docs/lighthouse/performance/uses-rel-preconnect/`;
|
|
883
|
+
case 'LCPDiscovery':
|
|
880
884
|
case 'RenderBlocking':
|
|
881
|
-
|
|
882
|
-
|
|
885
|
+
links.push('https://web.dev/articles/lcp');
|
|
886
|
+
links.push('https://web.dev/articles/optimize-lcp');
|
|
887
|
+
break;
|
|
888
|
+
case 'NetworkDependencyTree':
|
|
889
|
+
links.push('https://web.dev/learn/performance/understanding-the-critical-path');
|
|
890
|
+
links.push('https://developer.chrome.com/docs/lighthouse/performance/uses-rel-preconnect/');
|
|
891
|
+
break;
|
|
883
892
|
case 'SlowCSSSelector':
|
|
884
|
-
|
|
893
|
+
links.push('https://developer.chrome.com/docs/devtools/performance/selector-stats');
|
|
894
|
+
break;
|
|
885
895
|
case 'ThirdParties':
|
|
886
|
-
|
|
896
|
+
links.push('https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript/');
|
|
897
|
+
break;
|
|
887
898
|
case 'Viewport':
|
|
888
|
-
|
|
899
|
+
links.push('https://developer.chrome.com/blog/300ms-tap-delay-gone-away/');
|
|
900
|
+
break;
|
|
889
901
|
case 'Cache':
|
|
890
|
-
|
|
902
|
+
links.push('https://web.dev/uses-long-cache-ttl/');
|
|
903
|
+
break;
|
|
891
904
|
case 'ModernHTTP':
|
|
892
|
-
|
|
905
|
+
links.push('https://developer.chrome.com/docs/lighthouse/best-practices/uses-http2');
|
|
906
|
+
break;
|
|
893
907
|
case 'LegacyJavaScript':
|
|
894
|
-
|
|
895
|
-
|
|
908
|
+
links.push('https://web.dev/articles/baseline-and-polyfills');
|
|
909
|
+
links.push('https://philipwalton.com/articles/the-state-of-es5-on-the-web/');
|
|
910
|
+
break;
|
|
896
911
|
}
|
|
912
|
+
return links.map(link => '- ' + link).join('\n');
|
|
897
913
|
}
|
|
898
914
|
#description() {
|
|
899
915
|
switch (this.#insight.insightKey) {
|
|
@@ -15,7 +15,7 @@ export class PerformanceTraceFormatter {
|
|
|
15
15
|
constructor(focus) {
|
|
16
16
|
this.#focus = focus;
|
|
17
17
|
this.#parsedTrace = focus.parsedTrace;
|
|
18
|
-
this.#insightSet = focus.
|
|
18
|
+
this.#insightSet = focus.primaryInsightSet;
|
|
19
19
|
this.#eventsSerializer = focus.eventsSerializer;
|
|
20
20
|
}
|
|
21
21
|
serializeEvent(event) {
|
|
@@ -91,58 +91,62 @@ export class PerformanceTraceFormatter {
|
|
|
91
91
|
}
|
|
92
92
|
formatTraceSummary() {
|
|
93
93
|
const parsedTrace = this.#parsedTrace;
|
|
94
|
-
const insightSet = this.#insightSet;
|
|
95
94
|
const traceMetadata = this.#parsedTrace.metadata;
|
|
96
95
|
const data = parsedTrace.data;
|
|
97
96
|
const parts = [];
|
|
98
|
-
const lcp = insightSet ? Trace.Insights.Common.getLCP(insightSet) : null;
|
|
99
|
-
const cls = insightSet ? Trace.Insights.Common.getCLS(insightSet) : null;
|
|
100
|
-
const inp = insightSet ? Trace.Insights.Common.getINP(insightSet) : null;
|
|
101
97
|
parts.push(`URL: ${data.Meta.mainFrameURL}`);
|
|
102
|
-
parts.push(`
|
|
98
|
+
parts.push(`Trace bounds: ${this.serializeBounds(data.Meta.traceBounds)}`);
|
|
103
99
|
parts.push('CPU throttling: ' + (traceMetadata.cpuThrottling ? `${traceMetadata.cpuThrottling}x` : 'none'));
|
|
104
100
|
parts.push(`Network throttling: ${traceMetadata.networkThrottling ?? 'none'}`);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
if (subparts
|
|
122
|
-
|
|
101
|
+
parts.push('\n# Available insight sets\n');
|
|
102
|
+
parts.push('The following is a list of insight sets. An insight set covers a specific part of the trace, split by navigations. The insights within each insight set are specific to that part of the trace. Be sure to consider the insight set id and bounds when calling functions. If no specific insight set or navigation is mentioned, assume the user is referring to the first one.');
|
|
103
|
+
for (const insightSet of parsedTrace.insights?.values() ?? []) {
|
|
104
|
+
const lcp = insightSet ? Trace.Insights.Common.getLCP(insightSet) : null;
|
|
105
|
+
const cls = insightSet ? Trace.Insights.Common.getCLS(insightSet) : null;
|
|
106
|
+
const inp = insightSet ? Trace.Insights.Common.getINP(insightSet) : null;
|
|
107
|
+
parts.push(`\n## insight set id: ${insightSet.id}\n`);
|
|
108
|
+
parts.push(`URL: ${insightSet.url}`);
|
|
109
|
+
parts.push(`Bounds: ${this.serializeBounds(insightSet.bounds)}`);
|
|
110
|
+
if (lcp || cls || inp) {
|
|
111
|
+
parts.push('Metrics (lab / observed):');
|
|
112
|
+
if (lcp) {
|
|
113
|
+
const nodeId = insightSet?.model.LCPBreakdown.lcpEvent?.args.data?.nodeId;
|
|
114
|
+
const nodeIdText = nodeId !== undefined ? `, nodeId: ${nodeId}` : '';
|
|
115
|
+
parts.push(` - LCP: ${Math.round(lcp.value / 1000)} ms, event: ${this.serializeEvent(lcp.event)}${nodeIdText}`);
|
|
116
|
+
const subparts = insightSet?.model.LCPBreakdown.subparts;
|
|
117
|
+
if (subparts) {
|
|
118
|
+
const serializeSubpart = (subpart) => {
|
|
119
|
+
return `${micros(subpart.range)}, bounds: ${this.serializeBounds(subpart)}`;
|
|
120
|
+
};
|
|
121
|
+
parts.push(' - LCP breakdown:');
|
|
122
|
+
parts.push(` - TTFB: ${serializeSubpart(subparts.ttfb)}`);
|
|
123
|
+
if (subparts.loadDelay !== undefined) {
|
|
124
|
+
parts.push(` - Load delay: ${serializeSubpart(subparts.loadDelay)}`);
|
|
125
|
+
}
|
|
126
|
+
if (subparts.loadDuration !== undefined) {
|
|
127
|
+
parts.push(` - Load duration: ${serializeSubpart(subparts.loadDuration)}`);
|
|
128
|
+
}
|
|
129
|
+
parts.push(` - Render delay: ${serializeSubpart(subparts.renderDelay)}`);
|
|
123
130
|
}
|
|
124
|
-
|
|
131
|
+
}
|
|
132
|
+
if (inp) {
|
|
133
|
+
parts.push(` - INP: ${Math.round(inp.value / 1000)} ms, event: ${this.serializeEvent(inp.event)}`);
|
|
134
|
+
}
|
|
135
|
+
if (cls) {
|
|
136
|
+
const eventText = cls.worstClusterEvent ? `, event: ${this.serializeEvent(cls.worstClusterEvent)}` : '';
|
|
137
|
+
parts.push(` - CLS: ${cls.value.toFixed(2)}${eventText}`);
|
|
125
138
|
}
|
|
126
139
|
}
|
|
127
|
-
|
|
128
|
-
parts.push(
|
|
140
|
+
else {
|
|
141
|
+
parts.push('Metrics (lab / observed): n/a');
|
|
129
142
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
parts.push(
|
|
143
|
+
const cruxParts = insightSet && this.#getCruxTraceSummary(insightSet);
|
|
144
|
+
if (cruxParts?.length) {
|
|
145
|
+
parts.push(...cruxParts);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
parts.push('Metrics (field / real users): n/a – no data for this page in CrUX');
|
|
133
149
|
}
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
parts.push('Metrics (lab / observed): n/a');
|
|
137
|
-
}
|
|
138
|
-
const cruxParts = insightSet && this.#getCruxTraceSummary(insightSet);
|
|
139
|
-
if (cruxParts?.length) {
|
|
140
|
-
parts.push(...cruxParts);
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
parts.push('Metrics (field / real users): n/a – no data for this page in CrUX');
|
|
144
|
-
}
|
|
145
|
-
if (insightSet) {
|
|
146
150
|
parts.push('Available insights:');
|
|
147
151
|
for (const [insightName, model] of Object.entries(insightSet.model)) {
|
|
148
152
|
if (model.state === 'pass') {
|
|
@@ -172,23 +176,44 @@ export class PerformanceTraceFormatter {
|
|
|
172
176
|
parts.push(` - ${insightPartsText}`);
|
|
173
177
|
}
|
|
174
178
|
}
|
|
179
|
+
return parts.join('\n');
|
|
180
|
+
}
|
|
181
|
+
#formatFactByInsightSet(options) {
|
|
182
|
+
const { insights, title, description, empty, cb } = options;
|
|
183
|
+
const lines = [`# ${title}\n`];
|
|
184
|
+
if (description) {
|
|
185
|
+
lines.push(`${description}\n`);
|
|
186
|
+
}
|
|
187
|
+
if (insights?.size) {
|
|
188
|
+
const multipleInsightSets = insights.size > 1;
|
|
189
|
+
for (const insightSet of insights.values()) {
|
|
190
|
+
if (multipleInsightSets) {
|
|
191
|
+
lines.push(`## insight set id: ${insightSet.id}\n`);
|
|
192
|
+
}
|
|
193
|
+
lines.push((cb(insightSet) ?? empty) + '\n');
|
|
194
|
+
}
|
|
195
|
+
}
|
|
175
196
|
else {
|
|
176
|
-
|
|
197
|
+
lines.push(empty + '\n');
|
|
177
198
|
}
|
|
178
|
-
return
|
|
199
|
+
return lines.join('\n');
|
|
179
200
|
}
|
|
180
201
|
formatCriticalRequests() {
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
202
|
+
const parsedTrace = this.#parsedTrace;
|
|
203
|
+
return this.#formatFactByInsightSet({
|
|
204
|
+
insights: parsedTrace.insights,
|
|
205
|
+
title: 'Critical network requests',
|
|
206
|
+
empty: 'none',
|
|
207
|
+
cb: insightSet => {
|
|
208
|
+
const criticalRequests = [];
|
|
209
|
+
const walkRequest = (node) => {
|
|
210
|
+
criticalRequests.push(node.request);
|
|
211
|
+
node.children.forEach(walkRequest);
|
|
212
|
+
};
|
|
213
|
+
insightSet.model.NetworkDependencyTree.rootNodes.forEach(walkRequest);
|
|
214
|
+
return criticalRequests.length ? this.formatNetworkRequests(criticalRequests, { verbose: false }) : null;
|
|
215
|
+
},
|
|
216
|
+
});
|
|
192
217
|
}
|
|
193
218
|
#serializeBottomUpRootNode(rootNode, limit) {
|
|
194
219
|
// Sorted by selfTime.
|
|
@@ -220,19 +245,24 @@ export class PerformanceTraceFormatter {
|
|
|
220
245
|
}
|
|
221
246
|
return `- self: ${millis(node.selfTime)}, total: ${millis(node.totalTime)}, source: ${source}`;
|
|
222
247
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
248
|
+
return topNodes.map(node => nodeToText.call(this, node)).join('\n');
|
|
249
|
+
}
|
|
250
|
+
#getSerializeBottomUpRootNodeFormat(limit) {
|
|
251
|
+
return `This is the bottom-up summary for the entire trace. Only the top ${limit} activities (sorted by self time) are shown. An activity is all the aggregated time spent on the same type of work. For example, it can be all the time spent in a specific JavaScript function, or all the time spent in a specific browser rendering stage (like layout, v8 compile, parsing html). "Self time" represents the aggregated time spent directly in an activity, across all occurrences. "Total time" represents the aggregated time spent in an activity or any of its children.`;
|
|
226
252
|
}
|
|
227
253
|
formatMainThreadBottomUpSummary() {
|
|
228
254
|
const parsedTrace = this.#parsedTrace;
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
255
|
+
const limit = 10;
|
|
256
|
+
return this.#formatFactByInsightSet({
|
|
257
|
+
insights: parsedTrace.insights,
|
|
258
|
+
title: 'Main thread bottom-up summary',
|
|
259
|
+
description: this.#getSerializeBottomUpRootNodeFormat(limit),
|
|
260
|
+
empty: 'no activity',
|
|
261
|
+
cb: insightSet => {
|
|
262
|
+
const rootNode = AIQueries.mainThreadActivityBottomUpSingleNavigation(insightSet.navigation?.args.data?.navigationId, insightSet.bounds, parsedTrace);
|
|
263
|
+
return rootNode ? this.#serializeBottomUpRootNode(rootNode, limit) : null;
|
|
264
|
+
},
|
|
265
|
+
});
|
|
236
266
|
}
|
|
237
267
|
#formatThirdPartyEntitySummaries(summaries) {
|
|
238
268
|
const topMainThreadTimeEntries = summaries.toSorted((a, b) => b.mainThreadTime - a.mainThreadTime).slice(0, 5);
|
|
@@ -248,36 +278,36 @@ export class PerformanceTraceFormatter {
|
|
|
248
278
|
return listText;
|
|
249
279
|
}
|
|
250
280
|
formatThirdPartySummary() {
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
if (!listText) {
|
|
262
|
-
return '';
|
|
263
|
-
}
|
|
264
|
-
return `Third party summary:\n${listText}`;
|
|
281
|
+
const parsedTrace = this.#parsedTrace;
|
|
282
|
+
return this.#formatFactByInsightSet({
|
|
283
|
+
insights: parsedTrace.insights,
|
|
284
|
+
title: '3rd party summary',
|
|
285
|
+
empty: 'no 3rd parties',
|
|
286
|
+
cb: insightSet => {
|
|
287
|
+
const thirdPartySummaries = Trace.Extras.ThirdParties.summarizeByThirdParty(parsedTrace.data, insightSet.bounds);
|
|
288
|
+
return thirdPartySummaries.length ? this.#formatThirdPartyEntitySummaries(thirdPartySummaries) : null;
|
|
289
|
+
},
|
|
290
|
+
});
|
|
265
291
|
}
|
|
266
292
|
formatLongestTasks() {
|
|
267
293
|
const parsedTrace = this.#parsedTrace;
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
294
|
+
return this.#formatFactByInsightSet({
|
|
295
|
+
insights: parsedTrace.insights,
|
|
296
|
+
title: 'Longest tasks',
|
|
297
|
+
empty: 'none',
|
|
298
|
+
cb: insightSet => {
|
|
299
|
+
const longestTaskTrees = AIQueries.longestTasks(insightSet.navigation?.args.data?.navigationId, insightSet.bounds, parsedTrace, 3);
|
|
300
|
+
if (!longestTaskTrees?.length) {
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
303
|
+
return longestTaskTrees
|
|
304
|
+
.map(tree => {
|
|
305
|
+
const time = millis(tree.rootNode.totalTime);
|
|
306
|
+
return `- total time: ${time}, event: ${this.serializeEvent(tree.rootNode.event)}`;
|
|
307
|
+
})
|
|
308
|
+
.join('\n');
|
|
309
|
+
},
|
|
310
|
+
});
|
|
281
311
|
}
|
|
282
312
|
#serializeRelatedInsightsForEvents(events) {
|
|
283
313
|
if (!events.length) {
|
|
@@ -313,16 +343,22 @@ export class PerformanceTraceFormatter {
|
|
|
313
343
|
return results.join('\n');
|
|
314
344
|
}
|
|
315
345
|
formatMainThreadTrackSummary(bounds) {
|
|
346
|
+
if (!this.#parsedTrace.insights) {
|
|
347
|
+
return 'No main thread activity found';
|
|
348
|
+
}
|
|
316
349
|
const results = [];
|
|
317
|
-
const
|
|
350
|
+
const insightSet = this.#parsedTrace.insights?.values().find(insightSet => Trace.Helpers.Timing.boundsIncludeTimeRange({ bounds, timeRange: insightSet.bounds }));
|
|
351
|
+
const topDownTree = AIQueries.mainThreadActivityTopDown(insightSet?.navigation?.args.data?.navigationId, bounds, this.#parsedTrace);
|
|
318
352
|
if (topDownTree) {
|
|
319
353
|
results.push('# Top-down main thread summary');
|
|
320
354
|
results.push(this.formatCallTree(topDownTree, 2 /* headerLevel */));
|
|
321
355
|
}
|
|
322
|
-
const bottomUpRootNode = AIQueries.mainThreadActivityBottomUp(
|
|
356
|
+
const bottomUpRootNode = AIQueries.mainThreadActivityBottomUp(bounds, this.#parsedTrace);
|
|
323
357
|
if (bottomUpRootNode) {
|
|
324
358
|
results.push('# Bottom-up main thread summary');
|
|
325
|
-
|
|
359
|
+
const limit = 20;
|
|
360
|
+
results.push(this.#getSerializeBottomUpRootNodeFormat(limit));
|
|
361
|
+
results.push(this.#serializeBottomUpRootNode(bottomUpRootNode, limit));
|
|
326
362
|
}
|
|
327
363
|
const thirdPartySummaries = Trace.Extras.ThirdParties.summarizeByThirdParty(this.#parsedTrace.data, bounds);
|
|
328
364
|
if (thirdPartySummaries.length) {
|
|
@@ -496,7 +532,7 @@ Network requests data:
|
|
|
496
532
|
}
|
|
497
533
|
static callFrameDataFormatDescription = `Each call frame is presented in the following format:
|
|
498
534
|
|
|
499
|
-
'id;eventKey;name;duration;selfTime;urlIndex;childRange;[S]'
|
|
535
|
+
'id;eventKey;name;duration;selfTime;urlIndex;childRange;[line];[column];[S]'
|
|
500
536
|
|
|
501
537
|
Key definitions:
|
|
502
538
|
|
|
@@ -507,15 +543,17 @@ Key definitions:
|
|
|
507
543
|
* selfTime: The time spent directly within the call frame, excluding its children's execution.
|
|
508
544
|
* urlIndex: Index referencing the "All URLs" list. Empty if no specific script URL is associated.
|
|
509
545
|
* childRange: Specifies the direct children of this node using their IDs. If empty ('' or 'S' at the end), the node has no children. If a single number (e.g., '4'), the node has one child with that ID. If in the format 'firstId-lastId' (e.g., '4-5'), it indicates a consecutive range of child IDs from 'firstId' to 'lastId', inclusive.
|
|
546
|
+
* line: An optional field for a call frame's line number. This is where the function is defined.
|
|
547
|
+
* column: An optional field for a call frame's column number. This is where the function is defined.
|
|
510
548
|
* S: _Optional_. The letter 'S' terminates the line if that call frame was selected by the user.
|
|
511
549
|
|
|
512
550
|
Example Call Tree:
|
|
513
551
|
|
|
514
|
-
1;r-123;main;500;100;;
|
|
515
|
-
2;r-124;update;200;50;;3
|
|
516
|
-
3;p-49575-15428179-2834-374;animate;150;20;0;4-5;S
|
|
517
|
-
4;p-49575-15428179-3505-1162;calculatePosition;80;80;;
|
|
518
|
-
5;p-49575-15428179-5391-2767;applyStyles;50;50;;
|
|
552
|
+
1;r-123;main;500;100;0;1;;
|
|
553
|
+
2;r-124;update;200;50;;3;0;1;
|
|
554
|
+
3;p-49575-15428179-2834-374;animate;150;20;0;4-5;0;1;S
|
|
555
|
+
4;p-49575-15428179-3505-1162;calculatePosition;80;80;0;1;;
|
|
556
|
+
5;p-49575-15428179-5391-2767;applyStyles;50;50;0;1;;
|
|
519
557
|
`;
|
|
520
558
|
/**
|
|
521
559
|
* Network requests format description that is sent to the model as a fact.
|
|
@@ -610,4 +648,17 @@ The order of headers corresponds to an internal fixed list. If a header is not p
|
|
|
610
648
|
];
|
|
611
649
|
return parts.join(';');
|
|
612
650
|
}
|
|
651
|
+
formatFunctionCode(code) {
|
|
652
|
+
const { startLine, startColumn } = code.range;
|
|
653
|
+
const { startLine: contextStartLine, startColumn: contextStartColumn, endLine: contextEndLine, endColumn: contextEndColumn } = code.rangeWithContext;
|
|
654
|
+
const name = code.functionBounds.name;
|
|
655
|
+
const url = code.functionBounds.uiSourceCode.url();
|
|
656
|
+
const parts = [];
|
|
657
|
+
parts.push(`${name} @ ${url}:${startLine}:${startColumn}. With added context, chunk is from ${contextStartLine}:${contextStartColumn} to ${contextEndLine}:${contextEndColumn}`);
|
|
658
|
+
parts.push('\nThe following is a markdown block of JavaScript. <FUNCTION_START> and <FUNCTION_END> marks the exact function declaration, and everything outside that is provided for additional context. Comments at the end of each line indicate the runtime performance cost of that code. Do not show the user the function markers or the additional context.\n');
|
|
659
|
+
parts.push('```');
|
|
660
|
+
parts.push(code.codeWithContext);
|
|
661
|
+
parts.push('```');
|
|
662
|
+
return parts.join('\n');
|
|
663
|
+
}
|
|
613
664
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// Copyright 2024 The Chromium Authors
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
|
-
import * as Root from '../../../core/root/root.js';
|
|
5
4
|
import * as Trace from '../../../models/trace/trace.js';
|
|
6
5
|
import * as SourceMapsResolver from '../../../models/trace_source_maps_resolver/trace_source_maps_resolver.js';
|
|
7
6
|
/** Iterates from a node down through its descendents. If the callback returns true, the loop stops. */
|
|
@@ -122,7 +121,7 @@ export class AICallTree {
|
|
|
122
121
|
if (!data.Renderer.entryToNode.has(selectedEvent) && !data.Samples.entryToNode.has(selectedEvent)) {
|
|
123
122
|
return null;
|
|
124
123
|
}
|
|
125
|
-
const
|
|
124
|
+
const showAllEvents = parsedTrace.data.Meta.config.showAllEvents;
|
|
126
125
|
const { startTime, endTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(selectedEvent);
|
|
127
126
|
const selectedEventBounds = Trace.Helpers.Timing.traceWindowFromMicroSeconds(Trace.Helpers.Timing.milliToMicro(startTime), Trace.Helpers.Timing.milliToMicro(endTime));
|
|
128
127
|
let threadEvents = data.Renderer.processes.get(selectedEvent.pid)?.threads.get(selectedEvent.tid)?.entries;
|
|
@@ -139,7 +138,7 @@ export class AICallTree {
|
|
|
139
138
|
// If the "Show all events" experiment is on, we don't filter out any
|
|
140
139
|
// events here, otherwise the generated call tree will not match what the
|
|
141
140
|
// user is seeing.
|
|
142
|
-
if (!
|
|
141
|
+
if (!showAllEvents) {
|
|
143
142
|
filters.push(new Trace.Extras.TraceFilter.VisibleEventsFilter(Trace.Styles.visibleTypes()));
|
|
144
143
|
}
|
|
145
144
|
// Build a tree bounded by the selected event's timestamps, and our other filters applied
|
|
@@ -245,10 +244,12 @@ export class AICallTree {
|
|
|
245
244
|
* 5. `urlIndex`: An index referencing a URL in the `allUrls` array. If no URL is present, this is an empty string.
|
|
246
245
|
* 6. `childRange`: A string indicating the range of IDs for the node's children. Children should always have consecutive IDs.
|
|
247
246
|
* If there is only one child, it's a single ID.
|
|
248
|
-
* 7. `[
|
|
247
|
+
* 7. `[line]`: An optional field for a call frame's line number.
|
|
248
|
+
* 8. `[column]`: An optional field for a call frame's column number.
|
|
249
|
+
* 9. `[S]`: An optional marker indicating that this node is the selected node.
|
|
249
250
|
*
|
|
250
251
|
* Example:
|
|
251
|
-
* `1;Parse HTML;2.5;0.3;0;2-5;S`
|
|
252
|
+
* `1;Parse HTML;2.5;0.3;0;2-5;10;11;S`
|
|
252
253
|
* This represents:
|
|
253
254
|
* - Node ID 1
|
|
254
255
|
* - Name "Parse HTML"
|
|
@@ -256,6 +257,7 @@ export class AICallTree {
|
|
|
256
257
|
* - Self time of 0.3ms
|
|
257
258
|
* - URL index 0 (meaning the URL is the first one in the `allUrls` array)
|
|
258
259
|
* - Child range of IDs 2 to 5
|
|
260
|
+
* - Line, column is 10:11
|
|
259
261
|
* - This node is the selected node (S marker)
|
|
260
262
|
*/
|
|
261
263
|
stringifyNode(node, nodeId, parsedTrace, selectedNode, allUrls, childStartingNodeIndex) {
|
|
@@ -281,7 +283,8 @@ export class AICallTree {
|
|
|
281
283
|
// 5. Self Time
|
|
282
284
|
const selfTimeStr = roundToTenths(node.selfTime);
|
|
283
285
|
// 6. URL Index
|
|
284
|
-
const
|
|
286
|
+
const location = SourceMapsResolver.SourceMapsResolver.codeLocationForEntry(parsedTrace, event);
|
|
287
|
+
const url = location?.url;
|
|
285
288
|
let urlIndexStr = '';
|
|
286
289
|
if (url) {
|
|
287
290
|
const existingIndex = allUrls.indexOf(url);
|
|
@@ -309,6 +312,8 @@ export class AICallTree {
|
|
|
309
312
|
line += ';' + selfTimeStr;
|
|
310
313
|
line += ';' + urlIndexStr;
|
|
311
314
|
line += ';' + childRangeStr;
|
|
315
|
+
line += ';' + (location?.line ?? '');
|
|
316
|
+
line += ';' + (location?.column ?? '');
|
|
312
317
|
if (selectedMarker) {
|
|
313
318
|
line += ';' + selectedMarker;
|
|
314
319
|
}
|
|
@@ -3,21 +3,30 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
import * as Trace from '../../../models/trace/trace.js';
|
|
5
5
|
import { AICallTree } from './AICallTree.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Gets the first, most relevant InsightSet to use, following the logic of:
|
|
8
|
+
* 1. If there is only one InsightSet, use that.
|
|
9
|
+
* 2. If there are more, prefer the first we find that has a navigation associated with it.
|
|
10
|
+
* 3. If none with a navigation are found, fallback to the first one.
|
|
11
|
+
* 4. Otherwise, return null.
|
|
12
|
+
*/
|
|
13
|
+
function getPrimaryInsightSet(insights) {
|
|
14
|
+
const insightSets = Array.from(insights.values());
|
|
15
|
+
if (insightSets.length === 0) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
if (insightSets.length === 1) {
|
|
19
|
+
return insightSets[0];
|
|
20
|
+
}
|
|
21
|
+
return insightSets.filter(set => set.navigation).at(0) ?? insightSets.at(0) ?? null;
|
|
11
22
|
}
|
|
12
23
|
export class AgentFocus {
|
|
13
24
|
static fromParsedTrace(parsedTrace) {
|
|
14
25
|
if (!parsedTrace.insights) {
|
|
15
26
|
throw new Error('missing insights');
|
|
16
27
|
}
|
|
17
|
-
const insightSet = getFirstInsightSet(parsedTrace.insights);
|
|
18
28
|
return new AgentFocus({
|
|
19
29
|
parsedTrace,
|
|
20
|
-
insightSet,
|
|
21
30
|
event: null,
|
|
22
31
|
callTree: null,
|
|
23
32
|
insight: null,
|
|
@@ -27,10 +36,8 @@ export class AgentFocus {
|
|
|
27
36
|
if (!parsedTrace.insights) {
|
|
28
37
|
throw new Error('missing insights');
|
|
29
38
|
}
|
|
30
|
-
const insightSet = getFirstInsightSet(parsedTrace.insights);
|
|
31
39
|
return new AgentFocus({
|
|
32
40
|
parsedTrace,
|
|
33
|
-
insightSet,
|
|
34
41
|
event: null,
|
|
35
42
|
callTree: null,
|
|
36
43
|
insight,
|
|
@@ -40,35 +47,27 @@ export class AgentFocus {
|
|
|
40
47
|
if (!parsedTrace.insights) {
|
|
41
48
|
throw new Error('missing insights');
|
|
42
49
|
}
|
|
43
|
-
const insightSet = getFirstInsightSet(parsedTrace.insights);
|
|
44
50
|
const result = AgentFocus.#getCallTreeOrEvent(parsedTrace, event);
|
|
45
|
-
return new AgentFocus({ parsedTrace,
|
|
51
|
+
return new AgentFocus({ parsedTrace, event: result.event, callTree: result.callTree, insight: null });
|
|
46
52
|
}
|
|
47
53
|
static fromCallTree(callTree) {
|
|
48
|
-
|
|
49
|
-
// Select the insight set containing the call tree.
|
|
50
|
-
// If for some reason that fails, fallback to the first one.
|
|
51
|
-
let insightSet = null;
|
|
52
|
-
if (insights) {
|
|
53
|
-
const callTreeTimeRange = Trace.Helpers.Timing.traceWindowFromEvent(callTree.rootNode.event);
|
|
54
|
-
insightSet = insights.values().find(set => Trace.Helpers.Timing.boundsIncludeTimeRange({
|
|
55
|
-
timeRange: callTreeTimeRange,
|
|
56
|
-
bounds: set.bounds,
|
|
57
|
-
})) ??
|
|
58
|
-
getFirstInsightSet(insights);
|
|
59
|
-
}
|
|
60
|
-
return new AgentFocus({ parsedTrace: callTree.parsedTrace, insightSet, event: null, callTree, insight: null });
|
|
54
|
+
return new AgentFocus({ parsedTrace: callTree.parsedTrace, event: null, callTree, insight: null });
|
|
61
55
|
}
|
|
62
56
|
#data;
|
|
57
|
+
#primaryInsightSet;
|
|
63
58
|
eventsSerializer = new Trace.EventsSerializer.EventsSerializer();
|
|
64
59
|
constructor(data) {
|
|
60
|
+
if (!data.parsedTrace.insights) {
|
|
61
|
+
throw new Error('missing insights');
|
|
62
|
+
}
|
|
65
63
|
this.#data = data;
|
|
64
|
+
this.#primaryInsightSet = getPrimaryInsightSet(data.parsedTrace.insights);
|
|
66
65
|
}
|
|
67
66
|
get parsedTrace() {
|
|
68
67
|
return this.#data.parsedTrace;
|
|
69
68
|
}
|
|
70
|
-
get
|
|
71
|
-
return this.#
|
|
69
|
+
get primaryInsightSet() {
|
|
70
|
+
return this.#primaryInsightSet;
|
|
72
71
|
}
|
|
73
72
|
/** Note: at most one of event or callTree is non-null. */
|
|
74
73
|
get event() {
|