Bug 1373483 - Add telemetry for the grid inspector. r=pbro. data-r=bsmedberg
authorGabriel Luong <gabriel.luong@gmail.com>
Tue, 20 Jun 2017 16:32:18 -0700
changeset 413968 86f86f9710141b1f2689665c78e0e8917e146f2f
parent 413967 8cd5e6e5d0f71c18d928f76cf4312961145bb5af
child 413969 eeb0a65afa6d5535ac098b89e9b87bf0d626ca30
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspbro
bugs1373483
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1373483 - Add telemetry for the grid inspector. r=pbro. data-r=bsmedberg
devtools/client/inspector/boxmodel/box-model.js
devtools/client/inspector/grids/grid-inspector.js
devtools/client/inspector/grids/test/browser.ini
devtools/client/inspector/grids/test/browser_grids_number-of-css-grids-telemetry.js
devtools/client/inspector/inspector.js
devtools/client/inspector/shared/highlighters-overlay.js
devtools/client/shared/telemetry.js
devtools/server/actors/layout.js
devtools/shared/specs/layout.js
toolkit/components/telemetry/Histograms.json
toolkit/components/telemetry/Scalars.yaml
--- a/devtools/client/inspector/boxmodel/box-model.js
+++ b/devtools/client/inspector/boxmodel/box-model.js
@@ -342,20 +342,19 @@ BoxModel.prototype = {
 
     let toolbox = this.inspector.toolbox;
     let nodeFront = this.inspector.selection.nodeFront;
 
     toolbox.highlighterUtils.highlightNodeFront(nodeFront, options);
   },
 
   /**
-   * Handler for the inspector sidebar select event. Starts listening for
-   * "grid-layout-changed" if the layout panel is visible. Otherwise, stop
-   * listening for grid layout changes. Finally, refresh the layout view if
-   * it is visible.
+   * Handler for the inspector sidebar select event. Starts tracking reflows if the
+   * layout panel is visible. Otherwise, stop tracking reflows. Finally, refresh the box
+   * model view if it is visible.
    */
   onSidebarSelect() {
     if (!this.isPanelVisible()) {
       this.untrackReflows();
       return;
     }
 
     if (this.inspector.selection.isConnected() &&
--- a/devtools/client/inspector/grids/grid-inspector.js
+++ b/devtools/client/inspector/grids/grid-inspector.js
@@ -15,16 +15,18 @@ const {
   updateGrids,
 } = require("./actions/grids");
 const {
   updateShowGridAreas,
   updateShowGridLineNumbers,
   updateShowInfiniteLines,
 } = require("./actions/highlighter-settings");
 
+const CSS_GRID_COUNT_HISTOGRAM_ID = "DEVTOOLS_NUMBER_OF_CSS_GRIDS_IN_A_PAGE";
+
 const SHOW_GRID_AREAS = "devtools.gridinspector.showGridAreas";
 const SHOW_GRID_LINE_NUMBERS = "devtools.gridinspector.showGridLineNumbers";
 const SHOW_INFINITE_LINES_PREF = "devtools.gridinspector.showInfiniteLines";
 // @remove after release 56 (See Bug 1355747)
 const PROMOTE_COUNT_PREF = "devtools.promote.layoutview";
 
 // Default grid colors.
 const GRID_COLORS = [
@@ -38,16 +40,17 @@ const GRID_COLORS = [
   "#FF2647"
 ];
 
 function GridInspector(inspector, window) {
   this.document = window.document;
   this.highlighters = inspector.highlighters;
   this.inspector = inspector;
   this.store = inspector.store;
+  this.telemetry = inspector.telemetry;
   this.walker = this.inspector.walker;
 
   this.getSwatchColorPickerTooltip = this.getSwatchColorPickerTooltip.bind(this);
   this.updateGridPanel = this.updateGridPanel.bind(this);
 
   this.onGridLayoutChange = this.onGridLayoutChange.bind(this);
   this.onHighlighterChange = this.onHighlighterChange.bind(this);
   this.onReflow = this.onReflow.bind(this);
@@ -86,29 +89,30 @@ GridInspector.prototype = {
       {
         supportsCssColor4ColorFunction: () => false
       }
     );
 
     this.highlighters.on("grid-highlighter-hidden", this.onHighlighterChange);
     this.highlighters.on("grid-highlighter-shown", this.onHighlighterChange);
     this.inspector.sidebar.on("select", this.onSidebarSelect);
+    this.inspector.target.on("navigate", this.onGridLayoutChange);
 
     this.onSidebarSelect();
   }),
 
   /**
    * Destruction function called when the inspector is destroyed. Removes event listeners
    * and cleans up references.
    */
   destroy() {
     this.highlighters.off("grid-highlighter-hidden", this.onHighlighterChange);
     this.highlighters.off("grid-highlighter-shown", this.onHighlighterChange);
     this.inspector.sidebar.off("select", this.onSidebarSelect);
-    this.layoutInspector.off("grid-layout-changed", this.onGridLayoutChange);
+    this.inspector.target.off("navigate", this.onGridLayoutChange);
 
     this.inspector.reflowTracker.untrackReflows(this, this.onReflow);
 
     this.swatchColorPickerTooltip.destroy();
 
     this.document = null;
     this.highlighters = null;
     this.inspector = null;
@@ -235,41 +239,44 @@ GridInspector.prototype = {
     this.highlighters.showGridHighlighter(node, settings);
   },
 
   toggleGridHighlighter(node, settings) {
     this.lastHighlighterColor = settings.color;
     this.lastHighlighterNode = node;
     this.lastHighlighterState = node !== this.highlighters.gridHighlighterShown;
 
-    this.highlighters.toggleGridHighlighter(node, settings);
+    this.highlighters.toggleGridHighlighter(node, settings, "grid");
   },
 
   /**
    * Updates the grid panel by dispatching the new grid data. This is called when the
    * layout view becomes visible or the view needs to be updated with new grid data.
-   *
-   * @param  {Array|null} gridFronts
-   *         Optional array of all GridFront in the current page.
    */
-  updateGridPanel: Task.async(function* (gridFronts) {
+  updateGridPanel: Task.async(function* () {
     // Stop refreshing if the inspector or store is already destroyed.
     if (!this.inspector || !this.store) {
       return;
     }
 
     // Get all the GridFront from the server if no gridFronts were provided.
-    if (!gridFronts) {
-      try {
-        gridFronts = yield this.layoutInspector.getAllGrids(this.walker.rootNode);
-      } catch (e) {
-        // This call might fail if called asynchrously after the toolbox is finished
-        // closing.
-        return;
-      }
+    let gridFronts;
+    try {
+      gridFronts = yield this.layoutInspector.getAllGrids(this.walker.rootNode);
+    } catch (e) {
+      // This call might fail if called asynchrously after the toolbox is finished
+      // closing.
+      return;
+    }
+
+    // Log how many CSS Grid elements DevTools sees.
+    if (gridFronts.length > 0 &&
+        this.inspector.target.url != this.inspector.previousURL) {
+      this.telemetry.log(CSS_GRID_COUNT_HISTOGRAM_ID, gridFronts.length);
+      this.inspector.previousURL = this.inspector.target.url;
     }
 
     let grids = [];
     for (let i = 0; i < gridFronts.length; i++) {
       let grid = gridFronts[i];
 
       let nodeFront;
       try {
@@ -291,24 +298,21 @@ GridInspector.prototype = {
         nodeFront,
       });
     }
 
     this.store.dispatch(updateGrids(grids));
   }),
 
   /**
-   * Handler for "grid-layout-changed" events emitted from the LayoutActor.
-   *
-   * @param  {Array} grids
-   *         Array of all GridFront in the current page.
+   * Handler for "navigate" event fired by the tab target. Updates grid panel contents.
    */
-  onGridLayoutChange(grids) {
+  onGridLayoutChange() {
     if (this.isPanelVisible()) {
-      this.updateGridPanel(grids);
+      this.updateGridPanel();
     }
   },
 
   /**
    * Handler for "grid-highlighter-shown" and "grid-highlighter-hidden" events emitted
    * from the HighlightersOverlay. Updates the NodeFront's grid highlighted state.
    *
    * @param  {Event} event
@@ -456,33 +460,30 @@ GridInspector.prototype = {
     highlighterSettings.color = color;
 
     this.showGridHighlighter(node, highlighterSettings);
 
     this.store.dispatch(updateGridHighlighted(node, true));
   },
 
   /**
-   * Handler for the inspector sidebar select event. Starts listening for
-   * "grid-layout-changed" if the layout panel is visible. Otherwise, stop
-   * listening for grid layout changes. Finally, refresh the layout view if
-   * it is visible.
+   * Handler for the inspector sidebar "select" event. Starts tracking reflows
+   * if the layout panel is visible. Otherwise, stop tracking reflows.
+   * Finally, refresh the layout view if it is visible.
    */
   onSidebarSelect() {
     if (!this.isPanelVisible()) {
-      this.layoutInspector.off("grid-layout-changed", this.onGridLayoutChange);
       this.inspector.reflowTracker.untrackReflows(this, this.onReflow);
       return;
     }
 
     // @remove after release 56 (See Bug 1355747)
     Services.prefs.setIntPref(PROMOTE_COUNT_PREF, 0);
 
     this.inspector.reflowTracker.trackReflows(this, this.onReflow);
-    this.layoutInspector.on("grid-layout-changed", this.onGridLayoutChange);
     this.updateGridPanel();
   },
 
   /**
    * Handler for a change in the input checkboxes in the GridList component.
    * Toggles on/off the grid highlighter for the provided grid container element.
    *
    * @param  {NodeFront} node
@@ -504,16 +505,20 @@ GridInspector.prototype = {
     *
     * @param  {Boolean} enabled
     *         Whether or not the grid highlighter should show the grid areas.
     */
   onToggleShowGridAreas(enabled) {
     this.store.dispatch(updateShowGridAreas(enabled));
     Services.prefs.setBoolPref(SHOW_GRID_AREAS, enabled);
 
+    if (enabled) {
+      this.telemetry.toolOpened("gridInspectorShowGridAreasOverlayChecked");
+    }
+
     let { grids } = this.store.getState();
 
     for (let grid of grids) {
       if (grid.highlighted) {
         let highlighterSettings = this.getGridHighlighterSettings(grid.nodeFront);
         this.highlighters.showGridHighlighter(grid.nodeFront, highlighterSettings);
       }
     }
@@ -527,16 +532,20 @@ GridInspector.prototype = {
    *
    * @param  {Boolean} enabled
    *         Whether or not the grid highlighter should show the grid line numbers.
    */
   onToggleShowGridLineNumbers(enabled) {
     this.store.dispatch(updateShowGridLineNumbers(enabled));
     Services.prefs.setBoolPref(SHOW_GRID_LINE_NUMBERS, enabled);
 
+    if (enabled) {
+      this.telemetry.toolOpened("gridInspectorShowGridLineNumbersChecked");
+    }
+
     let { grids } = this.store.getState();
 
     for (let grid of grids) {
       if (grid.highlighted) {
         let highlighterSettings = this.getGridHighlighterSettings(grid.nodeFront);
         this.showGridHighlighter(grid.nodeFront, highlighterSettings);
       }
     }
@@ -550,16 +559,20 @@ GridInspector.prototype = {
    *
    * @param  {Boolean} enabled
    *         Whether or not the grid highlighter should extend grid lines infinitely.
    */
   onToggleShowInfiniteLines(enabled) {
     this.store.dispatch(updateShowInfiniteLines(enabled));
     Services.prefs.setBoolPref(SHOW_INFINITE_LINES_PREF, enabled);
 
+    if (enabled) {
+      this.telemetry.toolOpened("gridInspectorShowInfiniteLinesChecked");
+    }
+
     let { grids } = this.store.getState();
 
     for (let grid of grids) {
       if (grid.highlighted) {
         let highlighterSettings = this.getGridHighlighterSettings(grid.nodeFront);
         this.showGridHighlighter(grid.nodeFront, highlighterSettings);
       }
     }
--- a/devtools/client/inspector/grids/test/browser.ini
+++ b/devtools/client/inspector/grids/test/browser.ini
@@ -24,8 +24,9 @@ support-files =
 [browser_grids_grid-list-on-mutation-element-removed.js]
 [browser_grids_grid-list-toggle-multiple-grids.js]
 [browser_grids_grid-list-toggle-single-grid.js]
 [browser_grids_grid-outline-cannot-show-outline.js]
 [browser_grids_grid-outline-highlight-area.js]
 [browser_grids_grid-outline-highlight-cell.js]
 [browser_grids_grid-outline-selected-grid.js]
 [browser_grids_highlighter-setting-rules-grid-toggle.js]
+[browser_grids_number-of-css-grids-telemetry.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/grids/test/browser_grids_number-of-css-grids-telemetry.js
@@ -0,0 +1,45 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Tests that the telemetry count for the number of CSS Grid Elements on a page navigation
+// is correct when the toolbox is opened.
+
+const TEST_URI1 = `
+  <div></div>
+`;
+
+const TEST_URI2 = `
+  <style type='text/css'>
+    #grid {
+      display: grid;
+    }
+  </style>
+  <div id="grid">
+    <div id="cell1">cell1</div>
+    <div id="cell2">cell2</div>
+  </div>
+`;
+
+const CSS_GRID_COUNT_HISTOGRAM_ID = "DEVTOOLS_NUMBER_OF_CSS_GRIDS_IN_A_PAGE";
+
+add_task(function* () {
+  yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI1));
+
+  let { inspector } = yield openLayoutView();
+  let { store } = inspector;
+
+  info("Navigate to TEST_URI2");
+
+  let onGridListUpdate = waitUntilState(store, state => state.grids.length == 1);
+  yield navigateTo(inspector,
+    "data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI2));
+  yield onGridListUpdate;
+
+  let histogram = Services.telemetry.getHistogramById(CSS_GRID_COUNT_HISTOGRAM_ID);
+  let snapshot = histogram.snapshot();
+
+  is(snapshot.counts[1], 1, "Got a count of 1 for 1 CSS Grid element seen.");
+  is(snapshot.sum, 1, "Got the correct sum.");
+});
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -96,16 +96,20 @@ function Inspector(toolbox) {
   // Stores all the instances of sidebar panels like rule view, computed view, ...
   this._panels = new Map();
 
   this.highlighters = new HighlightersOverlay(this);
   this.reflowTracker = new ReflowTracker(this._target);
   this.store = Store();
   this.telemetry = new Telemetry();
 
+  // Store the URL of the target page prior to navigation in order to ensure
+  // telemetry counts in the Grid Inspector are not double counted on reload.
+  this.previousURL = this.target.url;
+
   this.nodeMenuTriggerInfo = null;
 
   this._handleRejectionIfNotDestroyed = this._handleRejectionIfNotDestroyed.bind(this);
   this._onBeforeNavigate = this._onBeforeNavigate.bind(this);
   this.onNewRoot = this.onNewRoot.bind(this);
   this._onContextMenu = this._onContextMenu.bind(this);
   this.onTextBoxContextMenu = this.onTextBoxContextMenu.bind(this);
   this._updateSearchResultsLabel = this._updateSearchResultsLabel.bind(this);
--- a/devtools/client/inspector/shared/highlighters-overlay.js
+++ b/devtools/client/inspector/shared/highlighters-overlay.js
@@ -1,16 +1,17 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
+const Services = require("Services");
 const {Task} = require("devtools/shared/task");
 const EventEmitter = require("devtools/shared/event-emitter");
 const { VIEW_NODE_VALUE_TYPE } = require("devtools/client/inspector/shared/node-types");
 
 const DEFAULT_GRID_COLOR = "#4B0082";
 
 /**
  * Highlighters overlay is a singleton managing all highlighters in the Inspector.
@@ -102,47 +103,57 @@ HighlightersOverlay.prototype = {
 
   /**
    * Toggle the grid highlighter for the given grid container element.
    *
    * @param  {NodeFront} node
    *         The NodeFront of the grid container element to highlight.
    * @param  {Object} options
    *         Object used for passing options to the grid highlighter.
+   * @param. {String|null} trigger
+   *         String name matching "grid" or "rule" to indicate where the
+   *         grid highlighter was toggled on from. "grid" represents the grid view
+   *         "rule" represents the rule view.
    */
-  toggleGridHighlighter: Task.async(function* (node, options = {}) {
+  toggleGridHighlighter: Task.async(function* (node, options = {}, trigger) {
     if (node == this.gridHighlighterShown) {
       yield this.hideGridHighlighter(node);
       return;
     }
 
-    yield this.showGridHighlighter(node, options);
+    yield this.showGridHighlighter(node, options, trigger);
   }),
 
   /**
    * Show the grid highlighter for the given grid container element.
    *
    * @param  {NodeFront} node
    *         The NodeFront of the grid container element to highlight.
    * @param  {Object} options
    *         Object used for passing options to the grid highlighter.
    */
-  showGridHighlighter: Task.async(function* (node, options) {
+  showGridHighlighter: Task.async(function* (node, options, trigger) {
     let highlighter = yield this._getHighlighter("CssGridHighlighter");
     if (!highlighter) {
       return;
     }
 
     let isShown = yield highlighter.show(node, options);
     if (!isShown) {
       return;
     }
 
     this._toggleRuleViewGridIcon(node, true);
 
+    if (trigger == "grid") {
+      Services.telemetry.scalarAdd("devtools.grid.gridinspector.opened", 1);
+    } else if (trigger == "rule") {
+      Services.telemetry.scalarAdd("devtools.rules.gridinspector.opened", 1);
+    }
+
     try {
       // Save grid highlighter state.
       let { url } = this.inspector.target;
       let selector = yield node.getUniqueSelector();
       this.state.grid = { selector, options, url };
 
       this.gridHighlighterShown = node;
       // Emit the NodeFront of the grid container element that the grid highlighter was
@@ -386,17 +397,18 @@ HighlightersOverlay.prototype = {
     event.stopPropagation();
 
     let { store } = this.inspector;
     let { grids, highlighterSettings } = store.getState();
     let grid = grids.find(g => g.nodeFront == this.inspector.selection.nodeFront);
 
     highlighterSettings.color = grid ? grid.color : DEFAULT_GRID_COLOR;
 
-    this.toggleGridHighlighter(this.inspector.selection.nodeFront, highlighterSettings);
+    this.toggleGridHighlighter(this.inspector.selection.nodeFront, highlighterSettings,
+      "rule");
   },
 
   onMouseMove: function (event) {
     // Bail out if the target is the same as for the last mousemove.
     if (event.target === this._lastHovered) {
       return;
     }
 
@@ -511,16 +523,17 @@ HighlightersOverlay.prototype = {
     this.inspector.target.off("will-navigate", this.onWillNavigate);
 
     this._lastHovered = null;
 
     this.inspector = null;
     this.highlighters = null;
     this.highlighterUtils = null;
     this.supportsHighlighters = null;
+    this.state = null;
 
     this.geometryEditorHighlighterShown = null;
     this.gridHighlighterShown = null;
     this.hoveredHighlighterShown = null;
     this.selectorHighlighterShown = null;
 
     this.destroyed = true;
   }
--- a/devtools/client/shared/telemetry.js
+++ b/devtools/client/shared/telemetry.js
@@ -172,16 +172,25 @@ Telemetry.prototype = {
       timerHistogram: "DEVTOOLS_CUSTOM_TIME_ACTIVE_SECONDS"
     },
     reloadAddonInstalled: {
       histogram: "DEVTOOLS_RELOAD_ADDON_INSTALLED_COUNT",
     },
     reloadAddonReload: {
       histogram: "DEVTOOLS_RELOAD_ADDON_RELOAD_COUNT",
     },
+    gridInspectorShowGridAreasOverlayChecked: {
+      scalar: "devtools.grid.showGridAreasOverlay.checked",
+    },
+    gridInspectorShowGridLineNumbersChecked: {
+      scalar: "devtools.grid.showGridLineNumbers.checked",
+    },
+    gridInspectorShowInfiniteLinesChecked: {
+      scalar: "devtools.grid.showInfiniteLines.checked",
+    },
   },
 
   /**
    * Add an entry to a histogram.
    *
    * @param  {String} id
    *         Used to look up the relevant histogram ID and log true to that
    *         histogram.
--- a/devtools/server/actors/layout.js
+++ b/devtools/server/actors/layout.js
@@ -1,15 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-const events = require("sdk/event/core");
 const { Actor, ActorClassWithSpec } = require("devtools/shared/protocol");
 const { getStringifiableFragments } =
   require("devtools/server/actors/utils/css-grid-utils");
 const { gridSpec, layoutSpec } = require("devtools/shared/specs/layout");
 
 /**
  * Set of actors the expose the CSS layout information to the devtools protocol clients.
  *
@@ -67,27 +66,21 @@ var GridActor = ActorClassWithSpec(gridS
  * The CSS layout actor provides layout information for the given document.
  */
 var LayoutActor = ActorClassWithSpec(layoutSpec, {
   initialize: function (conn, tabActor, walker) {
     Actor.prototype.initialize.call(this, conn);
 
     this.tabActor = tabActor;
     this.walker = walker;
-
-    this.onNavigate = this.onNavigate.bind(this);
-
-    events.on(this.tabActor, "navigate", this.onNavigate);
   },
 
   destroy: function () {
     Actor.prototype.destroy.call(this);
 
-    events.off(this.tabActor, "navigate", this.onNavigate);
-
     this.tabActor = null;
     this.walker = null;
   },
 
   /**
    * Returns an array of GridActor objects for all the grid containers found by iterating
    * below the given rootNode.
    *
@@ -137,17 +130,12 @@ var LayoutActor = ActorClassWithSpec(lay
 
     for (let {document} of this.tabActor.windows) {
       grids = [...grids, ...this.getGrids(document.documentElement)];
     }
 
     return grids;
   },
 
-  onNavigate: function () {
-    let grids = this.getAllGrids(this.walker.rootNode);
-    events.emit(this, "grid-layout-changed", grids);
-  },
-
 });
 
 exports.GridActor = GridActor;
 exports.LayoutActor = LayoutActor;
--- a/devtools/shared/specs/layout.js
+++ b/devtools/shared/specs/layout.js
@@ -11,23 +11,16 @@ const gridSpec = generateActorSpec({
   typeName: "grid",
 
   methods: {},
 });
 
 const layoutSpec = generateActorSpec({
   typeName: "layout",
 
-  events: {
-    "grid-layout-changed": {
-      type: "grid-layout-changed",
-      grids: Arg(0, "array:grid")
-    }
-  },
-
   methods: {
     getAllGrids: {
       request: {
         rootNode: Arg(0, "domnode"),
         traverseFrames: Arg(1, "nullable:boolean")
       },
       response: {
         grids: RetVal("array:grid")
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -10092,16 +10092,27 @@
     "record_in_processes": ["main", "content"],
     "bug_numbers": [1347517],
     "alert_emails": ["dev-developer-tools@lists.mozilla.org"],
     "expires_in_version": "never",
     "keyed": true,
     "kind": "count",
     "description": "Reports the command name used in GCLI e.g. 'screenshot'"
   },
+  "DEVTOOLS_NUMBER_OF_CSS_GRIDS_IN_A_PAGE": {
+    "record_in_processes": ["main", "content"],
+    "alert_emails": ["dev-developer-tools@lists.mozilla.org"],
+    "expires_in_version": "never",
+    "kind": "linear",
+    "high": 30,
+    "n_buckets": 29,
+    "bug_numbers": [1373483],
+    "description": "On page load, record the number of CSS Grid elements present on a page when the DevTools is open",
+    "releaseChannelCollection": "opt-out"
+  },
   "VIEW_SOURCE_IN_BROWSER_OPENED_BOOLEAN": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["mozilla-dev-developer-tools@lists.mozilla.org", "jryans@mozilla.com"],
     "expires_in_version": "53",
     "kind": "boolean",
     "description": "How many times has view source in browser / tab been opened?"
   },
   "VIEW_SOURCE_IN_WINDOW_OPENED_BOOLEAN": {
--- a/toolkit/components/telemetry/Scalars.yaml
+++ b/toolkit/components/telemetry/Scalars.yaml
@@ -471,16 +471,86 @@ devtools.copy.xpath:
     expires: "58"
     kind: uint
     notification_emails:
       - dev-developer-tools@lists.mozilla.org
     release_channel_collection: opt-out
     record_in_processes:
       - 'main'
 
+devtools.rules.gridinspector:
+  opened:
+    bug_numbers:
+      - 1373483
+    description: >
+      Number of times the DevTools grid inspector was opened from the rules view.
+    expires: never
+    kind: uint
+    notification_emails:
+      - dev-developer-tools@lists.mozilla.org
+    release_channel_collection: opt-out
+    record_in_processes:
+      - 'main'
+
+devtools.grid.gridinspector:
+  opened:
+    bug_numbers:
+      - 1373483
+    description: >
+      Number of times the DevTools grid inspector was opened from the grid view.
+    expires: never
+    kind: uint
+    notification_emails:
+      - dev-developer-tools@lists.mozilla.org
+    release_channel_collection: opt-out
+    record_in_processes:
+      - 'main'
+
+devtools.grid.showGridAreasOverlay:
+  checked:
+    bug_numbers:
+      - 1373483
+    description: >
+      Number of times the DevTools grid inspector's "Display grid areas" was checked.
+    expires: never
+    kind: uint
+    notification_emails:
+      - dev-developer-tools@lists.mozilla.org
+    release_channel_collection: opt-out
+    record_in_processes:
+      - 'main'
+
+devtools.grid.showGridLineNumbers:
+  checked:
+    bug_numbers:
+      - 1373483
+    description: >
+      Number of times the DevTools grid inspector's "Display grid numbers" was checked.
+    expires: never
+    kind: uint
+    notification_emails:
+      - dev-developer-tools@lists.mozilla.org
+    release_channel_collection: opt-out
+    record_in_processes:
+      - 'main'
+
+devtools.grid.showInfiniteLines:
+  checked:
+    bug_numbers:
+      - 1373483
+    description: >
+      Number of times the DevTools grid inspector's "Extend grid lines infinitely" was checked.
+    expires: never
+    kind: uint
+    notification_emails:
+      - dev-developer-tools@lists.mozilla.org
+    release_channel_collection: opt-out
+    record_in_processes:
+      - 'main'
+
 navigator.storage:
   estimate_count:
     bug_numbers:
       - 1359708
     description: >
       Number of times navigator.storage.estimate has been used.
     expires: "60"
     kind: uint