遥测¶
我们使用遥测来获取 DevTools 中不同功能和面板使用情况的指标。这将帮助我们在优先考虑工作时做出更明智、更合理的决策。
向工具添加指标¶
向工具添加指标的过程大致包括以下步骤:
向 Firefox 添加探针
在 DevTools 代码中使用 Histograms.json 探针
在 DevTools 代码中使用 Scalars.yaml 探针
在 DevTools 代码中使用 Events.yaml 探针,以便在 Amplitude 中进行分析。
获得数据团队的批准
1. 向 Firefox 添加探针¶
第一步涉及在包含 Firefox 可能报告给 Mozilla 的所有数据声明的文件之一中创建探针的条目。
这些文件是:
toolkit/components/telemetry/Histograms.json
toolkit/components/telemetry/Scalars.yaml
toolkit/components/telemetry/Events.yaml
标量允许收集简单值,例如计数、布尔值和字符串,并且应尽可能使用标量而不是直方图。
直方图允许收集多个不同的值,但将其聚合到多个桶中。每个桶都有一个值范围和一个记录了多少值的计数。
事件允许收集许多属性,这些属性与事件发生的类别、方法、对象和值相关联。事件遥测帮助我们讲述用户如何与浏览器交互的故事。
标量和直方图都允许通过键记录数据。这允许更灵活的两级数据收集。
不同的文件格式¶
数据团队选择 YAML 用于 Scalars.yaml
和 Events.yaml
,因为它易于编写并提供 JSON 中不可用的许多功能,包括注释、可扩展的数据类型、关系锚点、不带引号的字符串以及保留键顺序的映射类型。
虽然我们之前在 histograms.json 中出于类似目的使用了 JSON,但我们在这里使用了 YAML,因为它允许添加注释并且通常更容易编写。
数据团队正在考虑在某个时候将直方图迁移到 YAML 格式。
如果您是第一次添加其中之一,建议您遵循现有条目的样式。
多年来添加了新的数据类型,因此我们的一些探针现在不太适合的情况是完全有可能的。
有关类型(以及一般遥测)的更多信息,请参阅 此页面 和 此其他页面。
当然,如有疑问,请随时提问!
向 Histograms.json
添加探针¶
我们的条目以 DEVTOOLS_
为前缀。例如:
"DEVTOOLS_DOM_OPENED_COUNT": {
"alert_emails": ["[email protected]"],
"expires_in_version": "never",
"kind": "count",
"bug_numbers": [1343501],
"description": "Number of times the DevTools DOM Inspector has been opened.",
"releaseChannelCollection": "opt-out"
},
"DEVTOOLS_DOM_TIME_ACTIVE_SECONDS": {
"alert_emails": ["[email protected]"],
"expires_in_version": "never",
"kind": "exponential",
"bug_numbers": [1343501],
"high": 10000000,
"n_buckets": 100,
"description": "How long has the DOM inspector been active (seconds)"
},
您可以使用不同类型的探针。这些由 kind
字段指定。通常我们使用 count
来计算工具打开的次数,使用 exponential
来计算面板激活的次数。
向 Scalars.yaml
添加探针¶
我们的条目以 devtools.
为前缀。例如:
devtools.toolbar.eyedropper:
opened:
bug_numbers:
- 1247985
- 1352115
description: Number of times the DevTools Eyedropper has been opened via the inspector toolbar.
expires: never
kind: uint
notification_emails:
- [email protected]
release_channel_collection: opt-out
record_in_processes:
- 'main'
devtools.copy.unique.css.selector:
opened:
bug_numbers:
- 1323700
- 1352115
description: Number of times the DevTools copy unique CSS selector has been used.
expires: "57"
kind: uint
notification_emails:
- [email protected]
release_channel_collection: opt-out
record_in_processes:
- 'main'
向 Events.yaml
添加探针¶
我们的条目以 devtools.
为前缀。例如:
devtools.main:
open:
objects: ["tools"]
bug_numbers: [1416024]
notification_emails: ["[email protected]", "[email protected]"]
record_in_processes: ["main"]
description: User opens devtools toolbox.
release_channel_collection: opt-out
expiry_version: never
extra_keys:
entrypoint: How was the toolbox opened? CommandLine, ContextMenu, HamburgerMenu, KeyShortcut, SessionRestore or SystemMenu
first_panel: The name of the first panel opened.
host: "Toolbox host (positioning): bottom, side, window or other."
splitconsole: Indicates whether the split console was open.
width: Toolbox width (px).
2. 在 DevTools 代码中使用 Histograms.json 探针¶
在 Histograms.json
文件中声明探针后,您需要在我们的代码中实际使用它。
首先,您需要在 devtools/client/shared/telemetry.js
中为其指定一个 ID。与 Histograms.json
的情况类似,您需要遵循现有条目的样式。例如:
dom: {
histogram: "DEVTOOLS_DOM_OPENED_COUNT",
timerHistogram: "DEVTOOLS_DOM_TIME_ACTIVE_SECONDS"
},
… 将对应于我们在上一节中声明的探针。
然后,在每个需要遥测的工具上包含该模块
let Telemetry = require("devtools/client/shared/telemetry");
在工具构造函数上创建一个遥测实例
this._telemetry = new Telemetry({ useSessionId: true });
useSessionId
允许在随机唯一的“session_id”额外属性后面聚合所有记录。例如,这有助于聚合为一个特定的工具箱实例记录的所有数据。
并使用该实例报告例如工具打开…
this._telemetry.toolOpened("mytoolname", this);
… 或关闭
this._telemetry.toolClosed("mytoolname", this);
请注意,mytoolname
是我们在 telemetry.js
模块中声明的 ID。
3. 在 DevTools 代码中使用 Scalars.yaml 探针¶
在 Scalars.yaml
文件中声明探针后,您需要在我们的代码中实际使用它。
首先,您需要在 devtools/client/shared/telemetry.js
中为其指定一个 ID。您需要遵循现有小写直方图条目的样式。例如:
toolbareyedropper: {
scalar: "devtools.toolbar.eyedropper.opened", // Note that the scalar is lowercase
},
copyuniquecssselector: {
scalar: "devtools.copy.unique.css.selector.opened",
},
… 将对应于我们在上一节中声明的探针。
然后,在每个需要遥测的工具上包含该模块
let Telemetry = require("devtools/client/shared/telemetry");
在工具构造函数上创建一个遥测实例
this._telemetry = new Telemetry();
并使用该实例报告例如工具打开…
this._telemetry.toolOpened("mytoolname", this);
注意
mytoolname
是我们在Scalars.yaml
模块中声明的 ID。因为我们没有在
Scalars.yaml
中记录工具打开的时间,所以我们不关心 toolClosed。当然,如果telemetry.js
和histograms.json
中定义了相应的timerHistogram
字段,则也应添加toolClosed
。
4. 在 DevTools 代码中使用 Events.yaml 探针¶
在 Events.yaml
文件中声明探针后,您需要在我们的代码中实际使用它。
至关重要的是要理解事件遥测有一个字符串标识符,该标识符由 category
、method
、object
(名称)和事件发生时所在的 value
构成。此键指向一个“extra”对象,其中包含有关事件的更多信息(我们将在本节后面给出示例)。
由于这些“extra”对象可以来自完全独立的代码路径,因此我们可以发送事件并将其保留在挂起状态,直到收到所有预期的额外属性。
首先,在每个需要遥测的工具中包含遥测模块
let Telemetry = require("devtools/client/shared/telemetry");
在工具构造函数上创建一个遥测实例
this._telemetry = new Telemetry();
并使用该实例报告例如工具打开…
// If you already have all the properties for the event you can send the
// telemetry event using:
// this._telemetry.recordEvent(method, object, value, extra) e.g.
this._telemetry.recordEvent("open", "tools", null, {
"entrypoint": "ContextMenu",
"first_panel": "Inspector",
"host": "bottom",
"splitconsole": false,
"width": 1024,
});
// If your "extra" properties are in different code paths you will need to
// create a "pending event." These events contain a list of expected properties
// that can be populated before or after creating the pending event.
// Use the category, method, object, value combinations above to add a
// property... we do this before creating the pending event simply to
// demonstrate that properties can be sent before the pending event is created.
this._telemetry.addEventProperty(
this, "open", "tools", null, "entrypoint", "ContextMenu");
// In this example `"open", "tools", null` make up the
// signature of the event and needs to be sent with all properties.
// Create the pending event using
// this._telemetry.preparePendingEvent(this, method, object, value,
// expectedPropertyNames) e.g.
this._telemetry.preparePendingEvent(this, "open", "tools", null,
["entrypoint", "first_panel", "host", "splitconsole", "width", "session_id"]
);
// Use the category, method, object, value combinations above to add each
// property.
this._telemetry.addEventProperty(
this, "open", "tools", null, "first_panel", "inspector");
this._telemetry.addEventProperty(
this, "open", "tools", null, "host", "bottom");
this._telemetry.addEventProperty(
this, "open", "tools", null, "splitconsole", false);
this._telemetry.addEventProperty(
this, "open", "tools", null, "width", 1024);
// You can also add properties in batches using e.g.:
this._telemetry.addEventProperties(this, "open", "tools", null, {
"first_panel": "inspector",
"host": "bottom",
"splitconsole": false,
"width": 1024
});
注意
mytoolname
是我们在Scalars.yaml
模块中声明的 ID。因为我们没有在
Scalars.yaml
中记录工具打开的时间,所以我们不关心 toolClosed。当然,如果telemetry.js
和histograms.json
中定义了相应的timerHistogram
字段,则也应添加toolClosed
。
关于顶级面板的说明¶
选项卡的代码使用它们的 ID 在您在面板之间切换时自动报告遥测,因此您无需在顶级面板上显式调用 toolOpened
和 toolClosed
。
您仍然需要在子面板或 about:debugging
等未作为选项卡打开的工具上调用这些函数。
测试¶
如果缺少 ID,遥测模块将向标准输出打印警告。强烈建议确保此功能正常工作,因为该模块会将未声明 ID 的使用情况归因于通用 custom
桶。这对获得准确的结果不利!
要查看这些警告,您需要将 browser.dom.window.dump.enabled
浏览器首选项设置为 true
(在 about:config
中)(并重新启动浏览器)。
然后,尝试执行触发遥测调用的操作(例如打开工具)。假设我们在报告工具已打开时输入错误
this._telemetry.toolOpened('mytoolnmae', this);
^^^^ typo, should be *mytoolname*
将向标准输出报告错误
Warning: An attempt was made to write to the mytoolnmae histogram, which is not defined in Histograms.json
因此,请注意错误。
测试事件遥测¶
这最好通过示例来说明
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { Toolbox } = require("devtools/client/framework/toolbox");
const { TelemetryTestUtils } = ChromeUtils.importESModule("resource://testing-common/TelemetryTestUtils.sys.mjs");
const URL = "data:text/html;charset=utf8,browser_toolbox_telemetry_close.js";
const { RIGHT, BOTTOM } = Toolbox.HostType;
const DATA = [
{
category: "devtools.main",
method: "close",
object: "tools",
value: null,
extra: {
host: "right",
width: w => w > 0,
}
},
{
category: "devtools.main",
method: "close",
object: "tools",
value: null,
extra: {
host: "bottom",
width: w => w > 0,
}
}
];
add_task(async function() {
// Let's reset the counts.
Services.telemetry.clearEvents();
// Ensure no events have been logged
TelemetryTestUtils.assertNumberOfEvents(0);
await openAndCloseToolbox("webconsole", SIDE);
await openAndCloseToolbox("webconsole", BOTTOM);
checkResults();
});
async function openAndCloseToolbox(toolId, host) {
const tab = await addTab(URL);
const toolbox = await gDevTools.showToolboxForTab(tab, { toolId });
await toolbox.switchHost(host);
await toolbox.destroy();
}
function checkResults() {
TelemetryTestUtils.assertEvents(DATA, {category: "devtools.main", method: "close", object: "tools"});
}
编译它¶
如果您已编辑 Histograms.json
或 Events.yaml
,则需要进行完整的 Firefox 构建,因为它们是在构建时处理的,并且会对其运行各种检查以确保它们有效。
./mach build
如果您使用 mach build faster
或构件构建,则不会执行这些检查,并且当在那里运行这些检查时,您的 Try 构建将失败(“崩溃”)。
节省您的时间,并在本地运行检查。
注意:对 Scalars.yaml
的更改会在执行构件构建时处理。
4. 获得数据团队的批准¶
在更改进入 mozilla-central
之前,需要获得此批准。
要获得批准,请将您的补丁附加到 Bugzilla 中的错误,并设置两个标记
一个用于数据管理员的
review?
标记。一个用于 hkirschner 的
needinfo?
标记(我们的产品经理,因此他证明我们正在使用这些数据)。
请务必清楚地解释新探针的用途。例如,“我们正在寻求批准以跟踪用于调试 Web API ABCD 的新面板的打开次数”比在没有背景信息的情况下只是请求反馈要好得多。
此审查不应该花费太长时间:如果存在问题,他们应该告诉您如何解决。如果您在几天后没有看到任何活动迹象,您可以在 #developers
中询问。
请注意,此审查除了正常的同事审查之外。
单击 此处 以获取更多详细信息。
访问现有数据¶
本地数据¶
转到 about:telemetry
以查看与您的本地实例相关的统计信息。
全局数据¶
从大量 Firefox 用户聚合的数据可在 telemetry.mozilla.org 获取。
报告使用 SQL 编写。例如,以下报告比较了 一些 DevTools 面板的使用情况。
如果您想更好地了解人们如何使用这些工具,建议您通过编写自己的报告来探索此数据集。
最简单的入门方法是派生现有报告并对其进行修改,以熟悉语法,因为用于海量数据表的 SQL 与用于简单博客引擎的 SQL 非常不同,您会发现一些可能看起来不熟悉的新的运算符。
还建议采取小步骤并经常运行查询,以便在错误过于复杂难以解决之前检测到它们,尤其是在您(尚未)熟悉此操作时。
系统会中断缓慢的查询,因此不必担心“提取过多数据”或“使用过多资源”。内置了保护措施以避免您的代码占用遥测数据库。
有趣的是,如果您居住在欧洲,您可能很幸运,因为该网站在欧洲工作时间比在太平洋工作时间响应更快,因为似乎欧洲与之交互的人数较少。