Bug 1521511 - Add telemetry for additional runtime actions;r=daisuke,janerik
authorJulian Descottes <jdescottes@mozilla.com>
Fri, 22 Feb 2019 17:12:18 +0000
changeset 518939 623d172979d9e285feda9857abe444133d9b6096
parent 518938 8f991ed45f905ec8a7d576665cd7c1a7c0ec6fe7
child 518940 97ff6454af343ca6f353812d8e26084a6a78340f
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdaisuke, janerik
bugs1521511
milestone67.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 1521511 - Add telemetry for additional runtime actions;r=daisuke,janerik Depends on D19529 Waiting for product feedback before asking for review from janerik Differential Revision: https://phabricator.services.mozilla.com/D19686
devtools/client/aboutdebugging-new/src/middleware/event-recording.js
devtools/client/aboutdebugging-new/test/browser/browser.ini
devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_profiler_dialog.js
devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_telemetry_runtime_actions.js
devtools/client/aboutdebugging-new/test/browser/head.js
toolkit/components/telemetry/Events.yaml
--- a/devtools/client/aboutdebugging-new/src/middleware/event-recording.js
+++ b/devtools/client/aboutdebugging-new/src/middleware/event-recording.js
@@ -10,22 +10,25 @@ loader.lazyGetter(this, "telemetry", () 
 loader.lazyGetter(this, "sessionId", () => parseInt(telemetry.msSinceProcessStart(), 10));
 
 const {
   CONNECT_RUNTIME_SUCCESS,
   DISCONNECT_RUNTIME_SUCCESS,
   REMOTE_RUNTIMES_UPDATED,
   RUNTIMES,
   SELECT_PAGE_SUCCESS,
+  SHOW_PROFILER_DIALOG,
   TELEMETRY_RECORD,
+  UPDATE_CONNECTION_PROMPT_SETTING_SUCCESS,
 } = require("../constants");
 
 const {
   findRuntimeById,
   getAllRuntimes,
+  getCurrentRuntime,
 } = require("../modules/runtimes-state-helper");
 
 function recordEvent(method, details) {
   // Add the session id to the event details.
   const eventDetails = Object.assign({}, details, { "session_id": sessionId });
   telemetry.recordEvent(method, "aboutdebugging", null, eventDetails);
 }
 
@@ -35,16 +38,21 @@ const telemetryRuntimeIds = new Map();
 function getTelemetryRuntimeId(id) {
   if (!telemetryRuntimeIds.has(id)) {
     const randomId = (Math.random() * 100000) | 0;
     telemetryRuntimeIds.set(id, "runtime-" + randomId);
   }
   return telemetryRuntimeIds.get(id);
 }
 
+function getCurrentRuntimeIdForTelemetry(store) {
+  const id = getCurrentRuntime(store.getState().runtimes).id;
+  return getTelemetryRuntimeId(id);
+}
+
 function getRuntimeEventExtras(runtime) {
   const { extra, runtimeDetails } = runtime;
 
   // deviceName can be undefined for non-usb devices, but we should not log "undefined".
   const deviceName = extra && extra.deviceName || "";
   const runtimeShortName = runtime.type === RUNTIMES.USB ? runtime.name : "";
   const runtimeName = runtimeDetails && runtimeDetails.info.name || "";
   return {
@@ -140,23 +148,34 @@ function eventRecordingMiddleware(store)
         onDisconnectRuntimeSuccess(action, store);
         break;
       case REMOTE_RUNTIMES_UPDATED:
         onRemoteRuntimesUpdated(action, store);
         break;
       case SELECT_PAGE_SUCCESS:
         recordEvent("select_page", { "page_type": action.page });
         break;
+      case SHOW_PROFILER_DIALOG:
+        recordEvent("show_profiler", {
+          "runtime_id": getCurrentRuntimeIdForTelemetry(store),
+        });
+        break;
       case TELEMETRY_RECORD:
         const { method, details } = action;
         if (method) {
           recordEvent(method, details);
         } else {
           console.error(`[RECORD EVENT FAILED] ${action.type}: no "method" property`);
         }
         break;
+      case UPDATE_CONNECTION_PROMPT_SETTING_SUCCESS:
+        recordEvent("update_conn_prompt", {
+          "prompt_enabled": `${action.connectionPromptEnabled}`,
+          "runtime_id": getCurrentRuntimeIdForTelemetry(store),
+        });
+        break;
     }
 
     return next(action);
   };
 }
 
 module.exports = eventRecordingMiddleware;
--- a/devtools/client/aboutdebugging-new/test/browser/browser.ini
+++ b/devtools/client/aboutdebugging-new/test/browser/browser.ini
@@ -92,15 +92,16 @@ skip-if = (os == 'linux' && bits == 32) 
 [browser_aboutdebugging_sidebar_usb_unknown_runtime.js]
 [browser_aboutdebugging_stop_adb.js]
 skip-if = (os == 'linux' && bits == 32) # ADB start() fails on linux 32, see Bug 1499638
 [browser_aboutdebugging_system_addons.js]
 [browser_aboutdebugging_tab_favicons.js]
 [browser_aboutdebugging_telemetry_basic.js]
 [browser_aboutdebugging_telemetry_inspect.js]
 [browser_aboutdebugging_telemetry_navigate.js]
+[browser_aboutdebugging_telemetry_runtime_actions.js]
 [browser_aboutdebugging_telemetry_runtime_updates.js]
 [browser_aboutdebugging_telemetry_runtime_updates_multi.js]
 [browser_aboutdebugging_telemetry_runtime_updates_network.js]
 [browser_aboutdebugging_thisfirefox.js]
 [browser_aboutdebugging_thisfirefox_runtime_info.js]
 [browser_aboutdebugging_thisfirefox_worker_inspection.js]
 [browser_aboutdebugging_workers_remote_runtime.js]
--- a/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_profiler_dialog.js
+++ b/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_profiler_dialog.js
@@ -60,21 +60,8 @@ function assertDialogVisible(doc) {
   ok(doc.querySelector(".js-profiler-dialog"), "Dialog is displayed");
   ok(doc.querySelector(".js-profiler-dialog-mask"), "Dialog mask is displayed");
 }
 
 function assertDialogHidden(doc) {
   ok(!document.querySelector(".js-profiler-dialog"), "Dialog is removed");
   ok(!document.querySelector(".js-profiler-dialog-mask"), "Dialog mask is removed");
 }
-
-function openProfilerDialog(client, doc) {
-  const onProfilerLoaded = new Promise(r => {
-    client.loadPerformanceProfiler = r;
-  });
-
-  info("Click on the Profile Runtime button");
-  const profileButton = doc.querySelector(".js-profile-runtime-button");
-  profileButton.click();
-
-  info("Wait for the loadPerformanceProfiler callback to be executed on client-wrapper");
-  return onProfilerLoaded;
-}
new file mode 100644
--- /dev/null
+++ b/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_telemetry_runtime_actions.js
@@ -0,0 +1,77 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/* import-globals-from helper-telemetry.js */
+Services.scriptloader.loadSubScript(CHROME_URL_ROOT + "helper-telemetry.js", this);
+
+const RUNTIME_ID = "test-runtime-id";
+const RUNTIME_NAME = "Test Runtime";
+const RUNTIME_DEVICE_NAME = "Test Device";
+
+/**
+ * Test that runtime specific actions are logged as telemetry events with the expected
+ * runtime id and action type.
+ */
+add_task(async function testUsbRuntimeUpdates() {
+  // enable USB devices mocks
+  const mocks = new Mocks();
+  setupTelemetryTest();
+
+  const { tab, document } = await openAboutDebugging();
+
+  const sessionId = getOpenEventSessionId();
+  ok(!isNaN(sessionId), "Open event has a valid session id");
+
+  const usbClient = mocks.createUSBRuntime(RUNTIME_ID, {
+    deviceName: RUNTIME_DEVICE_NAME,
+    name: RUNTIME_NAME,
+    shortName: RUNTIME_NAME,
+  });
+  mocks.emitUSBUpdate();
+
+  info("Wait for the runtime to appear in the sidebar");
+  await waitUntil(() => findSidebarItemByText(RUNTIME_NAME, document));
+  await connectToRuntime(RUNTIME_DEVICE_NAME, document);
+  await selectRuntime(RUNTIME_DEVICE_NAME, RUNTIME_NAME, document);
+
+  info("Read telemetry events to flush unrelated events");
+  const evts = readAboutDebuggingEvents();
+  const runtimeAddedEvent = evts.filter(e => e.method === "runtime_added")[0];
+  const telemetryRuntimeId = runtimeAddedEvent.extras.runtime_id;
+
+  info("Click on the toggle button and wait until the text is updated");
+  const promptButton = document.querySelector(".js-connection-prompt-toggle-button");
+  promptButton.click();
+  await waitUntil(() => promptButton.textContent.includes("Enable"));
+
+  checkTelemetryEvents([{
+    method: "update_conn_prompt",
+    extras: { "prompt_enabled": "false", "runtime_id": telemetryRuntimeId },
+  }], sessionId);
+
+  info("Click on the toggle button again and check we log the correct value");
+  promptButton.click();
+  await waitUntil(() => promptButton.textContent.includes("Disable"));
+
+  checkTelemetryEvents([{
+    method: "update_conn_prompt",
+    extras: { "prompt_enabled": "true", "runtime_id": telemetryRuntimeId },
+  }], sessionId);
+
+  info("Open the profiler dialog");
+  await openProfilerDialog(usbClient, document);
+
+  checkTelemetryEvents([{
+    method: "show_profiler",
+    extras: { "runtime_id": telemetryRuntimeId },
+  }], sessionId);
+
+  info("Remove runtime");
+  mocks.removeRuntime(RUNTIME_ID);
+  mocks.emitUSBUpdate();
+  await waitUntil(() => !findSidebarItemByText(RUNTIME_NAME, document));
+
+  await removeTab(tab);
+});
--- a/devtools/client/aboutdebugging-new/test/browser/head.js
+++ b/devtools/client/aboutdebugging-new/test/browser/head.js
@@ -262,8 +262,25 @@ async function selectRuntime(deviceName,
     const runtimeInfo = document.querySelector(".js-runtime-info");
     return runtimeInfo && runtimeInfo.textContent.includes(name);
   });
 }
 
 function getToolbox(win) {
   return gDevTools.getToolboxes().find(toolbox => toolbox.win === win);
 }
+
+/**
+ * Open the performance profiler dialog. Assumes the client is a mocked remote runtime
+ * client.
+ */
+async function openProfilerDialog(client, doc) {
+  const onProfilerLoaded = new Promise(r => {
+    client.loadPerformanceProfiler = r;
+  });
+
+  info("Click on the Profile Runtime button");
+  const profileButton = doc.querySelector(".js-profile-runtime-button");
+  profileButton.click();
+
+  info("Wait for the loadPerformanceProfiler callback to be executed on client-wrapper");
+  return onProfilerLoaded;
+}
--- a/toolkit/components/telemetry/Events.yaml
+++ b/toolkit/components/telemetry/Events.yaml
@@ -791,16 +791,27 @@ devtools.main:
     notification_emails: ["dev-developer-tools@lists.mozilla.org", "hkirschner@mozilla.com"]
     record_in_processes: ["main"]
     description: User navigates to a new page of an application such as about:debugging
     release_channel_collection: opt-out
     expiry_version: never
     extra_keys:
       page_type: Type of page the user navigates to (this-firefox, connect, runtime)
       session_id: The start time of the session in milliseconds since epoch (Unix Timestamp) e.g. 1396381378123.
+  show_profiler:
+    objects: ["aboutdebugging"]
+    bug_numbers: [1521511]
+    notification_emails: ["dev-developer-tools@lists.mozilla.org", "hkirschner@mozilla.com"]
+    record_in_processes: ["main"]
+    description: User has clicked on the "Open Profiler" button in a runtime page of about:debugging
+    release_channel_collection: opt-out
+    expiry_version: never
+    extra_keys:
+      runtime_id: Random id generated to track events related to a single runtime
+      session_id: The start time of the session in milliseconds since epoch (Unix Timestamp) e.g. 1396381378123.
   sidepanel_changed:
     objects: ["inspector", "netmonitor"]
     bug_numbers: [1463083, 1463169]
     notification_emails: ["dev-developer-tools@lists.mozilla.org", "hkirschner@mozilla.com"]
     record_in_processes: ["main"]
     description: User has switched sidepanel tabs.
     release_channel_collection: opt-out
     expiry_version: never
@@ -827,16 +838,28 @@ devtools.main:
     record_in_processes: ["main"]
     description: The amount of time a tool was opened for.
     release_channel_collection: opt-out
     expiry_version: never
     extra_keys:
       time_open: Time open.
       os: The OS name and version e.g. "Linux 4.4.0-1014-aws", "Darwin 14.5.0", "Windows_NT 6.1.7601" or "Windows_NT 10.0.15063." This can be used to make sense of data when a feature is only available from a particular operating system build number.
       session_id: The start time of the session in milliseconds since epoch (Unix Timestamp) e.g. 1396381378123.
+  update_conn_prompt:
+    objects: ["aboutdebugging"]
+    bug_numbers: [1521511]
+    notification_emails: ["dev-developer-tools@lists.mozilla.org", "hkirschner@mozilla.com"]
+    record_in_processes: ["main"]
+    description: User has clicked on the "Enable/Disable connection prompt" button in a runtime page of about:debugging
+    release_channel_collection: opt-out
+    expiry_version: never
+    extra_keys:
+      prompt_enabled: True if the user enables the prompt, false otherwise.
+      runtime_id: Random id generated to track events related to a single runtime
+      session_id: The start time of the session in milliseconds since epoch (Unix Timestamp) e.g. 1396381378123.
 
 security.ui.certerror:
   load:
     objects: ["aboutcerterror"]
     bug_numbers:
       - 1484255
       - 1505310
     description: >