[go: nahoru, domu]

[RPP] Use new engine data in the details pane

This is the implementation of the proposal doc to use new engine data in
the details view [1], except we are not forwarding legacy events from
the appender system, we are forwarding raw trace events with the new
engine types because support for these has recently been added throuout
the details view artifacts.

[1] https://docs.google.com/document/d/1yhOwUj0abz6gkc5iDd0YwweO68P0XxX0etgnd0XI54M/edit#heading=h.pcawn2wj7knb

Bug: 1433692
Change-Id: I06694e3eed8c8a600a7d8af1cf8419024170bc45
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/4502863
Commit-Queue: Andres Olivares <andoli@chromium.org>
Reviewed-by: Nancy Li <nancyly@chromium.org>
diff --git a/front_end/panels/timeline/TimelineFlameChartView.ts b/front_end/panels/timeline/TimelineFlameChartView.ts
index 98cd875..3bcb7aa 100644
--- a/front_end/panels/timeline/TimelineFlameChartView.ts
+++ b/front_end/panels/timeline/TimelineFlameChartView.ts
@@ -185,8 +185,7 @@
     if (flameChart !== this.mainFlameChart) {
       return;
     }
-    const track = group ? this.mainDataProvider.groupTrack(group) : null;
-    this.#selectedEvents = track ? track.eventsForTreeView() : null;
+    this.#selectedEvents = group ? this.mainDataProvider.groupTreeEvents(group) : null;
     this.updateTrack();
   }
 
diff --git a/front_end/panels/timeline/TimelineTreeView.ts b/front_end/panels/timeline/TimelineTreeView.ts
index 06a95a0..14421c2 100644
--- a/front_end/panels/timeline/TimelineTreeView.ts
+++ b/front_end/panels/timeline/TimelineTreeView.ts
@@ -714,9 +714,7 @@
 const profileNodeToTreeGridNode = new WeakMap<TimelineModel.TimelineProfileTree.Node, TreeGridNode>();
 
 export class AggregatedTimelineTreeView extends TimelineTreeView {
-  // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
-  // eslint-disable-next-line @typescript-eslint/no-explicit-any
-  protected readonly groupBySetting: Common.Settings.Setting<any>;
+  protected readonly groupBySetting: Common.Settings.Setting<AggregatedTimelineTreeView.GroupBy>;
   private readonly stackView: TimelineStackView;
   private executionContextNamesByOrigin = new Map<Platform.DevToolsPath.UrlString, string>();
 
@@ -730,6 +728,9 @@
     this.stackView.addEventListener(TimelineStackView.Events.SelectionChanged, this.onStackViewSelectionChanged, this);
   }
 
+  setGroupBySettingForTests(groupBy: AggregatedTimelineTreeView.GroupBy): void {
+    this.groupBySetting.set(groupBy);
+  }
   override setModelWithEvents(
       model: PerformanceModel|null,
       selectedEvents: SDK.TracingModel.CompatibleTraceEvent[]|null,
diff --git a/test/unittests/front_end/panels/timeline/BUILD.gn b/test/unittests/front_end/panels/timeline/BUILD.gn
index fdc7748..e3901d5 100644
--- a/test/unittests/front_end/panels/timeline/BUILD.gn
+++ b/test/unittests/front_end/panels/timeline/BUILD.gn
@@ -10,6 +10,7 @@
     "EventTypeHelpers_test.ts",
     "SaveFileFormatter_test.ts",
     "SourceMaps_test.ts",
+    "TimelineFlameChartDataProvider_test.ts",
     "TimelineFlameChartView_test.ts",
     "TimelineHistoryManager_test.ts",
     "TimelineSelection_test.ts",
diff --git a/test/unittests/front_end/panels/timeline/TimelineFlameChartDataProvider_test.ts b/test/unittests/front_end/panels/timeline/TimelineFlameChartDataProvider_test.ts
new file mode 100644
index 0000000..b44722c
--- /dev/null
+++ b/test/unittests/front_end/panels/timeline/TimelineFlameChartDataProvider_test.ts
@@ -0,0 +1,58 @@
+// Copyright 2023 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import * as SDK from '../../../../../front_end/core/sdk/sdk.js';
+import * as TraceEngine from '../../../../../front_end/models/trace/trace.js';
+import * as Timeline from '../../../../../front_end/panels/timeline/timeline.js';
+import {describeWithEnvironment} from '../../helpers/EnvironmentHelpers.js';
+import {allModelsFromFile} from '../../helpers/TraceHelpers.js';
+
+describeWithEnvironment('TimelineFlameChartDataProvider', () => {
+  describe('groupTreeEvents', () => {
+    it('returns the correct events for tree views given a flame chart group', async () => {
+      const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();
+      const {traceParsedData, performanceModel} = await allModelsFromFile('sync-like-timings.json.gz');
+      dataProvider.setModel(performanceModel, traceParsedData);
+      const timingsTrackGroup = dataProvider.timelineData().groups.find(g => g.name === 'Timings');
+      if (!timingsTrackGroup) {
+        assert.fail('Could not find Timings track flame chart group');
+      }
+      const groupTreeEvents = dataProvider.groupTreeEvents(timingsTrackGroup);
+      const allTimingEvents = [
+        ...traceParsedData.UserTimings.consoleTimings,
+        ...traceParsedData.UserTimings.timestampEvents,
+        ...traceParsedData.UserTimings.performanceMarks,
+        ...traceParsedData.UserTimings.performanceMeasures,
+        ...traceParsedData.PageLoadMetrics.allMarkerEvents,
+      ];
+      assert.deepEqual(groupTreeEvents, allTimingEvents);
+    });
+
+    it('filters out async events if they cannot be added to the tree', async () => {
+      const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();
+      const {traceParsedData, performanceModel} = await allModelsFromFile('timings-track.json.gz');
+      dataProvider.setModel(performanceModel, traceParsedData);
+      const timingsTrackGroup = dataProvider.timelineData().groups.find(g => g.name === 'Timings');
+      if (!timingsTrackGroup) {
+        assert.fail('Could not find Timings track flame chart group');
+      }
+      const groupTreeEvents = dataProvider.groupTreeEvents(timingsTrackGroup);
+      assert.strictEqual(groupTreeEvents?.length, 11);
+      const allEventsAreSync = groupTreeEvents?.every(
+          event => !TraceEngine.Types.TraceEvents.isAsyncPhase(SDK.TracingModel.phaseForEvent(event)));
+      assert.isTrue(allEventsAreSync);
+    });
+    it('returns data from the old engine if necessary', async () => {
+      const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();
+      const {traceParsedData, performanceModel} = await allModelsFromFile('timings-track.json.gz');
+      dataProvider.setModel(performanceModel, traceParsedData);
+      const mainTrack = dataProvider.timelineData().groups.find(g => g.name.includes('Main'));
+      if (!mainTrack) {
+        assert.fail('Could not find Main track flame chart group');
+      }
+      const groupTreeEvents = dataProvider.groupTreeEvents(mainTrack);
+      assert.strictEqual(groupTreeEvents?.length, 28995);
+    });
+  });
+});
diff --git a/test/unittests/front_end/panels/timeline/TimelineTreeView_test.ts b/test/unittests/front_end/panels/timeline/TimelineTreeView_test.ts
index 1bd8603..b4ba74a 100644
--- a/test/unittests/front_end/panels/timeline/TimelineTreeView_test.ts
+++ b/test/unittests/front_end/panels/timeline/TimelineTreeView_test.ts
@@ -82,15 +82,15 @@
   describe('CallTreeTimelineTreeView', () => {
     it('Creates a call tree from nestable events', async () => {
       const data = await allModelsFromFile('sync-like-timings.json.gz');
-      const CallTreeView = new Timeline.TimelineTreeView.CallTreeTimelineTreeView();
+      const callTreeView = new Timeline.TimelineTreeView.CallTreeTimelineTreeView();
       const consoleTimings = [...data.traceParsedData.UserTimings.consoleTimings];
       const startTime =
           TraceEngine.Helpers.Timing.microSecondsToMilliseconds(data.traceParsedData.Meta.traceBounds.min);
       const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(data.traceParsedData.Meta.traceBounds.max);
-      CallTreeView.setRange(startTime, endTime);
-      CallTreeView.setModelWithEvents(data.performanceModel, consoleTimings, data.traceParsedData);
+      callTreeView.setRange(startTime, endTime);
+      callTreeView.setModelWithEvents(data.performanceModel, consoleTimings, data.traceParsedData);
 
-      const tree = CallTreeView.buildTree();
+      const tree = callTreeView.buildTree();
       const topNodesIterator = tree.children().values();
       const firstNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;
       assert.strictEqual(firstNode.event?.name, 'first console time');
@@ -102,4 +102,45 @@
       assert.strictEqual(childNode.event?.name, 'second console time');
     });
   });
+  describe('event groupping', () => {
+    it('groups events by category in the Call Tree view', async () => {
+      const data = await allModelsFromFile('sync-like-timings.json.gz');
+      const callTreeView = new Timeline.TimelineTreeView.CallTreeTimelineTreeView();
+      const consoleTimings = [...data.traceParsedData.UserTimings.consoleTimings];
+      const startTime =
+          TraceEngine.Helpers.Timing.microSecondsToMilliseconds(data.traceParsedData.Meta.traceBounds.min);
+      const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(data.traceParsedData.Meta.traceBounds.max);
+      callTreeView.setRange(startTime, endTime);
+      callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.Category);
+      callTreeView.setModelWithEvents(data.performanceModel, consoleTimings, data.traceParsedData);
+      const tree = callTreeView.buildTree();
+      const treeEntries = tree.children().entries();
+      const groupEntry = treeEntries.next();
+      assert.strictEqual(groupEntry.value[0], 'scripting');
+      assert.isTrue(groupEntry.value[1].isGroupNode());
+      const children = groupEntry.value[1].children().values();
+      assert.strictEqual(children.next().value.event.name, 'first console time');
+      assert.strictEqual(children.next().value.event.name, 'third console time');
+    });
+    it('groups events by category in the Call Tree view', async () => {
+      const data = await allModelsFromFile('sync-like-timings.json.gz');
+      const callTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView();
+      const consoleTimings = [...data.traceParsedData.UserTimings.consoleTimings];
+      const startTime =
+          TraceEngine.Helpers.Timing.microSecondsToMilliseconds(data.traceParsedData.Meta.traceBounds.min);
+      const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(data.traceParsedData.Meta.traceBounds.max);
+      callTreeView.setRange(startTime, endTime);
+      callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.Category);
+      callTreeView.setModelWithEvents(data.performanceModel, consoleTimings, data.traceParsedData);
+      const tree = callTreeView.buildTree();
+      const treeEntries = tree.children().entries();
+      const groupEntry = treeEntries.next();
+      assert.strictEqual(groupEntry.value[0], 'scripting');
+      assert.isTrue(groupEntry.value[1].isGroupNode());
+      const children = groupEntry.value[1].children().values();
+      assert.strictEqual(children.next().value.event.name, 'second console time');
+      assert.strictEqual(children.next().value.event.name, 'first console time');
+      assert.strictEqual(children.next().value.event.name, 'third console time');
+    });
+  });
 });