资讯动态

Perfetto UI 深度链接(Deep Linking)实战:URL 直开、postMessage 传参与 UI 状态定制

发布时间:2026/9/18 1:36:34 来源:尧图企业网站定制
Perfetto UI 深度链接Deep Linking实战URL 直开、postMessage 传参与 UI 状态定制【免费下载链接】perfettoProduction-grade client-side tracing, profiling, and analysis for complex software systems.项目地址: https://gitcode.com/GitHub_Trending/pe/perfetto本文介绍如何让 Perfetto UI 打开托管在外部服务器上的 trace从而将 Perfetto UI 集成进自建仪表盘Dashboard并实现类似Open with Perfetto UI的功能。读完本文你将掌握两种打开方式——面向公开 trace 的直接 URL 链接最简单与面向鉴权、分享等场景的postMessage 全控制方式并能通过 URL 参数定制打开 trace 后的 UI 初始状态缩放区域、选中事件、自动查询、启动命令同时结合仓库源码理解其底层实现与安全模型。两种打开方式总览Perfetto UI线上版为https://ui.perfetto.dev源码位于 ui/ 目录是纯客户端应用支持两种外部集成路径方式适用场景核心机制Option 1直接 URLtrace 公开可访问、无需鉴权在 URL 查询串中携带url参数UI 直接 GET 拉取Option 2postMessage需要鉴权、自定义分享链接、隐藏 trace 标题等调用方先window.open()打开 UI再通过postMessage()把 trace 二进制数据推送给 UI两种方式都支持通过 URL fragment 参数控制 UI 初始状态详见下文「用 URL 参数定制 UI 状态」。无论哪种方式trace 数据都只在浏览器内存中处理不会上传到 Perfetto 的任何服务器。Option 1直接 URL 打开公开 trace如果 trace 通过 HTTPS 公开可访问可以直接用url查询参数链接到它https://ui.perfetto.dev/#!/?urlhttps://example.com/path/to/trace.pftrace前置要求trace 必须通过HTTPS提供服务该 URL 必须能通过不带查询参数的简单 GET 请求直接返回 trace 内容服务器必须为 Perfetto UI 所在源设置CORS 头例如Access-Control-Allow-Origin: https://ui.perfetto.dev或宽松的Access-Control-Allow-Origin: *。这是公开托管 trace 的最简单方案无需任何自建代码。从源码看url参数在 UI 的路由 schema 中声明route_schema.ts 中url: z.string().optional()注释明确说明它用于从 Cloud Storage 或本地服务器抓取 tracetools/record_android_trace等工具也依赖该参数把 trace 直接投递给 UI。局限性不支持鉴权trace 必须公开可访问不支持自定义分享链接无法控制 UI 中显示的 trace 标题。如果你需要以上任一能力请改用 Option 2postMessage 全控制方式。Option 2使用 postMessage 实现全控制对于需要鉴权、自定义分享 URL 或其他高级特性的 trace使用 postMessage 方案。这需要你在自己控制的基础设施上运行一些 JavaScript 代码。整个协议由 post_message_handler.ts 实现共分三步。第 1 步通过 window.open 打开 ui.perfetto.dev源仪表盘负责定位 trace、做 ACL 检查、OAuth 鉴权等的一方创建一个新标签页var handle window.open(https://ui.perfetto.dev);该handle允许你在仪表盘与 Perfetto UI 之间用postMessage()做双向通信。第 2 步用 PING/PONG 等待 UI 就绪window.open()建立的通信信道不缓冲消息如果在打开的页面注册onmessage监听器之前发送消息消息会被直接丢弃。为避免这个竞态条件请使用 PING/PONG 协议持续发送PING直到打开的窗口回复PONG再继续。在源码 post_message_handler.ts 中可以看到UI 一旦收到data PING立即用windowSource.postMessage(PONG, *)回复。这里使用*作为目标源是刻意为之跨域隔离场景下messageEvent.origin会显示为null而 PONG 不泄露任何敏感信息即便发错源也无妨。第 3 步投递 trace 数据握手完成后向 Perfetto UI 窗口发送一条消息。消息体是一个只含一个perfetto键的 JavaScript 对象{ perfetto: { buffer: ArrayBuffer; title: string; fileName?: string; // 可选 url?: string; // 可选 appStateHash?: string // 可选 } }对照源码 post_message_handler.ts 中的PostedTrace接口各属性语义如下bufferArrayBuffer包含原始 trace 数据的二进制内容。通常由你从前端fetch()后端接口得到。源码允许发送方直接传Uint8Array等视图ArrayBuffer.isView(buffer)也会被接受并在sanitizePostedTrace()边界处统一归一化为纯ArrayBuffer见 post_message_handler.ts。title人类可读字符串显示为 UI 中该 trace 的标题。多标签页打开多个 trace 时帮助用户区分。fileName可选用户在 Perfetto UI 中下载 trace 时建议使用的文件名省略时使用通用名。url可选用于分享 trace 的 URL详见下文「分享 trace 与 UI 状态」。appStateHash可选分享时用于恢复 UI 状态的哈希详见下文。额外字段源码级补充除文档列出的五个字段外PostedTrace还支持几个实用扩展字段shareable/downloadable是否允许 UI 将 trace 分享上传为 permalink或下载到本地。两者默认均为false——通过 postMessage 推入的 trace 默认仅存在于本地除非发送方显式打开开关localOnly兼容旧版字段早于shareable/downloadable拆分时代的发送方可能传它。localOnly: false等价于同时打开分享与下载其余取值或缺省保持本地-only显式的shareable/downloadable优先于该旧字段keepApiOpen为true时保留消息监听器见postMessageHandler中window.removeEventListener的逻辑允许同一页面后续多次投递 trace缺省会在收到第一条 trace 后移除监听避免调用方收到多次 PONG 而重复投递历史问题 b/182502595pluginArgs按插件 ID 组织的键值对插件可在onTraceLoad()中读取用于把仪表盘的额外数据如 APC 式看板的附加信息materialize 到 track 上。消息解析入口parsePostedTrace()post_message_handler.ts还兼容另一种更简化的调用方式直接把裸ArrayBuffer或其视图作为data发送此时 UI 会以标题External trace打开且shareable/downloadable默认关闭。分享 trace 与 UI 状态通过postMessage打开的 tracePerfetto不会把 trace 存储到任何服务器——因为这样做可能违反 trace 原始来源的留存策略trace 不会上传到任何地方。因此你必须提供一个经由自己基础设施直达同一份 trace 的 URL这个 URL 应能自动重新打开 Perfetto 并再次用 postMessage 投递同一份 trace。url与appStateHash两个属性配合使用让用户可以分享一个链接他人打开后不仅能恢复 trace还能恢复到相同的 UI 状态如缩放级别、选中的事件。当用户在 Perfetto UI 中点击Share按钮时UI 会查看你打开 trace 时提供的url。如果这个url包含特殊占位符perfettoStateHashPlaceholderPerfetto 会保存当前 UI 状态并生成一个唯一哈希用该哈希替换url中的perfettoStateHashPlaceholder把最终 URL 展示给用户分享。例如如果你提供的url是https://my-dashboard.com/trace?id1234stateperfettoStateHashPlaceholderPerfetto 可能生成这样的可分享链接https://my-dashboard.com/trace?id1234statea1b2c3d4当另一个用户打开该分享链接时你的应用应当从 URL 中提取状态哈希示例中的a1b2c3d4照常通过postMessage投递 tracebuffer但这次把appStateHash属性设为提取到的哈希。Perfetto 随后会加载 trace 并自动恢复与该哈希关联的 UI 状态。行为边界如果省略url属性分享功能会被禁用如果url中没有perfettoStateHashPlaceholdertrace 仍可分享但 UI 状态不会被保存。源码层面占位符逻辑在 trace_share_utils.ts 中STATE_HASH_PLACEHOLDER常量即perfettoStateHashPlaceholder分享时仅上传 UI 状态生成哈希createPermalink再用traceUrl.replace(STATE_HASH_PLACEHOLDER, hash)注入回你的 URL——这样发送方提供的 URL可能是带鉴权或非公开的得以原样保留。接收侧appStateHash在 post_message_handler.ts 中被校验为合法的 40 位十六进制 GCS 文件名后从https://storage.googleapis.com/bucket/hash拉取序列化状态并经parseAppState解析最终与 trace 一起交给AppImpl.instance.openTraceFromBuffer()。常见陷阱弹窗拦截。许多浏览器会拦截window.open()请求并提示用户允许弹窗常见原因window.open()不是由用户手势user gesture发起的用户手势与window.open()之间间隔过久。如果 trace 文件较大fetch()可能耗时超过用户手势的有效窗口表现为window.open()返回null。此时最佳做法是展示另一个可点击元素把抓取到的 traceArrayBuffer绑定到新的 onclick 处理器上上文示例代码正是这样做的。另外浏览器对用户手势超时阈值是变化的取决于网站参与度评分即用户此前访问该页面的频次因此测试时常见第一次使用看到弹窗拦截、之后不再出现的现象。file:// 限制。由于浏览器对file://URL 的安全限制该方案无法在file://页面下工作。COOP 头。源网站不能以Cross-Origin-Opener-Policy: same-origin响应头提供服务否则跨窗口通信会被浏览器切断可参考 perfetto 仓库 issue #525 的相关讨论。投递的 trace 去了哪里Perfetto UI 是纯客户端应用不依赖任何服务端交互。通过postMessage()推入的 trace 只保留在浏览器内存/缓存中不会发送给任何服务器。这也是它能够承载带鉴权、受留存策略约束的 trace 的根本原因。信任模型与安全确认源码还揭示了文档之外的信任机制isTrustedOrigin()post_message_handler.ts会检查消息来源——https://chrometto.googleplex.com、https://uma.googleplex.com、https://android-build.googleplex.com、.corp.google.com、.c.googlers.com等内部域名以及localhost/127.0.0.1等回环地址会被自动信任并直接打开 trace其余来源会弹出「Open trace?」确认对话框询问用户是否信任该来源并提供Always trust选项把来源写入 localStorage键trustedOrigins。发送方若希望被记住可参考saveUserTrustedOrigin()的存取逻辑。另外消息处理还会忽略perfettoIgnore: true的消息、Google 的 GA 调试器消息以及既非 opener 也非父窗口/被开窗口来源的消息。用 URL 参数定制 UI 状态除了打开 trace你还可以用 URL fragment 参数控制初始 UI 状态。这些参数对 Option 1直接 URL和 Option 2postMessage都有效——postMessage 方式下它们经由 route_schema.ts 声明的路由参数生效。所有参数在 UI 路由 schema 中均有定义ts、dur、tid、pid、query、visStart、visEnd、startupCommands、url、hideSidebar、mode、enablePlugins、referrer等见 route_schema.ts无效值会被静默忽略而不会破坏其他参数。缩放到 trace 的某个区域传visStart与visEnd控制初始视口取值为 SQL 表中看到的原始纳秒时间戳https://ui.perfetto.dev/#!/?visStart261191575272856visEnd261191675272856这会在大约 261192s 处打开 trace显示 100ms 宽的窗口。实现上DeeplinkQuerystring 插件 用Time.fromRaw(BigInt(...))解析这两个值并校验visStart visEnd且落在 trace 时间范围内再调用trace.timeline.panSpanIntoView(visStart, visEnd, {align: zoom})。加载时选中某个 slice传ts可选传dur。UI 会查询 slice 表找到匹配参数的 slice 并高亮。通常ts和dur足以唯一定位一个 slice。注意Perfetto刻意不支持按 slice ID 链接因为 slice ID 在不同 Perfetto 版本间不稳定。正确做法是按精确的开始时间戳与持续时间ts和dur链接这些值可通过SELECT ts, dur FROM slices WHERE id...查询得到。源码 DeeplinkQuerystring/index.ts 展示了实现细节插件以ts value有dur时追加AND dur value为条件查询slice表可通过table参数换成thread_state等含ts/dur/id列的表找到id后调用trace.selection.selectSqlEvent(table, id, ...)完成选中并滚动到该事件。加载时自动执行查询把查询语句放进query参数即可加载完成后会自动打开查询结果标签页https://ui.perfetto.dev/#!/?urlencoded-trace-urlqueryselect%20Hello%2C%20world!%20as%20msg对应实现是在 trace 就绪后调用QueryPagePlugin.addQueryResultsTab({query, title: Deeplink Query})见 DeeplinkQuerystring/index.ts。示例可直接在浏览器尝试注意其中url参数本身经过了 URL 编码visStart visEnd 示例ts dur 示例query 示例请记住在需要处对字符串做 URL 编码。启动命令Startup Commands你还可以通过 URL 内嵌启动命令让 trace 打开时自动配置 UI 本身——非常适合仪表盘集成为用户提供预配置分析环境的场景。把启动命令放在startupCommands参数中值为 URL 编码的 JSON 数组。命令在 trace 加载完成后自动按顺序执行可用来固定 track、创建 debug track 或执行其他 UI 自动化操作// 示例固定 CPU track 并创建一个 debug track const commands [ {id: dev.perfetto.PinTracksByRegex, args: [.*CPU [0-3].*]}, { id: dev.perfetto.AddDebugSliceTrack, args: [ SELECT ts, dur, name FROM slice WHERE name LIKE %render%, Render Operations, ], }, ]; const url https://ui.perfetto.dev/#!/?startupCommands${encodeURIComponent( JSON.stringify(commands), )};启动命令使用与 UI 自动化文档 中一致的 JSON 格式区别在于作为 URL 参数时必须 URL 编码。稳定且带向后兼容保证的命令清单见 Commands Automation Reference。实用组合参考来自 ui-automation.md先CollapseTracksByRegex.*折叠全部 track再PinTracksByRegex.*CPU \\d$固定 CPU track、ExpandTracksByRegex.*freq.*展开频率 track最后用AddDebugSliceTrackWithPivot创建按进程分组的 debug track。Debug track 的 SQL 必须返回tsslice 类还需dur与namecounter 类则需value。涉及 Perfetto SQL 模块时先用RunQuery执行include perfetto module xxx再创建 debug track。其他实用路由参数结合 route_schema.ts 的声明还有几个与深度链接配合使用的参数值得注意referrer覆盖 referrer 来源标识record_android_trace等脚本用它记录 trace 来源modeembedded嵌入式模式会禁用部分 UI 功能hideSidebartrue隐藏侧边栏适合嵌入式展示enablePlugins逗号分隔的插件列表为当前会话启用指定插件table配合ts/dur指定要查询的表默认slice例如tablethread_statets39978672284068dur18995809。源码与现成工具postMessage 协议的核心实现post_message_handler.tsPING/PONG 应答、消息解析、来源信任、状态恢复、时间范围滚动等全部逻辑URL 路由参数 schemaroute_schema.ts深度链接参数缩放/选中/查询的执行插件dev.perfetto.DeeplinkQuerystring/index.ts分享占位符逻辑trace_share_utils.ts现成的集成库open-perfetto-traceopen_perfetto_trace/index.ts。这是一个独立的 JS/TS 库封装了与 ui.perfetto.dev 的完整握手流程传入一个Blob如File或 trace URL它会在当前页渲染一个带进度条的弹窗可statusDialog: false关闭fetch 完成后通过隐藏表单 POST 到ui.perfetto.dev/_open_trace/tsnewTab: true时新标签打开并透传referrer、mode、hideSidebar、ts、dur、query、visStart、visEnd等选项也支持用uiUrl覆盖默认 UI 地址用于测试。总结Perfetto UI 提供了两条成熟的深度链接集成路径url参数直开公开 trace以及基于postMessage PING/PONG 握手的全控制方案支持鉴权、自定义分享与标题。在此基础上visStart/visEnd、ts/dur、query与startupCommands等 URL 参数可以精确还原分析现场视口、选中、查询、track 布局而分享占位符perfettoStateHashPlaceholder与appStateHash则让分享即还原成为可能。所有 trace 数据始终留在客户端内存不经过 Perfetto 服务器这也是该方案能承接受 ACL 与留存策略约束的 trace 的根本前提。【免费下载链接】perfettoProduction-grade client-side tracing, profiling, and analysis for complex software systems.项目地址: https://gitcode.com/GitHub_Trending/pe/perfetto创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价