Add UMA for Network panel "more filters"

Chromium CL: https://crrev.com/c/5025097

Bug: 1486431
Change-Id: Ifc50cda4a6678e0c2231ba4318f1ff4e7639ff15
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/5025097
Reviewed-by: Kateryna Prokopenko <[email protected]>
Auto-Submit: Wolfgang Beyer <[email protected]>
Commit-Queue: Wolfgang Beyer <[email protected]>
diff --git a/front_end/core/host/InspectorFrontendHostAPI.ts b/front_end/core/host/InspectorFrontendHostAPI.ts
index 7d0294d..0e7b5a9 100644
--- a/front_end/core/host/InspectorFrontendHostAPI.ts
+++ b/front_end/core/host/InspectorFrontendHostAPI.ts
@@ -466,4 +466,6 @@
   LegacyResourceTypeFilterItemSelected = 'DevTools.LegacyResourceTypeFilterItemSelected',
   ResourceTypeFilterNumberOfSelectedChanged = 'DevTools.ResourceTypeFilterNumberOfSelectedChanged',
   ResourceTypeFilterItemSelected = 'DevTools.ResourceTypeFilterItemSelected',
+  NetworkPanelMoreFiltersNumberOfSelectedChanged = 'DevTools.NetworkPanelMoreFiltersNumberOfSelectedChanged',
+  NetworkPanelMoreFiltersItemSelected = 'DevTools.NetworkPanelMoreFiltersItemSelected',
 }
diff --git a/front_end/core/host/UserMetrics.ts b/front_end/core/host/UserMetrics.ts
index bde54c5..8d54056 100644
--- a/front_end/core/host/UserMetrics.ts
+++ b/front_end/core/host/UserMetrics.ts
@@ -488,6 +488,22 @@
     InspectorFrontendHostInstance.recordEnumeratedHistogram(
         EnumeratedHistogram.ResourceTypeFilterItemSelected, resourceType, ResourceType.MaxValue);
   }
+
+  networkPanelMoreFiltersNumberOfSelectedChanged(itemCount: number): void {
+    const boundItemCount = Math.max(Math.min(itemCount, NetworkPanelMoreFilters.MaxValue), 0);
+    InspectorFrontendHostInstance.recordEnumeratedHistogram(
+        EnumeratedHistogram.NetworkPanelMoreFiltersNumberOfSelectedChanged, boundItemCount,
+        NetworkPanelMoreFilters.MaxValue);
+  }
+
+  networkPanelMoreFiltersItemSelected(filterName: string): void {
+    const filter = NetworkPanelMoreFilters[filterName as keyof typeof NetworkPanelMoreFilters];
+    if (filter === undefined) {
+      return;
+    }
+    InspectorFrontendHostInstance.recordEnumeratedHistogram(
+        EnumeratedHistogram.NetworkPanelMoreFiltersItemSelected, filter, NetworkPanelMoreFilters.MaxValue);
+  }
 }
 
 /**
@@ -1209,6 +1225,19 @@
 }
 
 // TODO(crbug.com/1167717): Make this a const enum again
+/* eslint-disable @typescript-eslint/naming-convention */
+// eslint-disable-next-line rulesdir/const_enum
+export enum NetworkPanelMoreFilters {
+  'Hide data URLs' = 0,
+  'Hide extension URLs' = 1,
+  'Blocked response cookies' = 2,
+  'Blocked requests' = 3,
+  '3rd-party requests' = 4,
+  MaxValue = 5,
+}
+/* eslint-enable @typescript-eslint/naming-convention */
+
+// TODO(crbug.com/1167717): Make this a const enum again
 // eslint-disable-next-line rulesdir/const_enum
 export enum LinearMemoryInspectorRevealedFrom {
   ContextMenu = 0,
diff --git a/front_end/panels/network/NetworkLogView.ts b/front_end/panels/network/NetworkLogView.ts
index 7e4eea0..4125e6d 100644
--- a/front_end/panels/network/NetworkLogView.ts
+++ b/front_end/panels/network/NetworkLogView.ts
@@ -2768,6 +2768,7 @@
   private contextMenu?: UI.ContextMenu.ContextMenu;
   private activeFiltersCount: HTMLElement;
   private activeFiltersCountAdorner: Adorners.Adorner.Adorner;
+  private hasChanged = false;
 
   constructor(filterChangedCallback: () => void) {
     super();
@@ -2806,20 +2807,37 @@
     this.updateTooltip();
   }
 
+  emitUMA(): void {
+    if (this.hasChanged) {
+      const selectedFilters = this.selectedFilters();
+      Host.userMetrics.networkPanelMoreFiltersNumberOfSelectedChanged(selectedFilters.length);
+      for (const selectedFilter of selectedFilters) {
+        Host.userMetrics.networkPanelMoreFiltersItemSelected(selectedFilter);
+      }
+    }
+  }
+
+  #onSettingChanged(): void {
+    this.hasChanged = true;
+    this.filterChangedCallback();
+  }
+
   showMoreFiltersContextMenu(event: Common.EventTarget.EventTargetEvent<Event>): void {
     const mouseEvent = event.data;
+    this.hasChanged = false;
 
-    this.networkHideDataURLSetting.addChangeListener(this.filterChangedCallback.bind(this));
-    this.networkHideChromeExtensionsSetting.addChangeListener(this.filterChangedCallback.bind(this));
-    this.networkShowBlockedCookiesOnlySetting.addChangeListener(this.filterChangedCallback.bind(this));
-    this.networkOnlyBlockedRequestsSetting.addChangeListener(this.filterChangedCallback.bind(this));
-    this.networkOnlyThirdPartySetting.addChangeListener(this.filterChangedCallback.bind(this));
+    this.networkHideDataURLSetting.addChangeListener(this.#onSettingChanged.bind(this));
+    this.networkHideChromeExtensionsSetting.addChangeListener(this.#onSettingChanged.bind(this));
+    this.networkShowBlockedCookiesOnlySetting.addChangeListener(this.#onSettingChanged.bind(this));
+    this.networkOnlyBlockedRequestsSetting.addChangeListener(this.#onSettingChanged.bind(this));
+    this.networkOnlyThirdPartySetting.addChangeListener(this.#onSettingChanged.bind(this));
     this.contextMenu = new UI.ContextMenu.ContextMenu(mouseEvent, {
       useSoftMenu: true,
       keepOpen: true,
       x: this.dropDownButton.element.getBoundingClientRect().left,
       y: this.dropDownButton.element.getBoundingClientRect().top +
           (this.dropDownButton.element as HTMLElement).offsetHeight,
+      onSoftMenuClosed: this.emitUMA.bind(this),
     });
 
     this.contextMenu.defaultSection().appendCheckboxItem(
diff --git a/test/unittests/front_end/panels/network/NetworkLogView_test.ts b/test/unittests/front_end/panels/network/NetworkLogView_test.ts
index 6da7c2d..4977a78 100644
--- a/test/unittests/front_end/panels/network/NetworkLogView_test.ts
+++ b/test/unittests/front_end/panels/network/NetworkLogView_test.ts
@@ -524,6 +524,8 @@
 
     it('can filter requests with blocked response cookies from dropdown', async () => {
       Root.Runtime.experiments.enableForTest(Root.Runtime.ExperimentName.NETWORK_PANEL_FILTER_BAR_REDESIGN);
+      const umaCountSpy = sinon.spy(Host.userMetrics, 'networkPanelMoreFiltersNumberOfSelectedChanged');
+      const umaItemSpy = sinon.spy(Host.userMetrics, 'networkPanelMoreFiltersItemSelected');
 
       const request1 = createNetworkRequest('url1', {target});
       request1.blockedResponseCookies = () => [{
@@ -556,11 +558,15 @@
       ]);
 
       dropdown.discard();
+      assert.isTrue(umaCountSpy.calledOnceWith(1));
+      assert.isTrue(umaItemSpy.calledOnceWith('Blocked response cookies'));
       networkLogView.detach();
     });
 
     it('lists selected options in more filters tooltip', async () => {
       Root.Runtime.experiments.enableForTest(Root.Runtime.ExperimentName.NETWORK_PANEL_FILTER_BAR_REDESIGN);
+      const umaCountSpy = sinon.spy(Host.userMetrics, 'networkPanelMoreFiltersNumberOfSelectedChanged');
+      const umaItemSpy = sinon.spy(Host.userMetrics, 'networkPanelMoreFiltersItemSelected');
       let filterBar;
       ({filterBar, networkLogView} = createEnvironment());
 
@@ -578,6 +584,10 @@
       assert.strictEqual(button.title, 'Hide extension URLs, Blocked response cookies');
 
       dropdown.discard();
+      assert.isTrue(umaCountSpy.calledOnceWith(2));
+      assert.isTrue(umaItemSpy.calledTwice);
+      assert.isTrue(umaItemSpy.calledWith('Hide extension URLs'));
+      assert.isTrue(umaItemSpy.calledWith('Blocked response cookies'));
       networkLogView.detach();
     });