☰
Fenix(Firefox for Android)Telemetry 实现指南:基于 Glean 的完整落地流程
2026/10/8 8:16:14 网站建设 项目流程
  • 移动开发

【免费下载链接】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
点击查看免费下载

导读

本文以 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()) } }

    测试模式要点:

    1. 触发前先断言testGetValue()为 null,确认"未埋点"基线;
    2. 调用触发埋点的交互方法;
    3. 断言控制器行为被委派(verify);
    4. 断言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.yamlactivation、first-session等 ping 的生命周期说明
    合法功能标签app/tags.yaml指标metadata.tags的合法取值
    功能标签使用指南docs/Metric-Feature-Tags.md如何为指标添加/同步标签
    启动指标手动验证docs/Test-telemetry-pings.mdstartup ping 的手动验证步骤
    续期与发布流程docs/Creating-a-release-branch.md指标续期操作方法
    标签同步脚本tools/update-glean-tags.py根据 GitHub feature 标签同步tags.yaml
    埋点示例(credit_cards)CreditCardEditorController.kt、CreditCardsManagementInteractor.kt事件上报的标准写法
    埋点单测示例DefaultCreditCardsManagementInteractorTest.ktGleanTestRule 断言范式

    结语

    实现 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
    点击查看免费下载
    上一篇:ClickHouse 25.11 版本全解析:Geometry 正式类型化、EXECUTE AS 用户模拟与 Prometheus Query API 落地
    下一篇:DataHub 核心概念全解析:URN、策略、角色与元数据建模模型

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询