news 2026/10/15 2:21:40

Firebase JavaScript SDK 性能监控模块(@firebase/performance)公共 API 完全指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Firebase JavaScript SDK 性能监控模块(@firebase/performance)公共 API 完全指南
  • 开发工具
  • 后端

【免费下载链接】firebase-js-sdk

Firebase Javascript SDK

项目地址:https://gitcode.com/gh_mirrors/fi/firebase-js-sdk
点击查看免费下载

本指南以 firebase-js-sdk 仓库中@firebase/performance包的公开 API 报告(common/api-review/performance.api.md)为骨架,结合 packages/performance/src 下的核心源码与测试,系统讲解 Performance Monitoring Web SDK 的函数、接口、配置项与底层实现。读完本文,你将掌握如何初始化性能监控、配置数据采集开关、创建自定义 Trace,并理解自动埋点(页面加载、网络请求、Web Vitals)与日志上报的完整链路。

说明:本文面向浏览器环境。@firebase/performance明确指出不支持 Node.js 环境(见 packages/performance/src/index.ts),所有 API 均需在浏览器页面中运行。

一、API 概览:六个公共符号构成完整监控体系

API 报告文件列出了@firebase/performance的全部公共导出,共 3 个函数与 3 个接口:

类别符号作用
函数getPerformance(app?)获取指定 FirebaseApp 对应的FirebasePerformance实例(默认使用默认 app)
函数initializePerformance(app, settings?)初始化性能监控实例并注入可选配置,只能调用一次
函数trace(performance, name)创建一个新的自定义 Trace(性能追踪)实例
接口FirebasePerformance性能监控服务接口,暴露app与两个采集开关属性
接口PerformanceSettings初始化时的配置对象,含两个可选布尔开关
接口PerformanceTraceTrace 实例接口,含计时、指标(metric)与属性(attribute)操作

这六个符号的完整签名如下(源自 common/api-review/performance.api.md):

import { FirebaseApp } from '@firebase/app'; export interface FirebasePerformance { app: FirebaseApp; dataCollectionEnabled: boolean; instrumentationEnabled: boolean; } export function getPerformance(app?: FirebaseApp): FirebasePerformance; export function initializePerformance(app: FirebaseApp, settings?: PerformanceSettings): FirebasePerformance; export interface PerformanceSettings { dataCollectionEnabled?: boolean; instrumentationEnabled?: boolean; } export interface PerformanceTrace { getAttribute(attr: string): string | undefined; getAttributes(): { [key: string]: string }; getMetric(metricName: string): number; incrementMetric(metricName: string, num?: number): void; putAttribute(attr: string, value: string): void; putMetric(metricName: string, num: number): void; record(startTime: number, duration: number, options?: { metrics?: { [key: string]: number }; attributes?: { [key: string]: string }; }): void; removeAttribute(attr: string): void; start(): void; stop(): void; } export function trace(performance: FirebasePerformance, name: string): PerformanceTrace;

二、初始化:getPerformance与initializePerformance

2.1getPerformance(app?)——懒获取实例

getPerformance用于获取某个 app 关联的性能监控实例。源码实现位于 packages/performance/src/index.ts:

export function getPerformance( app: FirebaseApp = getApp() ): FirebasePerformance { app = getModularInstance(app); const provider = _getProvider(app, 'performance'); const perfInstance = provider.getImmediate() as PerformanceController; return perfInstance; }

关键行为:

  • app参数可选,缺省时自动使用默认 FirebaseApp(getApp());
  • 内部通过@firebase/component的 Provider 机制按需实例化服务;
  • 若实例尚未初始化,getPerformance会触发注册的工厂函数完成初始化(详见下文 2.3 的工厂逻辑)。

2.2initializePerformance(app, settings?)——带配置初始化

initializePerformance是带配置的初始化入口,且只能调用一次(packages/performance/src/index.ts):

export function initializePerformance( app: FirebaseApp, settings?: PerformanceSettings ): FirebasePerformance { app = getModularInstance(app); const provider = _getProvider(app, 'performance'); // throw if an instance was already created. // It could happen if initializePerformance() is called more than once, or getPerformance() is called first. if (provider.isInitialized()) { const existingInstance = provider.getImmediate(); const initialSettings = provider.getOptions() as PerformanceSettings; if (deepEqual(initialSettings, settings ?? {})) { return existingInstance; } else { throw ERROR_FACTORY.create(ErrorCode.ALREADY_INITIALIZED); } } const perfInstance = provider.initialize({ options: settings }) as PerformanceController; return perfInstance; }

注意这里的幂等性设计:

  • 若实例已存在且传入配置与原配置完全相同(通过deepEqual比较),直接返回既有实例,不会报错;
  • 若配置不同,则抛出already initialized错误(错误码定义见 packages/performance/src/utils/errors.ts),错误信息提示开发者应使用与首次调用相同的配置,或改用getPerformance()获取已初始化实例。

2.3 服务注册与工厂初始化条件

性能服务通过模块加载时自动调用registerPerformance()完成注册(packages/performance/src/index.ts)。实例工厂(第 112-133 行)包含三条硬性约束,理解它们有助于排查"性能监控不工作"的问题:

  1. 必须是默认 app:app.name !== '[DEFAULT]'时抛出FB not default错误;
  2. 必须在浏览器环境:typeof window === 'undefined'时抛出no window错误(再次印证不支持 Node.js);
  3. 依赖 Installations 与 API 能力:工厂会获取installations-internal依赖并调用setupApi(window)注入浏览器 API(packages/performance/src/services/api_service.ts)。

初始化完成后,PerformanceController._init(settings)会应用传入的配置并异步启动底层服务(packages/performance/src/controllers/perf.ts),只有浏览器支持 Fetch、Promise 且 Cookie 可用(requiredApisAvailable())时才会真正启动;否则仅打印一条 console 提示。

三、配置项详解:PerformanceSettings与两个开关

PerformanceSettings接口只有两个可选布尔字段(packages/performance/src/public_types.ts):

配置项类型默认值控制范围
dataCollectionEnabledboolean?true是否采集自定义事件(custom traces)
instrumentationEnabledboolean?true是否采集开箱即用事件(自动 Trace 与 HTTP/S 网络监控)

默认值来自单例SettingsService(packages/performance/src/services/settings_service.ts):

// The variable which controls logging of automatic traces and HTTP/S network monitoring. instrumentationEnabled = true; // The variable which controls logging of custom traces. dataCollectionEnabled = true;

运行时也可通过FirebasePerformance实例的属性动态切换(对应接口定义见 packages/performance/src/public_types.ts),这两个属性在PerformanceController中桥接到SettingsService(packages/performance/src/controllers/perf.ts):

set instrumentationEnabled(val: boolean) { SettingsService.getInstance().instrumentationEnabled = val; } set dataCollectionEnabled(val: boolean) { SettingsService.getInstance().dataCollectionEnabled = val; }

这两个开关的生效位置在日志层logTrace(packages/performance/src/services/perf_logger.ts):自动 Trace 在instrumentationEnabled为 false 时被丢弃;自定义 Trace 在dataCollectionEnabled为 false 时被丢弃。

3.1 初始化示例

import { initializeApp } from '@firebase/app'; import { getPerformance, initializePerformance } from '@firebase/performance'; const app = initializeApp(firebaseConfig); // 方式一:不传配置,直接获取实例 const perf = getPerformance(app); // 方式二:带配置初始化(只能调用一次) const perf2 = initializePerformance(app, { dataCollectionEnabled: true, // 采集自定义 Trace instrumentationEnabled: false // 关闭自动埋点(页面加载 / 网络请求) });

若你的业务只需要自定义 Trace 而想关闭自动埋点,instrumentationEnabled: false正是为此设计。

四、自定义 Trace:trace()与PerformanceTrace

4.1 创建 Trace

trace(performance, name)工厂函数(packages/performance/src/index.ts)返回一个Trace实例,其实现类位于 packages/performance/src/resources/trace.ts。Trace内部维护一个状态机(UNINITIALIZED→RUNNING→TERMINATED),非法调用会抛错。

4.2 计时:start()/stop()/record()

start/stop 模式适用于可以包裹在代码执行前后的场景:

const t = trace(getPerformance(), 'checkout-flow'); t.start(); // 开始计时 // ... 执行业务逻辑(如结算流程) t.stop(); // 停止计时并立即记录日志

底层实现(packages/performance/src/resources/trace.ts):

  • start()通过performance.mark()打上以FB-PERF-TRACE-START为前缀的 User Timing 标记(前缀常量见 packages/performance/src/constants.ts),重复 start 会抛出trace started错误;
  • stop()打停止标记、调用performance.measure()计算耗时,再由calculateTraceMetrics()从 Performance Timeline 读取时长(微秒级durationUs),最后交给logTrace上报。

record 模式适用于耗时信息先于 SDK 加载捕获、无法包裹代码的场景,直接给出起止时间:

t.record(startTime, duration, { metrics: { itemCount: 3 }, attributes: { experiment: 'v2' } });

record()的参数校验与行为(packages/performance/src/resources/trace.ts):

  • startTime与duration必须为正数,否则分别抛出nonpositive trace startTime/nonpositive trace duration错误;
  • 时间单位为毫秒,内部会乘以 1000 转换为微秒并向下取整;
  • metrics中非数值项会被静默忽略;
  • 调用后立即logTrace,无需再调stop()。

测试用例 packages/performance/src/resources/trace.test.ts 验证了record(0, 20)、record(-100, 20)等非法输入会抛错,且record(1, 20, { metrics: { cacheHits: 1 } })后getMetric('cacheHits')返回 1。

4.3 自定义指标(Metric):putMetric/incrementMetric/getMetric

方法语义说明
putMetric(name, num)将指标设为指定值不存在则创建;值会被向下取整为整数
incrementMetric(name, num?)累加指标num缺省为 1;不存在则按putMetric(name, num)创建
getMetric(name)读取指标值不存在时返回 0
t.putMetric('itemsLoaded', 42); t.incrementMetric('itemsLoaded'); // 变为 43 t.incrementMetric('retries', 3); // 新建 retries=3 const n = t.getMetric('itemsLoaded'); // 43

实现要点:

  • incrementMetric的默认增量是 1(packages/performance/src/resources/trace.ts);
  • 指标名须通过isValidMetricName校验(packages/performance/src/utils/metric_utils.ts):长度 1~100,且不能以保留前缀_开头(自动埋点的内置指标如_fcp、_lcp均以_开头,属于保留命名空间);
  • 值统一经convertMetricValueToInteger向下取整,小数输入会打印 console 提示(同文件第 62-69 行)。

4.4 自定义属性(Attribute):putAttribute/getAttribute/removeAttribute/getAttributes

属性用于给 Trace 附加维度信息(如实验分组、用户层级),便于在 Firebase 控制台分组分析:

t.putAttribute('experiment', 'v2'); const v = t.getAttribute('experiment'); // 'v2' t.removeAttribute('experiment'); const all = t.getAttributes(); // 当前全部属性的副本

校验规则来自 packages/performance/src/utils/attributes_utils.ts:

规则约束
属性名长度1~40 个字符
属性名格式必须以字母开头,仅含字母、数字、下划线(^[a-zA-Z]\w*$)
属性名保留前缀不能以firebase_、google_、ga_开头(避免与系统属性冲突)
属性值非空,长度不超过 100 字符

违反上述规则会分别抛出invalid attribute name/invalid attribute value错误(packages/performance/src/utils/errors.ts)。

五、开箱即用的自动埋点(Out-of-the-Box 资源)

当instrumentationEnabled为 true 时,SDK 会自动采集三类资源,全部由 packages/performance/src/services/oob_resources_service.ts 在初始化后通过setTimeout(0)分三条队列启动:

  1. 页面加载 Trace(Page Load Trace):监听pagehide(Safari 兼容降级为unload)与visibilitychange到 hidden 时,通过Trace.createOobTrace生成一条名为_wt_<页面路径>的自动 Trace,内置指标包括domInteractive、domContentLoadedEventEnd、loadEventEnd(来自 Navigation Timing),以及_fp(First Paint)、_fcp(First Contentful Paint)、_fid(First Input Delay)等(实现见 packages/performance/src/resources/trace.ts,指标常量见 packages/performance/src/constants.ts)。
  2. Web Vitals 采集:借助web-vitals/attribution库监听 LCP、CLS、INP,以_lcp、_cls、_inp指标上报,并附带lcp_element、cls_largestShiftTarget、inp_interactionTarget属性说明归因元素(packages/performance/src/services/oob_resources_service.ts)。
  3. 网络请求监控:遍历performance.getEntriesByType('resource')并通过PerformanceObserver持续监听,将每个资源请求转换为NetworkRequest(packages/performance/src/resources/network_request.ts),记录 URL(去掉 query 部分)、响应字节数、响应开始/完成耗时,然后走logNetworkRequest上报。
  4. User Timing 透传:监听页面中的performance.measure()条目,自动将开发者自定义的 User Timing measure 转成 Trace 上报(createUserTimingTrace),前提是该 measure 名不是 SDK 自身的FB-PERF-TRACE-MEASURE前缀(packages/performance/src/services/oob_resources_service.ts)。

六、数据上报链路:采样、批处理与传输

理解 Trace 从采集到入库的链路,能帮助你判断数据为何"没有上报"。

6.1 日志序列化与二次过滤

logTrace(packages/performance/src/services/perf_logger.ts)在写入上报队列前还会做四重检查:

  1. 自动 Trace 且instrumentationEnabled=false→ 丢弃;
  2. 自定义 Trace 且dataCollectionEnabled=false→ 丢弃;
  3. 浏览器缺少必要 API → 丢弃;
  4. 若初始化(Remote Config 拉取)尚未完成,则挂到getInitializationPromise上等初始化完成后再发送(自定义 Trace 允许在初始化前创建)。

序列化后的日志格式(serializeTrace,同文件第 221-242 行)包含trace_metric(name、is_auto、client_start_time_us、duration_us、counters、custom_attributes)与application_info(google_app_id、app_instance_id、sdk_version、page_url、service_worker_status、visibility_state、effective_connection_type 等环境维度)。

6.2 采样与开关(Remote Config 驱动)

SettingsService中有两组与服务端配置相关的字段(packages/performance/src/services/settings_service.ts):loggingEnabled(默认 false,由 Remote Config 下发)、tracesSamplingRate与networkRequestsSamplingRate(默认 1,即全量采样)、logTraceAfterSampling等。sendTraceLog只有loggingEnabled && logTraceAfterSampling同时为真才真正发送。SDK 启动时会从 Remote Config 拉取fpr_enabled、fpr_vc_trace_sampling_rate、fpr_log_max_flush_size等参数(packages/performance/src/services/remote_config_service.ts),配置默认缓存 12 小时(configTimeToLive = 12),并存于 localStorage(键为@firebase/performance/config)。

6.3 传输:批处理队列 + sendBeacon/fetch 双通道

packages/performance/src/services/transport_service.ts 实现了传输层:

  • 初始化后约 5.5 秒(INITIAL_SEND_TIME_DELAY_MS)首次尝试发送,之后每 10 秒(DEFAULT_SEND_INTERVAL_MS)轮询队列(第 78-90 行);
  • 单次请求最多携带 1000 条事件(MAX_EVENT_COUNT_PER_REQUEST),发送失败会将事件回插队列并重试,最多 3 次(DEFAULT_REMAINING_TRIES);
  • 优先使用navigator.sendBeacon(payload 上限 64KB,MAX_SEND_BEACON_PAYLOAD_SIZE),失败则回退到fetchPOST(第 137-154 行);
  • 页面卸载时flushLogs()会强制冲刷队列(每次最多 40 条,logMaxFlushSize),保证页面加载 Trace 优先送达(第 183-211 行)。

七、常见错误速查

SDK 通过@firebase/util的ErrorFactory统一构造错误(完整映射见 packages/performance/src/utils/errors.ts):

错误码触发场景
trace started对已启动的 Trace 再次调用start()
trace stopped对非 RUNNING 状态的 Trace 调用stop()
nonpositive trace startTimerecord()传入非正 startTime
nonpositive trace durationrecord()传入非正 duration
no window非浏览器环境调用(Node.js 等)
FB not default使用非默认 FirebaseApp 初始化性能监控
invalid attribute name/invalid attribute value自定义属性名/值不满足长度或格式约束
invalid custom metric name指标名超长或以保留前缀_开头
already initialized以不同配置重复调用initializePerformance()

八、版本与构建信息

@firebase/performance当前版本为0.7.14(packages/performance/package.json),依赖@firebase/installations(用于获取匿名实例 ID)、web-vitals(Web Vitals 采集)、@firebase/logger与@firebase/util;以@firebase/app为 peerDependency。该包不面向直接使用,官方推荐通过firebase聚合包使用(见 packages/performance/README.md),其 API 报告由 API Extractor 自动生成并作为发布门禁(yarn api-report,见 package.json 的 scripts)。

结语

通过 common/api-review/performance.api.md 这份 API 报告,我们完整梳理了 Firebase Performance Monitoring Web SDK 的六个公共符号:两个初始化函数(getPerformance/initializePerformance)、一个 Trace 工厂(trace)、一个配置接口(PerformanceSettings)与两个服务接口(FirebasePerformance/PerformanceTrace)。结合 packages/performance/src 的源码可以看到,每个公共 API 背后都有清晰的实现边界:状态机保障 Trace 生命周期合法性,attributes_utils/metric_utils执行命名校验,perf_logger与transport_service完成采样与批量上报。掌握这些 API 与开关语义,即可在浏览器应用中精确控制自定义与自动性能数据的采集范围。

  • 开发工具
  • 后端

【免费下载链接】firebase-js-sdk

Firebase Javascript SDK

项目地址:https://gitcode.com/gh_mirrors/fi/firebase-js-sdk
点击查看免费下载
上一篇:猫抓浏览器扩展:三秒搞定网页视频下载的终极解决方案
下一篇:Cycle.js响应式数据聚合性能优化:大数据集处理技巧

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 2:16:17

Flask项目部署Azure全攻略:从代码改造到稳定上线

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/15 2:16:04

C#调用VisionPro源码示例:VPP加载到结果回读的完整链路

简介&#xff1a;一份面向C#开发者的VisionPro集成源码示例&#xff0c;重点演示如何配置VisionPro SDK&#xff0c;并利用CogFindCircleTool在图像中查找圆形特征、显示检测结果。VisionPro是康耐视公司出品的机器视觉工具集&#xff0c;在制造业、物流等领域应用广泛&#xf…

作者头像 李华
网站建设 2026/10/15 2:15:14

DES安全性复盘与3DES续命逻辑:从暴力破解到中间相遇攻击

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/15 2:14:48

LangChain 工具调用实战:从 Tool 定义到 Agent 执行链路拆解

为什么单独聊工具调用 很多人学 LangChain&#xff0c;第一个完整例子往往是 Agent&#xff1a;给几个 Tool&#xff0c;接上模型&#xff0c;一句 agent.invoke() 就出结果。跑通很快&#xff0c;但一旦工具报错、模型不调用工具、或者需要自己控制中间步骤&#xff0c;就会卡…

作者头像 李华
网站建设 2026/10/15 2:14:33

Web经典高危漏洞深度防御实战白皮书:面向云原生时代的十重安全防线

在云原生微服务架构、容器编排与 Serverless 计算普及的今天&#xff0c;Web 攻防的战场已经发生了深刻的变化。过去单体系统时代的 Web 漏洞往往只影响单一主机的权限&#xff0c;而在由 Kubernetes、网关代理、分布式缓存与云元数据服务织就的庞大内网体系中&#xff0c;一个…

作者头像 李华