Firebase JS SDK PerformanceTrace 接口深度解析:自定义性能追踪(Trace)的完整开发指南

发布时间:2026/10/16 3:56:52
Firebase JS SDK PerformanceTrace 接口深度解析:自定义性能追踪(Trace)的完整开发指南
开发工具后端【免费下载链接】firebase-js-sdkFirebase Javascript SDK项目地址https://gitcode.com/gh_mirrors/fi/firebase-js-sdk点击查看免费下载PerformanceTrace是 Firebase Performance Monitoring Web SDK 暴露给开发者用于自定义性能追踪的核心接口对应仓库内的Trace实现类。通过它你可以在应用的任意关键路径图片加载、接口请求、支付流程、首屏渲染等上手动埋点记录耗时、自定义指标metric与自定义属性attribute并随 SDK 自动采集的页面加载追踪、网络请求追踪一起上报到 Firebase 控制台。读完本文你将掌握start/stop计时模型与record直接记录模型的使用方式、指标与属性的命名约束、底层 User Timing API 与日志上报机制并能直接在项目中落地一套可观测的自定义性能埋点方案。本文以 docs-devsite/performance.performancetrace.md 为骨架结合 packages/performance 下的源码实现Trace类、校验工具、日志服务与测试用例展开讲解。一、PerformanceTrace 是什么一次自定义追踪的完整生命周期PerformanceTrace是一次性能追踪的抽象官方接口定义位于 packages/performance/src/public_types.ts共暴露 10 个方法方法作用分类start()开始计时计时模型stop()停止计时并上报数据计时模型record(startTime, duration, options?)用给定参数直接记录一次追踪无需 start/stop直接记录模型incrementMetric(metricName, num?)累加自定义指标不存在则新建默认加 1自定义指标putMetric(metricName, num)设置自定义指标为指定值存在则覆盖自定义指标getMetric(metricName)读取自定义指标值不存在返回 0自定义指标putAttribute(attr, value)设置自定义属性自定义属性getAttribute(attr)读取自定义属性值不存在返回undefined自定义属性removeAttribute(attr)删除自定义属性自定义属性getAttributes()返回全部自定义属性的副本自定义属性从源码实现看一次 Trace 实例内部有严格的三态状态机packages/performance/src/resources/trace.tsconst enum TraceState { UNINITIALIZED 1, // 创建后、尚未 start RUNNING, // start() 后、stop() 前 TERMINATED // stop() 或 record() 之后生命周期结束 }理解这个状态机对正确使用 API 至关重要start()只能在UNINITIALIZED状态调用一次stop()只能在RUNNING状态调用record()则绕过状态机一步到位。二、获取 PerformanceTrace 实例自定义 Trace 不能直接new需要通过模块级函数trace(performance, name)创建。该函数在 packages/performance/src/index.ts 中实现import { getPerformance, trace } from firebase/performance; const perf getPerformance(); // 获取 FirebasePerformance 实例 const t trace(perf, image-load-trace); // 创建名为 image-load-trace 的 TracegetPerformance()默认使用默认 FirebaseAppgetApp()返回与 app 关联的FirebasePerformance实例。需要指出的是Performance SDK 是纯 Web SDK源码顶部明确标注This SDK does not work in a Node.js environmentpackages/performance/src/index.ts且实例工厂中若检测不到window会抛出Window is not available.错误packages/performance/src/index.ts。此外Performance 实例只允许绑定默认 Firebase app非默认 app 会抛出FB not defaultpackages/performance/src/index.ts。如需在初始化时指定采集开关可改用initializePerformance(app, settings)。Trace 名称的隐藏前缀内部创建 Trace 时会自动为 User Timing 标记生成带随机 ID 的名称packages/performance/src/constants.ts开始标记FB-PERF-TRACE-START-{randomId}-{traceName}结束标记FB-PERF-TRACE-STOP-{randomId}-{traceName}测量项FB-PERF-TRACE-MEASURE-{randomId}-{traceName}randomId为 01000000 的随机整数packages/performance/src/resources/trace.ts用于避免同页面多次追踪之间命名冲突。这些名称会出现在浏览器的 Performance 面板中可作为调试线索。三、计时模型start() 与 stop()start()与stop()是使用频率最高的一对方法用于围绕一段同步或异步代码测量真实耗时。3.1 start()开始计时start(): void;实现逻辑packages/performance/src/resources/trace.tsstart(): void { if (this.state ! TraceState.UNINITIALIZED) { throw ERROR_FACTORY.create(ErrorCode.TRACE_STARTED_BEFORE, { traceName: this.name }); } this.api.mark(this.traceStartMark); this.state TraceState.RUNNING; }要点只能调用一次状态非UNINITIALIZED时再次调用会抛出Trace {name} was started before.。底层调用浏览器的performance.mark()User Timing API打下一个开始标记。3.2 stop()停止计时并上报stop(): void;实现逻辑packages/performance/src/resources/trace.tsstop(): void { if (this.state ! TraceState.RUNNING) { throw ERROR_FACTORY.create(ErrorCode.TRACE_STOPPED_BEFORE, { traceName: this.name }); } this.state TraceState.TERMINATED; this.api.mark(this.traceStopMark); this.api.measure( this.traceMeasure, this.traceStartMark, this.traceStopMark ); this.calculateTraceMetrics(); logTrace(this); }要点必须处于 RUNNING 状态否则抛出Trace {name} is not running.。依次完成打结束标记 →performance.measure()计算开始到结束的时长 → 从 measure 条目读取duration和startTimepackages/performance/src/resources/trace.ts→ 触发日志上报。时间单位换算内部以**微秒us**存储durationUs Math.floor(duration * 1000)startTimeUs为 mark 起始时间与timeOrigin之和的微秒值。stop()后 Trace 进入TERMINATED状态生命周期结束后续再调用start()/stop()都会抛错。3.3 典型用法import { getPerformance, trace } from firebase/performance; const perf getPerformance(); const t trace(perf, checkout-step-1); t.start(); try { await loadCheckoutPage(); // 你的业务代码 t.putAttribute(result, success); } catch (e) { t.putAttribute(result, error); } finally { t.stop(); }对应测试用例packages/performance/src/resources/trace.test.ts验证了start()调用底层mark一次、stop()再打一次标记共两次mark且stop()会调用logTrace恰好一次。重复start()会抛错throws if a trace is started twice。四、直接记录模型record()record()提供了一条无需 start/stop的记录路径适合耗时在 SDK 加载之前就已发生或耗时无法在调用现场测量的场景例如数据在 Service Worker 中预先采集、或页面早期渲染时间在 Performance SDK 初始化前已被捕获。record( startTime: number, // trace 开始时间Unix 纪元以来的毫秒数必须为正数 duration: number, // trace 持续时间毫秒必须为正数 options?: { metrics?: { [key: string]: number }; // 可选的指标映射 attributes?: { [key: string]: string }; // 可选的属性映射 } ): void;实现要点packages/performance/src/resources/trace.ts参数强校验startTime 0抛出Trace {name} startTime should be positive.duration 0抛出Trace {name} duration should be positive.。对应测试packages/performance/src/resources/trace.test.ts覆盖了record(0, 20)、record(-100, 20)、record(1000, 0)、record(1000, -200)全部抛错场景。毫秒自动转为微秒durationUs Math.floor(duration * 1000)startTimeUs Math.floor(startTime * 1000)。options.attributes会整体覆盖当前自定义属性集浅拷贝。options.metrics会逐项写入计数器但isNaN(Number(value))的值如NaN会被静默跳过packages/performance/src/resources/trace.ts。测试验证了传入{ level: NaN }时最终getMetric(level)为 0packages/performance/src/resources/trace.test.ts。调用record()后立即触发logTrace(this)生命周期直接终结。典型用法——上报一段在 SDK 加载前采集到的耗时import { getPerformance, trace } from firebase/performance; const perf getPerformance(); // startTime/duration 为毫秒可能来自早期埋点或外部数据源 trace(perf, pre-sdk-timing).record( Date.now() - 350, // 假设这段耗时在 SDK 加载前就已开始 350, { metrics: { cacheHits: 3, bytesDownloaded: 2048 }, attributes: { env: production, region: cn-east } } );五、自定义指标MetricsincrementMetric / putMetric / getMetric自定义指标用于记录可累加或可量化的数值例如缓存命中次数、渲染元素个数、请求失败数。5.1 incrementMetric()累加incrementMetric(metricName: string, num?: number): void;num缺省时默认值为1源码签名numAsInteger 1见 packages/performance/src/resources/trace.ts。若指标不存在则新建并赋值为num若已存在则在原值上累加packages/performance/src/resources/trace.ts。累加结果同样会取整。测试验证incrementMetric(cacheHits, 200)后getMetric为 200再incrementMetric(cacheHits, 400)后为 600传入浮点400.38结果为 600向下取整传入负浮点-230.38结果为 -31packages/performance/src/resources/trace.test.ts。5.2 putMetric()直接设置putMetric(metricName: string, num: number): void;无论指标是否存在都将其设为num覆盖语义。值经convertMetricValueToInteger向下取整为整数若有小数部分会在控制台输出提示日志packages/performance/src/utils/metric_utils.ts。测试验证putMetric(timelapse, 200.48)结果为 200packages/performance/src/resources/trace.test.ts。传入undefined会被归一为 0numAsInteger ?? 0。5.3 getMetric()读取getMetric(metricName: string): number;实现为return this.counters[counter] || 0packages/performance/src/resources/trace.ts因此指标不存在时返回 0与接口文档描述一致。5.4 指标命名规则重要约束putMetric/incrementMetric会调用isValidMetricName做合法性校验packages/performance/src/utils/metric_utils.ts名称长度必须为1100 个字符名称不能以下划线_开头——_前缀是自动采集指标_fp、_fcp、_fid、_lcp、_cls、_inp等的保留位唯一的例外自动页面加载 Trace名称以_wt_开头内部允许使用上述 OOB 指标名。校验失败会抛出Custom metric name {name} is invalidpackages/performance/src/utils/errors.ts。测试用例确认incrementMetric(_invalidMetric, 1)、putMetric(_invalidMetric, 1)、putMetric(_fid, 1)都会抛错packages/performance/src/resources/trace.test.ts。const t trace(getPerformance(), feed-scroll); t.putMetric(visibleItems, 12); t.incrementMetric(likes); // 相当于 1 t.incrementMetric(likes, 2); // 累加 2 t.putMetric(scrollDepth, 84.7); // 实际记录为 84 console.log(t.getMetric(likes)); // 3 console.log(t.getMetric(nope)); // 0不存在六、自定义属性AttributesputAttribute / getAttribute / removeAttribute / getAttributes自定义属性用于给 Trace 附加上下文标签字符串键值对例如用户分层、实验组、错误类型方便在 Firebase 控制台按维度聚合分析。6.1 四个方法putAttribute(attr: string, value: string): void; // 设置/覆盖 getAttribute(attr: string): string | undefined; // 读取不存在返回 undefined removeAttribute(attr: string): void; // 删除不存在则静默返回 getAttributes(): { [key: string]: string }; // 返回全部属性浅拷贝实现细节packages/performance/src/resources/trace.tsputAttribute先分别校验名称与值两者都合法才写入名称不合法抛Attribute name {name} is invalid.值不合法抛Attribute value {value} is invalid.packages/performance/src/utils/errors.ts。removeAttribute对不存在的属性直接return不会抛错。getAttributes()返回内部 map 的展开副本避免外部修改污染内部状态。对应测试packages/performance/src/resources/trace.test.ts验证了同名属性可覆盖、非法名称_invalidAttribute抛错、超过 100 字符的值抛错、删除不存在的属性不抛错、删除后其他属性保留。6.2 属性命名与取值约束校验逻辑集中在 packages/performance/src/utils/attributes_utils.ts名称长度140 字符名称格式必须以字母开头后跟字母、数字或下划线正则^[a-zA-Z]\w*$保留前缀不能以firebase_、google_、ga_开头值长度1100 字符MAX_ATTRIBUTE_VALUE_LENGTH 100空值非法。const t trace(getPerformance(), video-playback); t.putAttribute(videoId, abc123); // 合法 t.putAttribute(quality, hd); t.getAttribute(videoId); // abc123 t.getAttributes(); // { videoId: abc123, quality: hd } t.removeAttribute(quality); // 非法示例均会抛错 // t.putAttribute(firebase_tier, x); // 保留前缀 // t.putAttribute(_level, x); // 下划线开头、非字母开头 // t.putAttribute(name, ); // 空值 // t.putAttribute(name, x.repeat(101));// 超过 100 字符七、底层上报链路Trace 数据如何被发送自定义 Trace 在stop()或record()时调用logTrace(this)上报链路为 packages/performance/src/services/perf_logger.ts包含多级开关采集开关自动 TraceisAuto受instrumentationEnabled控制自定义 Trace 受dataCollectionEnabled控制两者默认均为true见 packages/performance/src/services/settings_service.ts任一被关闭则直接跳过。环境开关Api.getInstance().requiredApisAvailable()要求浏览器支持 Fetch、Promise 且 Cookie 可用。初始化等待若 Performance 尚未完成初始化日志会挂起等初始化 Promise 完成后补发——这意味着自定义 Trace 可以在 SDK 初始化前创建并记录。发送前过滤sendTraceLog会再次检查loggingEnabled默认false由 Remote Config 下发与logTraceAfterSampling采样开关采样率tracesSamplingRate默认 1100% 采样。也就是说Trace 的上报最终受 Firebase 后台 Remote Config 的采样与开关控制。序列化格式serializeTracepackages/performance/src/services/perf_logger.ts生成的TraceMetric载荷包含{ name: checkout-step-1, is_auto: false, client_start_time_us: 1700000000000000, duration_us: 352000, counters: { cacheHits: 3 }, custom_attributes: { result: success } }并附带应用信息google_app_id、app_instance_id、SDK 版本、页面 URL、Service Worker 状态、可见性状态、网络连接类型等最终通过 transport 服务批量发送。八、错误处理速查Trace相关异常均由ErrorFactory统一创建packages/performance/src/utils/errors.ts常见错误及触发条件错误信息触发条件Trace {name} was started before.对已 start 的 Trace 再次调用start()Trace {name} is not running.在未 start 或已 stop 的状态调用stop()Trace {name} startTime should be positive.record()的startTime 0Trace {name} duration should be positive.record()的duration 0Attribute name {name} is invalid.属性名非法长度/格式/保留前缀Attribute value {value} is invalid.属性值为空或超过 100 字符Custom metric name {name} is invalid指标名非法空/超长/_前缀九、实战组合示例以下是一个将计时、指标、属性与直接记录结合使用的完整示例覆盖本文介绍的全部 APIimport { getPerformance, trace, PerformanceTrace } from firebase/performance; const perf getPerformance(); // 1) 计时模型测量图片列表加载 const loadTrace: PerformanceTrace trace(perf, image-list-load); loadTrace.start(); loadTrace.putAttribute(listSource, recommendation); fetch(/api/images) .then(res res.json()) .then(images { loadTrace.putMetric(imageCount, images.length); loadTrace.incrementMetric(apiCalls); loadTrace.stop(); }) .catch(() { loadTrace.putAttribute(listSource, error); loadTrace.stop(); }); // 2) 直接记录模型上报 SDK 加载前的早期耗时 trace(perf, pre-sdk).record(performance.timeOrigin, 120, { metrics: { scriptSize: 48 }, attributes: { stage: boot } });十、总结与进一步阅读PerformanceTrace是 Firebase Performance Web SDK 中自定义可观测能力的入口start/stop适合围绕真实代码路径计时record适合上报无法现场测量的历史耗时指标与属性提供结构化的聚合维度但必须遵守命名与长度约束指标 1100 字符且不能以_开头属性名 140 字符且以字母开头、属性值 1100 字符底层通过 User Timing API 计算时长经多级开关与采样后以微秒精度的 JSON 载荷上报。想深入了解可继续阅读仓库内的以下文件接口定义packages/performance/src/public_types.tsTrace核心实现packages/performance/src/resources/trace.ts模块入口与trace()工厂函数packages/performance/src/index.ts属性/指标校验规则packages/performance/src/utils/attributes_utils.ts、packages/performance/src/utils/metric_utils.ts上报链路与序列化packages/performance/src/services/perf_logger.ts行为验证测试packages/performance/src/resources/trace.test.ts配套模块级 API 文档docs-devsite/performance.md赞分享开发工具后端【免费下载链接】firebase-js-sdkFirebase Javascript SDK项目地址https://gitcode.com/gh_mirrors/fi/firebase-js-sdk点击查看免费下载相关推荐Firebase自定义追踪点深度解析与实战指南Firebase自定义追踪点深度解析与实战指南 在移动应用开发中精准的用户行为追踪是产品优化的关键。Firebase Analytics 提供了强大的自定义移动开发后端Firebase JS SDK 的 LoadBundleTaskProgress 接口深度解析Cloud Firestore Bundle 加载进度跟踪实战Firebase JS SDK 的 LoadBundleTaskProgress 接口深度解析Cloud Firestore Bundle 加载进度跟踪实战开发工具后端Firebase JS SDK App Check 自定义 ProviderCustomProvider深度解析与实战指南Firebase JS SDK App Check 自定义 ProviderCustomProvider深度解析与实战指南 导读 Firebase App开发工具后端上一篇Transformers Sam3TrackerVideo 实战面向视频的可提示对象分割与追踪下一篇Nox_DPOv3模型详解基于DPO技术的革命性文本生成模型全面解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考