- 移动开发
【免费下载链接】fenix
⚠️ Fenix (Firefox for Android) moved to a new repository. It is now developed and maintained as part of: https://github.com/mozilla-mobile/firefox-android
导读
本文以 Implementing-Telemetry.md 为核心骨架,系统讲解在 Fenix(Firefox for Android)项目中如何通过 Mozilla 的 Glean 遥测框架实现功能埋点。你将掌握从需求对齐、metrics.yaml声明、代码上报、单元测试、数据评审到上线后验证与续期的完整实战链路,并理解仓库中credit_cards模块作为完整范例背后的源码级原理。无论你是为浏览器新功能添加 Telemetry 的贡献者,还是想理解 Mozilla 数据管道运作方式的开发者,本文都提供了可直接复用的步骤与配置参考。
一、为什么 Telemetry 不只是"功能完成的对勾"
在动手实现之前,Fenix 团队给出几条必须先建立的心智模型(源自 Implementing-Telemetry.md 开篇):
- Telemetry 是严肃的产品资产,不是功能上线前的勾选清单项;它是产品迭代决策的事实来源。
- Telemetry 的最终消费者是数据科学(Data Science)团队。埋点设计要围绕他们的分析需求展开,而不是开发者自己觉得"有用"就埋。
- 拿不准时,优先参考示例实现、文档和数据评审格式(下文会逐一给出仓库内对应的范本)。
- 避免使用 SharedPreferences来存储与遥测相关的状态,应依赖 Glean 自身的内存与持久化机制。
- 必须编写单元测试,确保埋点逻辑可验证、可回归。
仓库中的credit_cards系列埋点就是遵循这套纪律产出的范本,本文后续会以其为主线串联所有步骤。
二、动手埋点前的三道准备工序
原文给出了"先对齐、再动手"的强制流程,任何新功能埋点都必须依次完成:
1. 与产品团队对齐功能边界
先联系产品(Product)团队,弄清楚你正在添加 Telemetry 的功能是什么、用户行为路径有哪些、预期观察哪些漏斗或转化。埋点脱离功能语义就是噪声。
2. 与数据科学团队明确需求
联系数据科学团队,获取完整的需求清单,至少包括三类信息:
| 需求维度 | 要确认的问题 |
|---|---|
| 分类(Categories) | 数据科学团队期望在哪些分类下收到数据? |
| 指标(Metrics) | 每个分类下期望哪些具体 telemetry? |
| 数据类型(Data types) | 每条 telemetry 是计数、事件、字符串还是布尔值? |
3. 反复打磨直到每个指标都被精确定义
与数据科学团队一起"抬高/降低"预期,直到每个指标都清晰、可实现、有意义。具体动作包括:
- 告知对方哪些 telemetry 当前无法实现(如受系统权限或 Web 内容限制);
- 告知对方他们可能不知道的、可额外采集的 telemetry;
- 指出没有收集意义的数据组合(例如"B 总是在 A 之后发生"这类冗余关联);
- 主动帮助数据科学团队设计出最有价值的采集方案。
此外,如有疑问随时咨询 Glean 团队,例如"该用哪种数据类型"这类涉及框架语义的问题。
从源码结构看,Fenix 仓库中的 app/metrics.yaml 正是这些需求落地的载体,它已包含 9000 余行指标声明,覆盖启动、搜索、登录、自动填充等全部功能域,是与产品/数据科学团队逐轮对齐后的产物。
三、事件埋点的标准实现流程(核心)
原文给出实现一个 Glean 事件(event)的九步流程,以下是逐条展开并结合仓库实例的完整说明。
第 1 步:在 metrics.yaml 中声明事件并重建项目
所有指标都必须先在 app/metrics.yaml 中声明,然后执行项目重建以生成对应的 Kotlin 类型代码。
以credit_cards.modified为例(完整定义见 app/metrics.yaml#L8319-L8335):
credit_cards: modified: type: event description: | A credit card has been modified by the user. bugs: - https://github.com/mozilla-mobile/fenix/issues/18711 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/20909 - https://github.com/mozilla-mobile/fenix/pull/26123#issuecomment-1190794469 data_sensitivity: - interaction notification_emails: - android-probes@mozilla.com expires: 118 metadata: tags: - Autofill各字段的实践含义:
| 字段 | 作用 | 说明 |
|---|---|---|
type | 指标类型 | event表示事件;Fenix 还大量使用counter(如credit_cards.saved、credit_cards.deleted即为counter,见 app/metrics.yaml#L8282-L8318)以及string、boolean、timespan等类型 |
description | 指标语义 | 供数据科学与代码审查者理解该指标含义 |
bugs | 关联 issue | 追踪该指标来源的 GitHub issue |
data_reviews | 数据评审链接 | 每个指标必须挂接评审 PR 或其评论 URL,这是合规红线 |
data_sensitivity | 敏感级别 | 本例为interaction(交互数据);Glean 会据此约束存储与访问权限 |
notification_emails | 告警邮箱 | 指标过期或异常时的通知对象 |
expires | 过期版本 | 数字表示 release 版本号(如118);也可用日期(YYYY-MM-DD)或never,如app_opened即为never(见 app/metrics.yaml#L37) |
metadata.tags | 功能标签 | 便于在 Glean Dictionary 中按功能检索,见后文"功能标签"一节 |
若事件需要携带附加信息,用extra_keys声明键。例如performed_search事件用source键记录搜索发生的方式(default.action、default.suggestion、shortcut.action、shortcut.suggestion),见 app/metrics.yaml#L97-L111。extra_keys中每个键必须声明type(string/boolean等)与description。
生成代码:重建后 Glean 插件会根据
metrics.yaml生成形如org.mozilla.fenix.GleanMetrics.CreditCards的类,其中每个指标对应一个可调用的伴生对象属性。
第 2 步:添加功能标签(feature tags)
为了让指标在 Glean Dictionary 中便于检索,需要在指标上添加对应功能域的tags。过去需要在 Glean Annotations 仓库单独维护,现在可直接在metrics.yaml中通过metadata.tags声明(详见 Metric-Feature-Tags.md):
search_bar_tapped: type: event description: | A user tapped the search bar metadata: tags: - Search ...合法标签集合由 app/tags.yaml 定义(如Autofill、Search、Tabs、Telemetry等数十个),文件头部注明"由./tools/update-glean-tags.py自动生成,禁止手改"。如果 GitHub 上的 feature 标签有增删,需在仓库根目录运行同步脚本:
./tools/update-glean-tags.py注意两点约束(来自 Metric-Feature-Tags.md):
- 一个 tag 必须存在于
tags.yaml中才能被指标使用; - 若某 tag 从
tags.yaml中移除,metrics.yaml中所有使用它的位置必须一并删除,否则校验失败。
Fenix 的credit_cards与addresses全部指标都挂了Autofill标签(见 app/tags.yaml#L21-L23 对Autofill的定义:对应 Address and Credit Card autofill 的 feature label)。
第 3 步(原文第 5 步):在正确的代码位置发送事件
重建生成类型代码后,在功能逻辑真正发生的代码路径中调用生成的record()方法,命名遵循GeneratedClassMetrics.generatedEvent.record()的驼峰转换规则:credit_cards.modified→CreditCards.modified.record(...)。
仓库中真实的调用点如下:
修改信用卡:
CreditCardEditorController.kt中保存成功后上报:CreditCardEditorController.kt#L103:
import org.mozilla.fenix.GleanMetrics.CreditCards // ... CreditCards.modified.record(NoExtras())管理页点击事件:CreditCardsManagementInteractor.kt#L44-L49 在用户点击已保存卡片与点击"添加"按钮时分别上报:
CreditCards.managementCardTapped.record(NoExtras()) CreditCards.managementAddTapped.record(NoExtras())
带extra_keys的事件则需传入键值对象,例如NoExtras()代表无附加键,带键时使用 Glean 生成的对应 extra 类(形如PerformedSearchExtra().apply { source = "default.action" })。
源码结构提示:Fenix 的事件发送点通常位于 Interactor(交互逻辑层)与 Controller(控制器层),而非 View 层,这保证了埋点与 UI 渲染解耦、便于单测。
第 4 步(原文第 6 步):创建 Pull Request
将metrics.yaml声明、生成的类型代码引用、业务代码改动一起提交,创建 Pull Request。参考原文给出的完整示例:Fenix PR #20909(credit card 系列埋点)。此外还可以参考 Android Components 与 Glean Annotations 仓库的同类 PR,理解"组件库 + 应用 + 注解"三层如何联动。
第 5 步(原文第 7 步):提交数据评审(Data Review)
Telemetry 涉及用户数据采集,任何新指标都必须经过数据评审:
- 评审格式模板:采用 Mozilla>@RunWith(FenixRobolectricTestRunner::class) class DefaultCreditCardsManagementInteractorTest { @get:Rule val gleanTestRule = GleanTestRule(testContext) // ... @Test fun onSelectCreditCard() { val creditCard: CreditCard = mockk(relaxed = true) assertNull(CreditCards.managementCardTapped.testGetValue()) interactor.onSelectCreditCard(creditCard) verify { controller.handleCreditCardClicked(creditCard) } assertNotNull(CreditCards.managementCardTapped.testGetValue()) } @Test fun onClickAddCreditCard() { assertNull(CreditCards.managementAddTapped.testGetValue()) interactor.onAddCreditCardClick() verify { controller.handleAddCreditCardClicked() } assertNotNull(CreditCards.managementAddTapped.testGetValue()) } }
测试模式要点:
- 触发前先断言
testGetValue()为 null,确认"未埋点"基线; - 调用触发埋点的交互方法;
- 断言控制器行为被委派(
verify); - 断言
testGetValue()非空,确认事件确实被记录。
仓库中同类测试还包括 DefaultCreditCardsManagementControllerTest.kt、DefaultCreditCardEditorControllerTest.kt 等,共同构成了"每个埋点都有测试"的覆盖网络。
六、Merge 之后:上线验证与数据确认
合并并不代表结束,原文给出两步收尾动作:
1. 回到 Glean Dictionary 验证事件上报
当改动进入 beta/release 渠道后,回到Glean Dictionary核对指标是否真实上报:
- 事件类:在 Glean Dictionary 中按
app名/metrics/指标名找到对应页面(原文示例为credit_cards.modified,字典 URL 形如https://dictionary.telemetry.mozilla.org/apps/fenix/metrics/credit_cards_modified),页面底部的 Looker 链接可确认事件计数; - 指标类(counter/string 等):用 SQL 平台创建查询(原文示例 query 82373)确认指标值持续上报。
2. 与数据科学团队确认数据可用性
主动与数据科学团队核对:他们看到的数据是否符合需求定义,是否存在字段缺失、计数异常或口径偏差,必要时回到
metrics.yaml调整声明。七、续期过期 Telemetry
所有指标都带
expires字段,到期后 Glean 将停止采集。续期操作参考 Creating-a-release-branch.md 中"Renew Telemetry"一节:- 定位
metrics.yaml中即将过期的指标(如expires: 118); - 评估是否仍有采集价值;若继续采集,则需在 release 分支上更新
expires(顺延版本号或日期),同时确认data_reviews记录仍有效; - 若指标不再需要,让其自然过期即可,无需额外处理。
从源码看,Fenix 中大量指标使用版本号形式(如
credit_cards系列的expires: 118),部分长期指标使用never(如app_opened),仓库的持续集成与 release 流程会同步跟踪过期状态。八、仓库内配套资源速查
资源 路径 用途 指标声明文件 app/metrics.yaml 全部指标的权威定义(约 9000 行) 自定义 ping 定义 app/pings.yaml activation、first-session等 ping 的生命周期说明合法功能标签 app/tags.yaml 指标 metadata.tags的合法取值功能标签使用指南 docs/Metric-Feature-Tags.md 如何为指标添加/同步标签 启动指标手动验证 docs/Test-telemetry-pings.md startup ping 的手动验证步骤 续期与发布流程 docs/Creating-a-release-branch.md 指标续期操作方法 标签同步脚本 tools/update-glean-tags.py 根据 GitHub feature 标签同步 tags.yaml埋点示例(credit_cards) CreditCardEditorController.kt、CreditCardsManagementInteractor.kt 事件上报的标准写法 埋点单测示例 DefaultCreditCardsManagementInteractorTest.kt GleanTestRule 断言范式 结语
实现 Telemetry 的完整链路可以浓缩为一句话:先与产品、数据科学团队对齐需求,再在
metrics.yaml精确声明、重建生成代码、在正确位置调用record()、用 GleanTestRule 写测试、经数据评审后合并,最后回到 Glean Dictionary 验证真实上报,并按 release 节奏续期。这套流程在 Fenix 仓库中由 Implementing-Telemetry.md 固化为工程规范,credit_cards系列(app/metrics.yaml#L8282-L8501 的声明 + 源码上报 + 单测覆盖)则是这条规范最完整的落地方案。开发者在新功能中复刻这一模式,即可保证 Telemetry 从设计到上线全链路合规、可追溯、可验证。赞- 移动开发
点击查看免费下载【免费下载链接】fenix
⚠️ Fenix (Firefox for Android) moved to a new repository. It is now developed and maintained as part of: https://github.com/mozilla-mobile/firefox-android
项目地址:https://gitcode.com/gh_mirrors/fe/fenix相关推荐
如何快速构建Firefox Fenix Android浏览器:完整开发指南与架构解析
如何快速构建Firefox Fenix Android浏览器:完整开发指南与架构解析 Firefox Fenix是Mozilla为Android设备打造的全新浏
移动开发SeaweedFS Telemetry Server 部署指南:基于 GitHub Actions 与 Docker 的完整落地实践
SeaweedFS Telemetry Server 部署指南:基于 GitHub Actions 与 Docker 的完整落地实践 本文是 SeaweedFS
分布式文件系统对象存储存储如何从零开始构建现代Android浏览器:Firefox Fenix完整开发指南
如何从零开始构建现代Android浏览器:Firefox Fenix完整开发指南 Firefox Fenix(Firefox for Android)是Mozi
移动开发
上一篇:ClickHouse 25.11 版本全解析:Geometry 正式类型化、EXECUTE AS 用户模拟与 Prometheus Query API 落地下一篇:DataHub 核心概念全解析:URN、策略、角色与元数据建模模型 - 触发前先断言
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考