Bug 1451734 - Track application panel events with EventTelemetry
Events tracked here:
- service worker debug (with duration)
- service worker start
- service worker unregister
- click on aboutdebugging link at bottom of sw list
- click on any help link
MozReview-Commit-ID: J2RYy6iHXw9
--- a/devtools/client/application/initializer.js
+++ b/devtools/client/application/initializer.js
@@ -12,16 +12,17 @@ const require = BrowserLoader({
const { createFactory } = require("devtools/client/shared/vendor/react");
const { render, unmountComponentAtNode } = require("devtools/client/shared/vendor/react-dom");
const Provider = createFactory(require("devtools/client/shared/vendor/react-redux").Provider);
const { bindActionCreators } = require("devtools/client/shared/vendor/redux");
const { configureStore } = require("./src/create-store");
const actions = require("./src/actions/index");
+const Telemetry = require("devtools/client/shared/telemetry");
const App = createFactory(require("./src/components/App"));
/**
* Global Application object in this panel. This object is expected by panel.js and is
* called to start the UI for the panel.
*/
window.Application = {
@@ -31,17 +32,23 @@ window.Application = {
this.mount = document.querySelector("#mount");
this.toolbox = toolbox;
this.client = toolbox.target.client;
this.store = configureStore();
this.actions = bindActionCreators(actions, this.store.dispatch);
+ let telemetry = new Telemetry();
+
const serviceContainer = {
+ recordEvent(action, extras) {
+ telemetry.recordEvent("devtools.main", action, "application", null, extras);
+ },
+
openWebLink(url) {
let win = toolbox.doc.defaultView.top;
win.openWebLinkIn(url, "tab", { relatedToCurrent: true });
},
openTrustedLink(url) {
let win = toolbox.doc.defaultView.top;
win.openTrustedLinkIn(url, "tab", { relatedToCurrent: true });
--- a/devtools/client/application/src/components/Worker.js
+++ b/devtools/client/application/src/components/Worker.js
@@ -4,16 +4,17 @@
"use strict";
const { Component } = require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { a, br, button, dd, dl, dt, header, li, section, span, time } =
require("devtools/client/shared/vendor/react-dom-factories");
const Services = require("Services");
+
const { getUnicodeUrl, getUnicodeUrlPath } = require("devtools/client/shared/unicode-url");
loader.lazyRequireGetter(this, "DebuggerClient",
"devtools/shared/client/debugger-client", true);
loader.lazyRequireGetter(this, "gDevToolsBrowser",
"devtools/client/framework/devtools-browser", true);
const Strings = Services.strings.createBundle(
@@ -25,16 +26,17 @@ const Strings = Services.strings.createB
* the worker as well as action links and buttons to interact with the worker (e.g. debug,
* unregister, update etc...).
*/
class Worker extends Component {
static get propTypes() {
return {
client: PropTypes.instanceOf(DebuggerClient).isRequired,
debugDisabled: PropTypes.bool,
+ serviceContainer: PropTypes.object.isRequired,
worker: PropTypes.shape({
active: PropTypes.bool,
name: PropTypes.string.isRequired,
scope: PropTypes.string.isRequired,
// registrationActor can be missing in e10s.
registrationActor: PropTypes.string,
workerActor: PropTypes.string
}).isRequired
@@ -44,45 +46,55 @@ class Worker extends Component {
constructor(props) {
super(props);
this.debug = this.debug.bind(this);
this.start = this.start.bind(this);
this.unregister = this.unregister.bind(this);
}
- debug() {
+ async debug() {
if (!this.isRunning()) {
console.log("Service workers cannot be debugged if they are not running");
return;
}
let { client, worker } = this.props;
- gDevToolsBrowser.openWorkerToolbox(client, worker.workerActor);
+
+ const start = performance.now();
+ const toolbox = await gDevToolsBrowser.openWorkerToolbox(client, worker.workerActor);
+ toolbox.once("destroy", () => {
+ const duration = performance.now() - start;
+ this.props.serviceContainer.recordEvent("debug_serviceworker", { duration });
+ });
}
start() {
if (!this.isActive() || this.isRunning()) {
console.log("Running or inactive service workers cannot be started");
return;
}
let { client, worker } = this.props;
client.request({
to: worker.registrationActor,
type: "start"
});
+
+ this.props.serviceContainer.recordEvent("start_serviceworker", {});
}
unregister() {
let { client, worker } = this.props;
client.request({
to: worker.registrationActor,
type: "unregister"
});
+
+ this.props.serviceContainer.recordEvent("unregister_serviceworker", {});
}
isRunning() {
// We know the worker is running if it has a worker actor.
return !!this.props.worker.workerActor;
}
isActive() {
--- a/devtools/client/application/src/components/WorkerList.js
+++ b/devtools/client/application/src/components/WorkerList.js
@@ -18,34 +18,41 @@ class WorkerList extends Component {
static get propTypes() {
return {
client: PropTypes.object.isRequired,
workers: PropTypes.object.isRequired,
serviceContainer: PropTypes.object.isRequired,
};
}
+ openAboutDebugging() {
+ this.props.serviceContainer.openTrustedLink("about:debugging#workers");
+ this.props.serviceContainer.recordEvent("open_aboutdebugging", {});
+ }
+
render() {
- const { workers, client, serviceContainer } = this.props;
- const { openTrustedLink } = serviceContainer;
+ const { client, serviceContainer, workers } = this.props;
return [
article({ className: "workers-container" },
h1({}, "Service Workers"),
ul({},
workers.map(worker => Worker({
client,
debugDisabled: false,
+ serviceContainer,
worker,
})))
),
footer({ className: "aboutdebugging-plug" },
"See about:debugging for Service Workers from other domains",
- a({ className: "aboutdebugging-plug__link",
- onClick: () => openTrustedLink("about:debugging#workers") },
+ a({
+ className: "aboutdebugging-plug__link",
+ onClick: () => this.openAboutDebugging()
+ },
"Open about:debugging"
)
)
];
}
}
// Exports
--- a/devtools/client/application/src/components/WorkerListEmpty.js
+++ b/devtools/client/application/src/components/WorkerListEmpty.js
@@ -17,29 +17,37 @@ const DOC_URL = "https://developer.mozil
class WorkerListEmpty extends Component {
static get propTypes() {
return {
serviceContainer: PropTypes.object.isRequired,
};
}
switchToConsole() {
- this.props.serviceContainer.selectTool("webconsole");
+ const { recordEvent, selectTool } = this.props.serviceContainer;
+ selectTool("webconsole");
+ recordEvent("open_help_link", { helpLink: "webconsole" });
}
switchToDebugger() {
- this.props.serviceContainer.selectTool("jsdebugger");
+ const { recordEvent, selectTool } = this.props.serviceContainer;
+ selectTool("jsdebugger");
+ recordEvent("open_help_link", { helpLink: "jsdebugger" });
}
openAboutDebugging() {
- this.props.serviceContainer.openTrustedLink("about:debugging#workers");
+ const { recordEvent, openTrustedLink } = this.props.serviceContainer;
+ openTrustedLink("about:debugging#workers");
+ recordEvent("open_help_link", { helpLink: "about:debugging#workers" });
}
openDocumentation() {
- this.props.serviceContainer.openWebLink(DOC_URL);
+ const { recordEvent, openTrustedLink } = this.props.serviceContainer;
+ openTrustedLink(DOC_URL);
+ recordEvent("open_help_link", { helpLink: "mdn (Using_Service_Workers)" });
}
render() {
return article(
{ className: "worker-list-empty" },
h1(
{ className: "worker-list-empty__title" },
"You need to register a Service Worker to inspect it here.",
--- a/devtools/client/framework/devtools-browser.js
+++ b/devtools/client/framework/devtools-browser.js
@@ -371,23 +371,26 @@ var gDevToolsBrowser = exports.gDevTools
* Open a window-hosted toolbox to debug the worker associated to the provided
* worker actor.
*
* @param {DebuggerClient} client
* @param {Object} workerActor
* worker actor form to debug
*/
openWorkerToolbox(client, workerActor) {
- client.attachWorker(workerActor, (response, workerClient) => {
- let workerTarget = TargetFactory.forWorker(workerClient);
- gDevTools.showToolbox(workerTarget, null, Toolbox.HostType.WINDOW)
- .then(toolbox => {
- toolbox.once("destroy", () => workerClient.detach());
- });
- });
+ return new Promise(resolve => {
+ client.attachWorker(workerActor, (response, workerClient) => {
+ let workerTarget = TargetFactory.forWorker(workerClient);
+ gDevTools.showToolbox(workerTarget, null, Toolbox.HostType.WINDOW)
+ .then(toolbox => {
+ toolbox.once("destroy", () => workerClient.detach());
+ resolve(toolbox);
+ });
+ });
+ })
},
/**
* Install WebIDE widget
*/
// Used by itself
installWebIDEWidget() {
if (this.isWebIDEWidgetInstalled()) {
--- a/toolkit/components/telemetry/Events.yaml
+++ b/toolkit/components/telemetry/Events.yaml
@@ -277,8 +277,53 @@ devtools.main:
notification_emails: ["dev-developer-tools@lists.mozilla.org", "hkirschner@mozilla.com"]
record_in_processes: ["main"]
description: User is editing HTML via the context menu item in the markup view.
release_channel_collection: opt-out
expiry_version: never
extra_keys:
made_changes: Indicates whether changes were made.
time_open: The amount of time in ms that the HTML editor was open.
+ start_serviceworker:
+ objects: ["application"]
+ bug_numbers: [1451734]
+ notification_emails: ["dev-developer-tools@lists.mozilla.org", "hkirschner@mozilla.com"]
+ record_in_processes: ["main"]
+ description: User clicked on the Start link for a serviceworker in the application panel.
+ release_channel_collection: opt-out
+ expiry_version: never
+ debug_serviceworker:
+ objects: ["application"]
+ bug_numbers: [1451734]
+ notification_emails: ["dev-developer-tools@lists.mozilla.org", "hkirschner@mozilla.com"]
+ record_in_processes: ["main"]
+ description: User clicked on the Debug link for a serviceworker in the application panel.
+ release_channel_collection: opt-out
+ expiry_version: never
+ extra_keys:
+ duration: How much time the debugging toolbox was opened
+ unregister_serviceworker:
+ objects: ["application"]
+ bug_numbers: [1451734]
+ notification_emails: ["dev-developer-tools@lists.mozilla.org", "hkirschner@mozilla.com"]
+ record_in_processes: ["main"]
+ description: User clicked on the Unregister button for a serviceworker in the application panel.
+ release_channel_collection: opt-out
+ expiry_version: never
+ open_aboutdebugging:
+ objects: ["application"]
+ bug_numbers: [1451734]
+ notification_emails: ["dev-developer-tools@lists.mozilla.org", "hkirschner@mozilla.com"]
+ record_in_processes: ["main"]
+ description: User clicked on the aboutdebugging link displayed in the list of service workers of the application panel.
+ release_channel_collection: opt-out
+ expiry_version: never
+ open_help_link:
+ objects: ["application"]
+ bug_numbers: [1451734]
+ notification_emails: ["dev-developer-tools@lists.mozilla.org", "hkirschner@mozilla.com"]
+ record_in_processes: ["main"]
+ description: User clicked on a help link from the application panel empty screen.
+ release_channel_collection: opt-out
+ expiry_version: never
+ extra_keys:
+ helpLink: Action (toolid, or URL) triggered by clicking on the link
+