Bug 1468761 - Migrate external Telemetry tests to handle packed histograms r=chutten
☠☠ backed out by a67cc39bf78a ☠ ☠
authorJan-Erik Rediger <jrediger@mozilla.com>
Mon, 22 Oct 2018 15:26:34 +0000
changeset 490757 8c08dcec61d8a3e5e234aacae1e2a373545bcdeb
parent 490756 9ee8406cf1d3585cb4090101ec48aa7fc696bc97
child 490758 42412209a3220de529f13d8ab51987e7a55c0213
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewerschutten
bugs1468761
milestone64.0a1
Bug 1468761 - Migrate external Telemetry tests to handle packed histograms r=chutten Depends on D9236 Differential Revision: https://phabricator.services.mozilla.com/D9237
browser/base/content/test/tabs/browser_abandonment_telemetry.js
browser/base/content/test/tabs/browser_tabCloseProbes.js
browser/base/content/test/tabs/browser_tabSpinnerProbe.js
browser/base/content/test/trackingUI/browser_trackingUI_telemetry.js
browser/components/extensions/test/browser/browser_ext_browserAction_telemetry.js
browser/components/extensions/test/browser/browser_ext_pageAction_telemetry.js
browser/components/search/test/browser_aboutSearchReset.js
browser/components/sessionstore/test/browser_522375.js
browser/components/sessionstore/test/unit/test_histogram_corrupt_files.js
browser/components/translation/test/browser_translation_telemetry.js
browser/modules/test/browser/browser_UsageTelemetry.js
browser/modules/test/browser/browser_UsageTelemetry_searchbar.js
browser/modules/test/browser/browser_UsageTelemetry_urlbar.js
devtools/client/framework/test/browser_toolbox_hosts_telemetry.js
devtools/client/inspector/grids/test/browser_grids_number-of-css-grids-telemetry.js
devtools/client/performance/test/browser_perf-telemetry-01.js
devtools/client/performance/test/browser_perf-telemetry-02.js
devtools/client/performance/test/browser_perf-telemetry-04.js
devtools/client/shared/test/browser_telemetry_button_paintflashing.js
devtools/client/shared/test/browser_telemetry_button_responsive.js
devtools/client/shared/test/browser_telemetry_button_scratchpad.js
devtools/client/shared/test/browser_telemetry_misc.js
devtools/client/shared/test/browser_telemetry_sidebar.js
devtools/client/shared/test/browser_telemetry_toolbox.js
devtools/client/shared/test/browser_telemetry_toolboxtabs_canvasdebugger.js
devtools/client/shared/test/browser_telemetry_toolboxtabs_inspector.js
devtools/client/shared/test/browser_telemetry_toolboxtabs_jsdebugger.js
devtools/client/shared/test/browser_telemetry_toolboxtabs_jsprofiler.js
devtools/client/shared/test/browser_telemetry_toolboxtabs_netmonitor.js
devtools/client/shared/test/browser_telemetry_toolboxtabs_options.js
devtools/client/shared/test/browser_telemetry_toolboxtabs_shadereditor.js
devtools/client/shared/test/browser_telemetry_toolboxtabs_storage.js
devtools/client/shared/test/browser_telemetry_toolboxtabs_styleeditor.js
devtools/client/shared/test/browser_telemetry_toolboxtabs_webaudioeditor.js
devtools/client/shared/test/browser_telemetry_toolboxtabs_webconsole.js
devtools/client/shared/test/telemetry-test-helpers.js
dom/webauthn/tests/browser/browser_webauthn_telemetry.js
--- a/browser/base/content/test/tabs/browser_abandonment_telemetry.js
+++ b/browser/base/content/test/tabs/browser_abandonment_telemetry.js
@@ -201,21 +201,21 @@ const PROBE_TESTS = [
  * @param snapshot (Object)
  *        The Telemetry histogram snapshot to examine.
  * @param category (String)
  *        The category in CATEGORIES whose index we expect to have
  *        been set to 1.
  */
 function assertOnlyOneTypeSet(snapshot, category) {
   let categoryIndex = CATEGORIES.indexOf(category);
-  Assert.equal(snapshot.counts[categoryIndex], 1,
+  Assert.equal(snapshot.values[categoryIndex], 1,
                `Should have seen the ${category} count increment.`);
   // Use Array.prototype.reduce to sum up all of the
   // snapshot.count entries
-  Assert.equal(snapshot.counts.reduce((a, b) => a + b), 1,
+  Assert.equal(Object.values(snapshot.values).reduce((a, b) => a + b, 0), 1,
                "Should only be 1 collected value.");
 }
 
 /**
  * A helper function for simulating clicking on the history
  * navigation popup menu that you get if you click and hold
  * on the back or forward buttons when you have some browsing
  * history.
--- a/browser/base/content/test/tabs/browser_tabCloseProbes.js
+++ b/browser/base/content/test/tabs/browser_tabCloseProbes.js
@@ -11,17 +11,17 @@ var gNoAnimHistogram = Services.telemetr
  * @param snapshot (Object)
  *        The Telemetry histogram snapshot to examine.
  * @return (int)
  *         The sum of all counts in the snapshot.
  */
 function snapshotCount(snapshot) {
   // Use Array.prototype.reduce to sum up all of the
   // snapshot.count entries
-  return snapshot.counts.reduce((a, b) => a + b);
+  return Object.values(snapshot.values).reduce((a, b) => a + b, 0);
 }
 
 /**
  * Takes a Telemetry histogram snapshot and makes sure
  * that the sum of all counts equals expectedCount.
  *
  * @param snapshot (Object)
  *        The Telemetry histogram snapshot to examine.
--- a/browser/base/content/test/tabs/browser_tabSpinnerProbe.js
+++ b/browser/base/content/test/tabs/browser_tabSpinnerProbe.js
@@ -45,20 +45,17 @@ function hangContentProcess(browser, aMs
  * telemetry probes.
  * @param {String} aProbe The probe to test. Should be one of:
  *                  - FX_TAB_SWITCH_SPINNER_VISIBLE_MS
  *                  - FX_TAB_SWITCH_SPINNER_VISIBLE_LONG_MS
  */
 async function testProbe(aProbe) {
   info(`Testing probe: ${aProbe}`);
   let histogram = Services.telemetry.getHistogramById(aProbe);
-  let buckets = histogram.snapshot().ranges.filter(function(value) {
-    return (value > MIN_HANG_TIME && value < MAX_HANG_TIME);
-  });
-  let delayTime = buckets[0]; // Pick a bucket arbitrarily
+  let delayTime = MIN_HANG_TIME + 1; // Pick a bucket arbitrarily
 
   // The tab spinner does not show up instantly. We need to hang for a little
   // bit of extra time to account for the tab spinner delay.
   delayTime += gBrowser.selectedTab.linkedBrowser.getTabBrowser()._getSwitcher().TAB_SWITCH_TIMEOUT;
 
   // In order for a spinner to be shown, the tab must have presented before.
   let origTab = gBrowser.selectedTab;
   let hangTab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
@@ -73,17 +70,17 @@ async function testProbe(aProbe) {
   histogram.clear();
   let hangTabSwitch = BrowserTestUtils.switchTab(gBrowser, hangTab);
   await tabHangPromise;
   await hangTabSwitch;
 
   // Now we should have a hang in our histogram.
   let snapshot = histogram.snapshot();
   BrowserTestUtils.removeTab(hangTab);
-  ok(sum(snapshot.counts) > 0,
+  ok(sum(Object.values(snapshot.values)) > 0,
    `Spinner probe should now have a value in some bucket`);
 }
 
 add_task(async function setup() {
   await SpecialPowers.pushPrefEnv({
     set: [
       ["dom.ipc.processCount", 1],
       // We can interrupt JS to paint now, which is great for
--- a/browser/base/content/test/trackingUI/browser_trackingUI_telemetry.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_telemetry.js
@@ -17,28 +17,28 @@ registerCleanupFunction(function() {
   Services.prefs.clearUserPref(PREF);
 });
 
 function getShieldHistogram() {
   return Services.telemetry.getHistogramById("TRACKING_PROTECTION_SHIELD");
 }
 
 function getShieldCounts() {
-  return getShieldHistogram().snapshot().counts;
+  return getShieldHistogram().snapshot().values;
 }
 
 add_task(async function setup() {
   await UrlClassifierTestUtils.addTestTrackers();
 
   let TrackingProtection = gBrowser.ownerGlobal.TrackingProtection;
   ok(TrackingProtection, "TP is attached to the browser window");
   ok(!TrackingProtection.enabled, "TP is not enabled");
 
   let enabledCounts =
-    Services.telemetry.getHistogramById("TRACKING_PROTECTION_ENABLED").snapshot().counts;
+    Services.telemetry.getHistogramById("TRACKING_PROTECTION_ENABLED").snapshot().values;
   is(enabledCounts[0], 1, "TP was not enabled on start up");
 
   let scalars = Services.telemetry.snapshotScalars(
     Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTOUT, false).parent;
 
   is(scalars["contentblocking.enabled"], Services.prefs.getBoolPref("browser.contentblocking.enabled"),
     "CB enabled status was recorded at startup");
   is(scalars["contentblocking.fastblock_enabled"], Services.prefs.getBoolPref("browser.fastblock.enabled"),
--- a/browser/components/extensions/test/browser/browser_ext_browserAction_telemetry.js
+++ b/browser/components/extensions/test/browser/browser_ext_browserAction_telemetry.js
@@ -27,21 +27,21 @@ const CATEGORIES = [
  * @param {Object} snapshot
  *        The Telemetry histogram snapshot to examine.
  * @param {string} category
  *        The category in CATEGORIES whose index we expect to have
  *        been set to 1.
  */
 function assertOnlyOneTypeSet(snapshot, category) {
   let categoryIndex = CATEGORIES.indexOf(category);
-  Assert.equal(snapshot.counts[categoryIndex], 1,
+  Assert.equal(snapshot.values[categoryIndex], 1,
                `Should have seen the ${category} count increment.`);
   // Use Array.prototype.reduce to sum up all of the
   // snapshot.count entries
-  Assert.equal(snapshot.counts.reduce((a, b) => a + b), 1,
+  Assert.equal(Object.values(snapshot.values).reduce((a, b) => a + b, 0), 1,
                "Should only be 1 collected value.");
 }
 
 add_task(async function testBrowserActionTelemetryTiming() {
   let extensionOptions = {
     manifest: {
       "browser_action": {
         "default_popup": "popup.html",
--- a/browser/components/extensions/test/browser/browser_ext_pageAction_telemetry.js
+++ b/browser/components/extensions/test/browser/browser_ext_pageAction_telemetry.js
@@ -4,17 +4,17 @@
 
 const HISTOGRAM = "WEBEXT_PAGEACTION_POPUP_OPEN_MS";
 const HISTOGRAM_KEYED = "WEBEXT_PAGEACTION_POPUP_OPEN_MS_BY_ADDONID";
 
 const EXTENSION_ID1 = "@test-extension1";
 const EXTENSION_ID2 = "@test-extension2";
 
 function snapshotCountsSum(snapshot) {
-  return snapshot.counts.reduce((a, b) => a + b, 0);
+  return Object.values(snapshot.values).reduce((a, b) => a + b, 0);
 }
 
 function histogramCountsSum(histogram) {
   return snapshotCountsSum(histogram.snapshot());
 }
 
 add_task(async function testPageActionTelemetry() {
   let extensionOptions = {
--- a/browser/components/search/test/browser_aboutSearchReset.js
+++ b/browser/components/search/test/browser_aboutSearchReset.js
@@ -15,23 +15,23 @@ const kSearchPurpose = "searchbar";
 
 const kTestEngine = "testEngine.xml";
 
 const kStatusPref = "browser.search.reset.status";
 
 function checkTelemetryRecords(expectedValue) {
   let histogram = Services.telemetry.getHistogramById("SEARCH_RESET_RESULT");
   let snapshot = histogram.snapshot();
-  // The probe is declared with 5 values, but we get 6 back from .counts
-  let expectedCounts = [0, 0, 0, 0, 0, 0];
   if (expectedValue != null) {
-    expectedCounts[expectedValue] = 1;
+    Assert.deepEqual(snapshot.values[expectedValue], 1,
+                     "histogram has expected content");
+  } else {
+    Assert.deepEqual(!!snapshot.values[expectedValue], false,
+                     "histogram has expected content");
   }
-  Assert.deepEqual(snapshot.counts, expectedCounts,
-                   "histogram has expected content");
   histogram.clear();
 }
 
 function promiseStoppedLoad(expectedURL) {
   return new Promise(resolve => {
     let browser = gBrowser.selectedBrowser;
     let original = browser.loadURI;
     browser.loadURI = function(URI) {
--- a/browser/components/sessionstore/test/browser_522375.js
+++ b/browser/components/sessionstore/test/browser_522375.js
@@ -2,17 +2,17 @@ function test() {
   var startup_info = Services.startup.getStartupInfo();
   // No .process info on mac
 
   // Check if we encountered a telemetry error for the the process creation
   // timestamp and turn the first test into a known failure.
   var snapshot = Services.telemetry.getHistogramById("STARTUP_MEASUREMENT_ERRORS")
                                    .snapshot();
 
-  if (snapshot.counts[0] == 0)
+  if (snapshot.values[0] == 0)
     ok(startup_info.process <= startup_info.main, "process created before main is run " + uneval(startup_info));
   else
     todo(false, "An error occurred while recording the process creation timestamp, skipping this test");
 
   // on linux firstPaint can happen after everything is loaded (especially with remote X)
   if (startup_info.firstPaint)
     ok(startup_info.main <= startup_info.firstPaint, "main ran before first paint " + uneval(startup_info));
 
--- a/browser/components/sessionstore/test/unit/test_histogram_corrupt_files.js
+++ b/browser/components/sessionstore/test/unit/test_histogram_corrupt_files.js
@@ -57,18 +57,18 @@ add_task(async function test_ensure_hist
 add_task(async function test_no_files_exist() {
   // No session files are available to SessionFile.
   await promise_reset_session();
 
   await SessionFile.read();
   // Checking if the histogram is updated negatively
   let h = Telemetry.getHistogramById(HistogramId);
   let s = h.snapshot();
-  Assert.equal(s.counts[0], 1, "One probe for the 'false' bucket.");
-  Assert.equal(s.counts[1], 0, "No probes in the 'true' bucket.");
+  Assert.equal(s.values[0], 1, "One probe for the 'false' bucket.");
+  Assert.equal(s.values[1], 0, "No probes in the 'true' bucket.");
 });
 
 /**
  * Makes sure that the histogram is negatively updated when at least one
  * backup file is not corrupted.
  */
 add_task(async function test_one_file_valid() {
   // Corrupting some backup files.
@@ -80,18 +80,18 @@ add_task(async function test_one_file_va
     recovery: invalidSession,
     recoveryBackup: invalidSession,
   });
 
   await SessionFile.read();
   // Checking if the histogram is updated negatively.
   let h = Telemetry.getHistogramById(HistogramId);
   let s = h.snapshot();
-  Assert.equal(s.counts[0], 1, "One probe for the 'false' bucket.");
-  Assert.equal(s.counts[1], 0, "No probes in the 'true' bucket.");
+  Assert.equal(s.values[0], 1, "One probe for the 'false' bucket.");
+  Assert.equal(s.values[1], 0, "No probes in the 'true' bucket.");
 });
 
 /**
  * Makes sure that the histogram is positively updated when all
  * backup files are corrupted.
  */
 add_task(async function test_all_files_corrupt() {
   // Corrupting all backup files.
@@ -102,11 +102,11 @@ add_task(async function test_all_files_c
     recovery: invalidSession,
     recoveryBackup: invalidSession,
   });
 
   await SessionFile.read();
   // Checking if the histogram is positively updated.
   let h = Telemetry.getHistogramById(HistogramId);
   let s = h.snapshot();
-  Assert.equal(s.counts[1], 1, "One probe for the 'true' bucket.");
-  Assert.equal(s.counts[0], 0, "No probes in the 'false' bucket.");
+  Assert.equal(s.values[1], 1, "One probe for the 'true' bucket.");
+  Assert.equal(s.values[0], 0, "No probes in the 'false' bucket.");
 });
--- a/browser/components/translation/test/browser_translation_telemetry.js
+++ b/browser/components/translation/test/browser_translation_telemetry.js
@@ -34,18 +34,18 @@ var MetricsChecker = {
   updateMetrics() {
     this._metrics = {
       opportunitiesCount: this.HISTOGRAMS.OPPORTUNITIES.snapshot().sum || 0,
       pageCount: this.HISTOGRAMS.PAGES.snapshot().sum || 0,
       charCount: this.HISTOGRAMS.CHARACTERS.snapshot().sum || 0,
       deniedOffers: this.HISTOGRAMS.DENIED.snapshot().sum || 0,
       autoRejectedOffers: this.HISTOGRAMS.AUTO_REJECTED.snapshot().sum || 0,
       showOriginal: this.HISTOGRAMS.SHOW_ORIGINAL.snapshot().sum || 0,
-      detectedLanguageChangedBefore: this.HISTOGRAMS.DETECTION_CHANGES.snapshot().counts[1] || 0,
-      detectedLanguageChangeAfter: this.HISTOGRAMS.DETECTION_CHANGES.snapshot().counts[0] || 0,
+      detectedLanguageChangedBefore: this.HISTOGRAMS.DETECTION_CHANGES.snapshot().values[1] || 0,
+      detectedLanguageChangeAfter: this.HISTOGRAMS.DETECTION_CHANGES.snapshot().values[0] || 0,
       targetLanguageChanged: this.HISTOGRAMS.TARGET_CHANGES.snapshot().sum || 0,
       showUI: this.HISTOGRAMS.SHOW_UI.snapshot().sum || 0,
       detectLang: this.HISTOGRAMS.DETECT_LANG.snapshot().sum || 0,
       // Metrics for Keyed histograms are estimated below.
       opportunitiesCountByLang: {},
       pageCountByLang: {},
     };
 
--- a/browser/modules/test/browser/browser_UsageTelemetry.js
+++ b/browser/modules/test/browser/browser_UsageTelemetry.js
@@ -132,86 +132,85 @@ add_task(async function test_subsessionS
   // Remove all the extra windows and tabs.
   for (let tab of openedTabs) {
     BrowserTestUtils.removeTab(tab);
   }
   await BrowserTestUtils.closeWindow(win);
 });
 
 function checkTabCountHistogram(result, expected, message) {
-  let expectedPadded = result.counts.map((val, idx) => idx < expected.length ? expected[idx] : 0);
-  Assert.deepEqual(result.counts, expectedPadded, message);
+  Assert.deepEqual(result.values, expected, message);
 }
 
 add_task(async function test_tabsHistogram() {
   let openedTabs = [];
   let tabCountHist = getAndClearHistogram("TAB_COUNT");
 
-  checkTabCountHistogram(tabCountHist.snapshot(), [0, 0], "TAB_COUNT telemetry - initial tab counts");
+  checkTabCountHistogram(tabCountHist.snapshot(), {}, "TAB_COUNT telemetry - initial tab counts");
 
   // Add a new tab and check that the count is right.
   BrowserUsageTelemetry._lastRecordTabCount = 0;
   openedTabs.push(await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank"));
-  checkTabCountHistogram(tabCountHist.snapshot(), [0, 0, 1], "TAB_COUNT telemetry - opening tabs");
+  checkTabCountHistogram(tabCountHist.snapshot(), {1: 0, 2: 1, 3: 0}, "TAB_COUNT telemetry - opening tabs");
 
   // Open a different page and check the counts.
   BrowserUsageTelemetry._lastRecordTabCount = 0;
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
   openedTabs.push(tab);
   BrowserUsageTelemetry._lastRecordTabCount = 0;
   await BrowserTestUtils.loadURI(tab.linkedBrowser, "http://example.com/");
   await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
-  checkTabCountHistogram(tabCountHist.snapshot(), [0, 0, 1, 2], "TAB_COUNT telemetry - loading page");
+  checkTabCountHistogram(tabCountHist.snapshot(), {1: 0, 2: 1, 3: 2, 4: 0}, "TAB_COUNT telemetry - loading page");
 
   // Open another tab
   BrowserUsageTelemetry._lastRecordTabCount = 0;
   openedTabs.push(await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank"));
-  checkTabCountHistogram(tabCountHist.snapshot(), [0, 0, 1, 2, 1], "TAB_COUNT telemetry - opening more tabs");
+  checkTabCountHistogram(tabCountHist.snapshot(), {1: 0, 2: 1, 3: 2, 4: 1, 5: 0}, "TAB_COUNT telemetry - opening more tabs");
 
   // Add a new window and then some tabs in it. A new window starts with one tab.
   BrowserUsageTelemetry._lastRecordTabCount = 0;
   let win = await BrowserTestUtils.openNewBrowserWindow();
-  checkTabCountHistogram(tabCountHist.snapshot(), [0, 0, 1, 2, 1, 1], "TAB_COUNT telemetry - opening window");
+  checkTabCountHistogram(tabCountHist.snapshot(), {1: 0, 2: 1, 3: 2, 4: 1, 5: 1, 6: 0}, "TAB_COUNT telemetry - opening window");
 
   // Do not trigger a recount if _lastRecordTabCount is recent on new tab
   BrowserUsageTelemetry._lastRecordTabCount = Date.now() - (MINIMUM_TAB_COUNT_INTERVAL_MS / 2);
   {
     let oldLastRecordTabCount = BrowserUsageTelemetry._lastRecordTabCount;
     openedTabs.push(await BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:blank"));
-    checkTabCountHistogram(tabCountHist.snapshot(), [0, 0, 1, 2, 1, 1, 0], "TAB_COUNT telemetry - new tab, recount event ignored");
+    checkTabCountHistogram(tabCountHist.snapshot(), {1: 0, 2: 1, 3: 2, 4: 1, 5: 1, 6: 0}, "TAB_COUNT telemetry - new tab, recount event ignored");
     ok(BrowserUsageTelemetry._lastRecordTabCount == oldLastRecordTabCount, "TAB_COUNT telemetry - _lastRecordTabCount unchanged");
   }
 
   // Trigger a recount if _lastRecordTabCount has passed on new tab
   BrowserUsageTelemetry._lastRecordTabCount = Date.now() - (MINIMUM_TAB_COUNT_INTERVAL_MS + 1000);
   {
     let oldLastRecordTabCount = BrowserUsageTelemetry._lastRecordTabCount;
     openedTabs.push(await BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:blank"));
-    checkTabCountHistogram(tabCountHist.snapshot(), [0, 0, 1, 2, 1, 1, 0, 1], "TAB_COUNT telemetry - new tab, recount event included");
+    checkTabCountHistogram(tabCountHist.snapshot(), {1: 0, 2: 1, 3: 2, 4: 1, 5: 1, 7: 1, 8: 0}, "TAB_COUNT telemetry - new tab, recount event included");
     ok(BrowserUsageTelemetry._lastRecordTabCount != oldLastRecordTabCount, "TAB_COUNT telemetry - _lastRecordTabCount updated");
     ok(BrowserUsageTelemetry._lastRecordTabCount > Date.now() - MINIMUM_TAB_COUNT_INTERVAL_MS, "TAB_COUNT telemetry - _lastRecordTabCount invariant");
   }
 
   // Do not trigger a recount if _lastRecordTabCount is recent on page load
   BrowserUsageTelemetry._lastRecordTabCount = Date.now() - (MINIMUM_TAB_COUNT_INTERVAL_MS / 2);
   {
     let oldLastRecordTabCount = BrowserUsageTelemetry._lastRecordTabCount;
     await BrowserTestUtils.loadURI(tab.linkedBrowser, "http://example.com/");
     await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
-    checkTabCountHistogram(tabCountHist.snapshot(), [0, 0, 1, 2, 1, 1, 0, 1], "TAB_COUNT telemetry - page load, recount event ignored");
+    checkTabCountHistogram(tabCountHist.snapshot(), {1: 0, 2: 1, 3: 2, 4: 1, 5: 1, 7: 1, 8: 0}, "TAB_COUNT telemetry - page load, recount event ignored");
     ok(BrowserUsageTelemetry._lastRecordTabCount == oldLastRecordTabCount, "TAB_COUNT telemetry - _lastRecordTabCount unchanged");
   }
 
   // Trigger a recount if _lastRecordTabCount has passed on page load
   BrowserUsageTelemetry._lastRecordTabCount = Date.now() - (MINIMUM_TAB_COUNT_INTERVAL_MS + 1000);
   {
     let oldLastRecordTabCount = BrowserUsageTelemetry._lastRecordTabCount;
     await BrowserTestUtils.loadURI(tab.linkedBrowser, "http://example.com/");
     await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
-    checkTabCountHistogram(tabCountHist.snapshot(), [0, 0, 1, 2, 1, 1, 0, 2], "TAB_COUNT telemetry - page load, recount event included");
+    checkTabCountHistogram(tabCountHist.snapshot(), {1: 0, 2: 1, 3: 2, 4: 1, 5: 1, 7: 2, 8: 0}, "TAB_COUNT telemetry - page load, recount event included");
     ok(BrowserUsageTelemetry._lastRecordTabCount != oldLastRecordTabCount, "TAB_COUNT telemetry - _lastRecordTabCount updated");
     ok(BrowserUsageTelemetry._lastRecordTabCount > Date.now() - MINIMUM_TAB_COUNT_INTERVAL_MS, "TAB_COUNT telemetry - _lastRecordTabCount invariant");
   }
 
   // Remove all the extra windows and tabs.
   for (let openTab of openedTabs) {
     BrowserTestUtils.removeTab(openTab);
   }
--- a/browser/modules/test/browser/browser_UsageTelemetry_searchbar.js
+++ b/browser/modules/test/browser/browser_UsageTelemetry_searchbar.js
@@ -4,22 +4,22 @@ const SCALAR_SEARCHBAR = "browser.engage
 
 ChromeUtils.defineModuleGetter(this, "URLBAR_SELECTED_RESULT_METHODS",
                                "resource:///modules/BrowserUsageTelemetry.jsm");
 
 ChromeUtils.import("resource://testing-common/CustomizableUITestUtils.jsm", this);
 let gCUITestUtils = new CustomizableUITestUtils(window);
 
 function checkHistogramResults(resultIndexes, expected, histogram) {
-  for (let i = 0; i < resultIndexes.counts.length; i++) {
+  for (let [i, val] of Object.entries(resultIndexes.values)) {
     if (i == expected) {
-      Assert.equal(resultIndexes.counts[i], 1,
+      Assert.equal(val, 1,
         `expected counts should match for ${histogram} index ${i}`);
     } else {
-      Assert.equal(resultIndexes.counts[i], 0,
+      Assert.equal(!!val, false,
         `unexpected counts should be zero for ${histogram} index ${i}`);
     }
   }
 }
 
 let searchInSearchbar = async function(inputText) {
   let win = window;
   await new Promise(r => waitForFocus(r, win));
--- a/browser/modules/test/browser/browser_UsageTelemetry_urlbar.js
+++ b/browser/modules/test/browser/browser_UsageTelemetry_urlbar.js
@@ -10,22 +10,22 @@ const ONEOFF_URLBAR_PREF = "browser.urlb
 
 ChromeUtils.defineModuleGetter(this, "URLBAR_SELECTED_RESULT_TYPES",
                                "resource:///modules/BrowserUsageTelemetry.jsm");
 
 ChromeUtils.defineModuleGetter(this, "URLBAR_SELECTED_RESULT_METHODS",
                                "resource:///modules/BrowserUsageTelemetry.jsm");
 
 function checkHistogramResults(resultIndexes, expected, histogram) {
-  for (let i = 0; i < resultIndexes.counts.length; i++) {
+  for (let [i, val] of Object.entries(resultIndexes.values)) {
     if (i == expected) {
-      Assert.equal(resultIndexes.counts[i], 1,
+      Assert.equal(val, 1,
         `expected counts should match for ${histogram} index ${i}`);
     } else {
-      Assert.equal(resultIndexes.counts[i], 0,
+      Assert.equal(!!val, false,
         `unexpected counts should be zero for ${histogram} index ${i}`);
     }
   }
 }
 
 let searchInAwesomebar = async function(inputText, win = window) {
   await new Promise(r => waitForFocus(r, win));
   // Write the search query in the urlbar.
--- a/devtools/client/framework/test/browser_toolbox_hosts_telemetry.js
+++ b/devtools/client/framework/test/browser_toolbox_hosts_telemetry.js
@@ -36,10 +36,10 @@ async function changeToolboxHost(toolbox
 }
 
 function checkResults() {
   // Check for:
   //   - 3 "bottom" entries.
   //   - 2 "left" entries.
   //   - 3 "right" entries.
   //   - 2 "window" entries.
-  checkTelemetry("DEVTOOLS_TOOLBOX_HOST", "", [3, 3, 2, 0, 2, 0, 0, 0, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_TOOLBOX_HOST", "", {0: 3, 1: 3, 2: 2, 4: 2, 5: 0}, "array");
 }
--- a/devtools/client/inspector/grids/test/browser_grids_number-of-css-grids-telemetry.js
+++ b/devtools/client/inspector/grids/test/browser_grids_number-of-css-grids-telemetry.js
@@ -39,11 +39,10 @@ add_task(async function() {
 
   checkResults();
 });
 
 function checkResults() {
   // Check for:
   //   - 1 CSS Grid Element
   checkTelemetry("DEVTOOLS_NUMBER_OF_CSS_GRIDS_IN_A_PAGE", "",
-    [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "array");
+    {0: 0, 1: 1, 2: 0}, "array");
 }
--- a/devtools/client/performance/test/browser_perf-telemetry-01.js
+++ b/devtools/client/performance/test/browser_perf-telemetry-01.js
@@ -34,19 +34,23 @@ add_task(async function() {
   checkResults();
 
   await teardownToolboxAndRemoveTab(panel);
 });
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_PERFTOOLS_")
   // here.
-  checkTelemetry("DEVTOOLS_PERFTOOLS_RECORDING_COUNT", "", [2, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_PERFTOOLS_RECORDING_COUNT", "", {0: 2, 1: 0}, "array");
   checkTelemetry("DEVTOOLS_PERFTOOLS_RECORDING_DURATION_MS", "", null, "hasentries");
   checkTelemetry(
-    "DEVTOOLS_PERFTOOLS_RECORDING_FEATURES_USED", "withMarkers", [0, 2, 0], "array");
+    "DEVTOOLS_PERFTOOLS_RECORDING_FEATURES_USED", "withMarkers", {0: 0, 1: 2, 2: 0},
+    "array");
   checkTelemetry(
-    "DEVTOOLS_PERFTOOLS_RECORDING_FEATURES_USED", "withMemory", [1, 1, 0], "array");
+    "DEVTOOLS_PERFTOOLS_RECORDING_FEATURES_USED", "withMemory", {0: 1, 1: 1, 2: 0},
+    "array");
   checkTelemetry(
-    "DEVTOOLS_PERFTOOLS_RECORDING_FEATURES_USED", "withAllocations", [2, 0, 0], "array");
+    "DEVTOOLS_PERFTOOLS_RECORDING_FEATURES_USED", "withAllocations", {0: 2, 1: 0},
+    "array");
   checkTelemetry(
-    "DEVTOOLS_PERFTOOLS_RECORDING_FEATURES_USED", "withTicks", [0, 2, 0], "array");
+    "DEVTOOLS_PERFTOOLS_RECORDING_FEATURES_USED", "withTicks", {0: 0, 1: 2, 2: 0},
+    "array");
 }
--- a/devtools/client/performance/test/browser_perf-telemetry-02.js
+++ b/devtools/client/performance/test/browser_perf-telemetry-02.js
@@ -39,11 +39,13 @@ add_task(async function() {
 
   checkResults();
   await teardownToolboxAndRemoveTab(panel);
 });
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_PERFTOOLS_")
   // here.
-  checkTelemetry("DEVTOOLS_PERFTOOLS_RECORDING_IMPORT_FLAG", "", [0, 1, 0], "array");
-  checkTelemetry("DEVTOOLS_PERFTOOLS_RECORDING_EXPORT_FLAG", "", [0, 1, 0], "array");
+  checkTelemetry("DEVTOOLS_PERFTOOLS_RECORDING_IMPORT_FLAG", "", {0: 0, 1: 1, 2: 0},
+    "array");
+  checkTelemetry("DEVTOOLS_PERFTOOLS_RECORDING_EXPORT_FLAG", "", {0: 0, 1: 1, 2: 0},
+    "array");
 }
--- a/devtools/client/performance/test/browser_perf-telemetry-04.js
+++ b/devtools/client/performance/test/browser_perf-telemetry-04.js
@@ -36,19 +36,22 @@ add_task(async function() {
 
   checkResults();
   await teardownToolboxAndRemoveTab(panel);
 });
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_PERFTOOLS_")
   // here.
-  checkTelemetry("DEVTOOLS_PERFTOOLS_CONSOLE_RECORDING_COUNT", "", [1, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_PERFTOOLS_CONSOLE_RECORDING_COUNT", "", {0: 1, 1: 0}, "array");
   checkTelemetry("DEVTOOLS_PERFTOOLS_RECORDING_DURATION_MS", "", null, "hasentries");
   checkTelemetry(
-    "DEVTOOLS_PERFTOOLS_RECORDING_FEATURES_USED", "withMarkers", [0, 1, 0], "array");
+    "DEVTOOLS_PERFTOOLS_RECORDING_FEATURES_USED", "withMarkers", {0: 0, 1: 1, 2: 0},
+    "array");
   checkTelemetry(
-    "DEVTOOLS_PERFTOOLS_RECORDING_FEATURES_USED", "withMemory", [1, 0, 0], "array");
+    "DEVTOOLS_PERFTOOLS_RECORDING_FEATURES_USED", "withMemory", {0: 1, 1: 0}, "array");
   checkTelemetry(
-    "DEVTOOLS_PERFTOOLS_RECORDING_FEATURES_USED", "withAllocations", [1, 0, 0], "array");
+    "DEVTOOLS_PERFTOOLS_RECORDING_FEATURES_USED", "withAllocations", {0: 1, 1: 0},
+    "array");
   checkTelemetry(
-    "DEVTOOLS_PERFTOOLS_RECORDING_FEATURES_USED", "withTicks", [0, 1, 0], "array");
+    "DEVTOOLS_PERFTOOLS_RECORDING_FEATURES_USED", "withTicks", {0: 0, 1: 1, 2: 0},
+    "array");
 }
--- a/devtools/client/shared/test/browser_telemetry_button_paintflashing.js
+++ b/devtools/client/shared/test/browser_telemetry_button_paintflashing.js
@@ -47,11 +47,11 @@ async function delayedClicks(toolbox, no
     info("Clicking button " + node.id);
     node.click();
   }
 }
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_PAINTFLASHING_")
   // here.
-  checkTelemetry("DEVTOOLS_PAINTFLASHING_OPENED_COUNT", "", [2, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_PAINTFLASHING_OPENED_COUNT", "", {0: 2, 1: 0}, "array");
   checkTelemetry("DEVTOOLS_PAINTFLASHING_TIME_ACTIVE_SECONDS", "", null, "hasentries");
 }
--- a/devtools/client/shared/test/browser_telemetry_button_responsive.js
+++ b/devtools/client/shared/test/browser_telemetry_button_responsive.js
@@ -79,11 +79,11 @@ var delayedClicks = async function(node,
     // See TOOL_DELAY for why we need setTimeout here
     await DevToolsUtils.waitForTime(TOOL_DELAY);
   }
 };
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_RESPONSIVE_")
   // here.
-  checkTelemetry("DEVTOOLS_RESPONSIVE_OPENED_COUNT", "", [2, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_RESPONSIVE_OPENED_COUNT", "", {0: 2, 1: 0}, "array");
   checkTelemetry("DEVTOOLS_RESPONSIVE_TIME_ACTIVE_SECONDS", "", null, "hasentries");
 }
--- a/devtools/client/shared/test/browser_telemetry_button_scratchpad.js
+++ b/devtools/client/shared/test/browser_telemetry_button_scratchpad.js
@@ -92,10 +92,10 @@ function delayedClicks(node, clicks) {
       }
     }, TOOL_DELAY);
   });
 }
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_SCRATCHPAD_")
   // here.
-  checkTelemetry("DEVTOOLS_SCRATCHPAD_WINDOW_OPENED_COUNT", "", [4, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_SCRATCHPAD_WINDOW_OPENED_COUNT", "", {0: 4, 1: 0}, "array");
 }
--- a/devtools/client/shared/test/browser_telemetry_misc.js
+++ b/devtools/client/shared/test/browser_telemetry_misc.js
@@ -15,16 +15,16 @@ add_task(async function() {
   checkResults();
 
   gBrowser.removeCurrentTab();
 });
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_")
   // here.
-  checkTelemetry("DEVTOOLS_TOOLBOX_OPENED_COUNT", "", [1, 0, 0], "array");
-  checkTelemetry("DEVTOOLS_INSPECTOR_OPENED_COUNT", "", [1, 0, 0], "array");
-  checkTelemetry("DEVTOOLS_RULEVIEW_OPENED_COUNT", "", [1, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_TOOLBOX_OPENED_COUNT", "", {0: 1, 1: 0}, "array");
+  checkTelemetry("DEVTOOLS_INSPECTOR_OPENED_COUNT", "", {0: 1, 1: 0}, "array");
+  checkTelemetry("DEVTOOLS_RULEVIEW_OPENED_COUNT", "", {0: 1, 1: 0}, "array");
   checkTelemetry("DEVTOOLS_TOOLBOX_TIME_ACTIVE_SECONDS", "", null, "hasentries");
   checkTelemetry("DEVTOOLS_INSPECTOR_TIME_ACTIVE_SECONDS", "", null, "hasentries");
   checkTelemetry("DEVTOOLS_RULEVIEW_TIME_ACTIVE_SECONDS", "", null, "hasentries");
   checkTelemetry("DEVTOOLS_TOOLBOX_HOST", "", null, "hasentries");
 }
--- a/devtools/client/shared/test/browser_telemetry_sidebar.js
+++ b/devtools/client/shared/test/browser_telemetry_sidebar.js
@@ -149,21 +149,21 @@ function testSidebar(toolbox) {
       }
     }, TOOL_DELAY);
   });
 }
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_")
   // here.
-  checkTelemetry("DEVTOOLS_INSPECTOR_OPENED_COUNT", "", [1, 0, 0], "array");
-  checkTelemetry("DEVTOOLS_RULEVIEW_OPENED_COUNT", "", [1, 0, 0], "array");
-  checkTelemetry("DEVTOOLS_COMPUTEDVIEW_OPENED_COUNT", "", [2, 0, 0], "array");
-  checkTelemetry("DEVTOOLS_LAYOUTVIEW_OPENED_COUNT", "", [3, 0, 0], "array");
-  checkTelemetry("DEVTOOLS_FONTINSPECTOR_OPENED_COUNT", "", [2, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_INSPECTOR_OPENED_COUNT", "", {0: 1, 1: 0}, "array");
+  checkTelemetry("DEVTOOLS_RULEVIEW_OPENED_COUNT", "", {0: 1, 1: 0}, "array");
+  checkTelemetry("DEVTOOLS_COMPUTEDVIEW_OPENED_COUNT", "", {0: 2, 1: 0}, "array");
+  checkTelemetry("DEVTOOLS_LAYOUTVIEW_OPENED_COUNT", "", {0: 3, 1: 0}, "array");
+  checkTelemetry("DEVTOOLS_FONTINSPECTOR_OPENED_COUNT", "", {0: 2, 1: 0}, "array");
   checkTelemetry("DEVTOOLS_COMPUTEDVIEW_TIME_ACTIVE_SECONDS", "", null, "hasentries");
   checkTelemetry("DEVTOOLS_LAYOUTVIEW_TIME_ACTIVE_SECONDS", "", null, "hasentries");
   checkTelemetry("DEVTOOLS_FONTINSPECTOR_TIME_ACTIVE_SECONDS", "", null, "hasentries");
 }
 
 function checkEventTelemetry() {
   const snapshot = Services.telemetry.snapshotEvents(OPTOUT, true);
   const events = snapshot.parent.filter(event => event[1] === "devtools.main" &&
--- a/devtools/client/shared/test/browser_telemetry_toolbox.js
+++ b/devtools/client/shared/test/browser_telemetry_toolbox.js
@@ -18,12 +18,12 @@ add_task(async function() {
   checkResults();
 
   gBrowser.removeCurrentTab();
 });
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_TOOLBOX_")
   // here.
-  checkTelemetry("DEVTOOLS_TOOLBOX_OPENED_COUNT", "", [3, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_TOOLBOX_OPENED_COUNT", "", {0: 3, 1: 0}, "array");
   checkTelemetry("DEVTOOLS_TOOLBOX_TIME_ACTIVE_SECONDS", "", null, "hasentries");
   checkTelemetry("DEVTOOLS_TOOLBOX_HOST", "", null, "hasentries");
 }
--- a/devtools/client/shared/test/browser_telemetry_toolboxtabs_canvasdebugger.js
+++ b/devtools/client/shared/test/browser_telemetry_toolboxtabs_canvasdebugger.js
@@ -25,11 +25,11 @@ add_task(async function() {
 
   info("De-activate the canvasdebugger");
   Services.prefs.setBoolPref("devtools.canvasdebugger.enabled", originalPref);
 });
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_CANVASDEBUGGER")
   // here.
-  checkTelemetry("DEVTOOLS_CANVASDEBUGGER_OPENED_COUNT", "", [2, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_CANVASDEBUGGER_OPENED_COUNT", "", {0: 2, 1: 0}, "array");
   checkTelemetry("DEVTOOLS_CANVASDEBUGGER_TIME_ACTIVE_SECONDS", "", null, "hasentries");
 }
--- a/devtools/client/shared/test/browser_telemetry_toolboxtabs_inspector.js
+++ b/devtools/client/shared/test/browser_telemetry_toolboxtabs_inspector.js
@@ -18,11 +18,11 @@ add_task(async function() {
   checkResults();
 
   gBrowser.removeCurrentTab();
 });
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_INSPECTOR_")
   // here.
-  checkTelemetry("DEVTOOLS_INSPECTOR_OPENED_COUNT", "", [2, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_INSPECTOR_OPENED_COUNT", "", {0: 2, 1: 0}, "array");
   checkTelemetry("DEVTOOLS_INSPECTOR_TIME_ACTIVE_SECONDS", "", null, "hasentries");
 }
--- a/devtools/client/shared/test/browser_telemetry_toolboxtabs_jsdebugger.js
+++ b/devtools/client/shared/test/browser_telemetry_toolboxtabs_jsdebugger.js
@@ -18,11 +18,11 @@ add_task(async function() {
   checkResults();
 
   gBrowser.removeCurrentTab();
 });
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_JSDEBUGGER_")
   // here.
-  checkTelemetry("DEVTOOLS_JSDEBUGGER_OPENED_COUNT", "", [2, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_JSDEBUGGER_OPENED_COUNT", "", {0: 2, 1: 0}, "array");
   checkTelemetry("DEVTOOLS_JSDEBUGGER_TIME_ACTIVE_SECONDS", "", null, "hasentries");
 }
--- a/devtools/client/shared/test/browser_telemetry_toolboxtabs_jsprofiler.js
+++ b/devtools/client/shared/test/browser_telemetry_toolboxtabs_jsprofiler.js
@@ -18,11 +18,11 @@ add_task(async function() {
   checkResults();
 
   gBrowser.removeCurrentTab();
 });
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_JSPROFILER")
   // here.
-  checkTelemetry("DEVTOOLS_JSPROFILER_OPENED_COUNT", "", [2, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_JSPROFILER_OPENED_COUNT", "", {0: 2, 1: 0}, "array");
   checkTelemetry("DEVTOOLS_JSPROFILER_TIME_ACTIVE_SECONDS", "", null, "hasentries");
 }
--- a/devtools/client/shared/test/browser_telemetry_toolboxtabs_netmonitor.js
+++ b/devtools/client/shared/test/browser_telemetry_toolboxtabs_netmonitor.js
@@ -18,11 +18,11 @@ add_task(async function() {
   checkResults();
 
   gBrowser.removeCurrentTab();
 });
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_NETMONITOR_")
   // here.
-  checkTelemetry("DEVTOOLS_NETMONITOR_OPENED_COUNT", "", [2, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_NETMONITOR_OPENED_COUNT", "", {0: 2, 1: 0}, "array");
   checkTelemetry("DEVTOOLS_NETMONITOR_TIME_ACTIVE_SECONDS", "", null, "hasentries");
 }
--- a/devtools/client/shared/test/browser_telemetry_toolboxtabs_options.js
+++ b/devtools/client/shared/test/browser_telemetry_toolboxtabs_options.js
@@ -18,11 +18,11 @@ add_task(async function() {
   checkResults();
 
   gBrowser.removeCurrentTab();
 });
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_OPTIONS_")
   // here.
-  checkTelemetry("DEVTOOLS_OPTIONS_OPENED_COUNT", "", [2, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_OPTIONS_OPENED_COUNT", "", {0: 2, 1: 0}, "array");
   checkTelemetry("DEVTOOLS_OPTIONS_TIME_ACTIVE_SECONDS", "", null, "hasentries");
 }
--- a/devtools/client/shared/test/browser_telemetry_toolboxtabs_shadereditor.js
+++ b/devtools/client/shared/test/browser_telemetry_toolboxtabs_shadereditor.js
@@ -26,11 +26,11 @@ add_task(async function() {
 
   info("De-activate the sharer editor");
   Services.prefs.setBoolPref(TOOL_PREF, originalPref);
 });
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_SHADEREDITOR_")
   // here.
-  checkTelemetry("DEVTOOLS_SHADEREDITOR_OPENED_COUNT", "", [2, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_SHADEREDITOR_OPENED_COUNT", "", {0: 2, 1: 0}, "array");
   checkTelemetry("DEVTOOLS_SHADEREDITOR_TIME_ACTIVE_SECONDS", "", null, "hasentries");
 }
--- a/devtools/client/shared/test/browser_telemetry_toolboxtabs_storage.js
+++ b/devtools/client/shared/test/browser_telemetry_toolboxtabs_storage.js
@@ -18,11 +18,11 @@ add_task(async function() {
   checkResults();
 
   gBrowser.removeCurrentTab();
 });
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_STORAGE_")
   // here.
-  checkTelemetry("DEVTOOLS_STORAGE_OPENED_COUNT", "", [2, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_STORAGE_OPENED_COUNT", "", {0: 2, 1: 0}, "array");
   checkTelemetry("DEVTOOLS_STORAGE_TIME_ACTIVE_SECONDS", "", null, "hasentries");
 }
--- a/devtools/client/shared/test/browser_telemetry_toolboxtabs_styleeditor.js
+++ b/devtools/client/shared/test/browser_telemetry_toolboxtabs_styleeditor.js
@@ -18,11 +18,11 @@ add_task(async function() {
   checkResults();
 
   gBrowser.removeCurrentTab();
 });
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_STYLEEDITOR_")
   // here.
-  checkTelemetry("DEVTOOLS_STYLEEDITOR_OPENED_COUNT", "", [2, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_STYLEEDITOR_OPENED_COUNT", "", {0: 2, 1: 0}, "array");
   checkTelemetry("DEVTOOLS_STYLEEDITOR_TIME_ACTIVE_SECONDS", "", null, "hasentries");
 }
--- a/devtools/client/shared/test/browser_telemetry_toolboxtabs_webaudioeditor.js
+++ b/devtools/client/shared/test/browser_telemetry_toolboxtabs_webaudioeditor.js
@@ -25,11 +25,11 @@ add_task(async function() {
 
   info("De-activating the webaudioeditor");
   Services.prefs.setBoolPref("devtools.webaudioeditor.enabled", originalPref);
 });
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_WEBAUDIOEDITOR")
   // here.
-  checkTelemetry("DEVTOOLS_WEBAUDIOEDITOR_OPENED_COUNT", "", [2, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_WEBAUDIOEDITOR_OPENED_COUNT", "", {0: 2, 1: 0}, "array");
   checkTelemetry("DEVTOOLS_WEBAUDIOEDITOR_TIME_ACTIVE_SECONDS", "", null, "hasentries");
 }
--- a/devtools/client/shared/test/browser_telemetry_toolboxtabs_webconsole.js
+++ b/devtools/client/shared/test/browser_telemetry_toolboxtabs_webconsole.js
@@ -18,11 +18,11 @@ add_task(async function() {
   checkResults();
 
   gBrowser.removeCurrentTab();
 });
 
 function checkResults() {
   // For help generating these tests use generateTelemetryTests("DEVTOOLS_WEBCONSOLE_")
   // here.
-  checkTelemetry("DEVTOOLS_WEBCONSOLE_OPENED_COUNT", "", [2, 0, 0], "array");
+  checkTelemetry("DEVTOOLS_WEBCONSOLE_OPENED_COUNT", "", {0: 2, 1: 0}, "array");
   checkTelemetry("DEVTOOLS_WEBCONSOLE_TIME_ACTIVE_SECONDS", "", null, "hasentries");
 }
--- a/devtools/client/shared/test/telemetry-test-helpers.js
+++ b/devtools/client/shared/test/telemetry-test-helpers.js
@@ -98,33 +98,33 @@ class TelemetryHelpers {
 
     if (checkType === "array" || checkType === "hasentries") {
       if (key) {
         const keyedHistogram =
           Services.telemetry.getKeyedHistogramById(histId).snapshot();
         const result = keyedHistogram[key];
 
         if (result) {
-          actual = result.counts;
+          actual = result.values;
         } else {
           ok(false, `${histId}[${key}] exists`);
           return;
         }
       } else {
-        actual = Services.telemetry.getHistogramById(histId).snapshot().counts;
+        actual = Services.telemetry.getHistogramById(histId).snapshot().values;
       }
     }
 
     switch (checkType) {
       case "array":
         msg = key ? `${histId}["${key}"] correct.` : `${histId} correct.`;
         is(JSON.stringify(actual), JSON.stringify(expected), msg);
         break;
       case "hasentries":
-        const hasEntry = actual.some(num => num > 0);
+        const hasEntry = Object.values(actual).some(num => num > 0);
         if (key) {
           ok(hasEntry, `${histId}["${key}"] has at least one entry.`);
         } else {
           ok(hasEntry, `${histId} has at least one entry.`);
         }
         break;
       case "scalar":
         const scalars =
--- a/dom/webauthn/tests/browser/browser_webauthn_telemetry.js
+++ b/dom/webauthn/tests/browser/browser_webauthn_telemetry.js
@@ -25,20 +25,17 @@ function cleanupTelemetry() {
   Services.telemetry.getHistogramById("WEBAUTHN_CREATE_CREDENTIAL_MS").clear();
   Services.telemetry.getHistogramById("WEBAUTHN_GET_ASSERTION_MS").clear();
 }
 
 function validateHistogramEntryCount(aHistogramName, aExpectedCount) {
   let hist = Services.telemetry.getHistogramById(aHistogramName);
   let resultIndexes = hist.snapshot();
 
-  let entriesSeen = 0;
-  for (let i = 0; i < resultIndexes.counts.length; i++) {
-    entriesSeen += resultIndexes.counts[i];
-  }
+  let entriesSeen = Object.values(resultIndexes.values).reduce((a,b) => a + b, 0);
 
   is(entriesSeen, aExpectedCount, "Expecting " + aExpectedCount + " histogram entries in " +
      aHistogramName);
 }
 
 function promiseMakeCredentialRequest(tab) {
   return ContentTask.spawn(tab.linkedBrowser, null, () => {
     const cose_alg_ECDSA_w_SHA256 = -7;