区块链DeFi前端移动开发【免费下载链接】interface Open source interfaces for the Uniswap protocol项目地址https://gitcode.com/gh_mirrors/in/interface点击查看免费下载本文系统讲解 Uniswap interface 仓库apps/mobile/.maestro/scripts/performance中一套完整的 Maestro E2E 性能追踪方案它用 TypeScript 编写埋点脚本经 esbuild 编译为 GraalJS 兼容的 IIFE 包在 Maestro 测试流程中以runScript注入采集 flow / sub-flow / 单步 UI 操作三类耗时指标最终面向本地、DeviceCloud 与 Maestro Cloud 三种运行环境分别通过控制台日志抽取或内存缓冲直接上传到 Datadog。读完本文你将掌握这套脚本的目录职责、编译管线、Maestro 全局变量约定、YAML 接入范式、指标格式以及故障排查方法并可直接在自己的 Maestro E2E 项目中复刻这套测试即性能观测的实践。一、方案定位与整体架构1.1 为什么在测试层做性能埋点这套体系的核心决策是对 Maestro E2E 测试文件本身做插桩而不是修改应用代码。理由集中在 LOCAL_INSTRUMENTATION_GUIDE.md 的 Design Rationale 部分非侵入应用代码零改动、零性能开销不存在把埋点代码误带上线的风险贴近用户体验测量的是真实用户流程tap 到响应的时长而非单次渲染帧耗时平台无关同一套脚本在 iOS / Android 模拟器上行为一致受限于 Maestro 能力Maestro 只能在测试动作之间执行脚本无法注入正在运行的 React Native 应用进程。与之对比的备选方案React NativePerformanceObserver、原生 Instruments/System Trace、Maestro 内建计时、视频逐帧分析、网络代理插桩要么要求改应用代码、只覆盖渲染性能要么平台耦合、开销大均被放弃。1.2 覆盖的三种运行环境环境指标收集方式上报链路本地开发脚本向控制台输出MAESTRO_METRIC:前缀日志extract-metrics.js抽取 →process-metrics.ts补全 →submit-metrics.js上传DeviceCloudCI同上控制台日志同上附加 CI 标签Maestro Cloud指标累积在output.METRICS_BUFFER内存缓冲每条 flow 结束时由upload-metrics.js直接 HTTP POST 到 DatadogLOCAL_INSTRUMENTATION_GUIDE.md中用一张 ASCII 架构图完整描述了这一双链路上方是埋点脚本串init-tracking → start-flow → track-action / start-sub-flow → end-sub-flow → end-flow中间按环境分流最终统一汇入带env / flow_name / platform / CI metadata标签的 Datadog。二、目录结构与脚本职责2.1 源文件src/目录树如下与 README 的 Architecture 一节对应apps/mobile/.maestro/scripts/performance/ ├── src/ │ ├── actions/ # 被 Maestro YAML flow 直接调用的动作脚本 │ │ ├── init-tracking.ts │ │ ├── start-flow.ts │ │ ├── end-flow.ts │ │ ├── start-sub-flow.ts │ │ ├── end-sub-flow.ts │ │ └── track-action.ts │ ├── utils/ # 共享工具函数 │ │ ├── bufferMetric.ts │ │ ├── emitMetric.ts │ │ ├── extract-metrics.ts │ │ ├── getTimestamp.ts │ │ ├── metricCreators.ts │ │ ├── process-metrics.ts │ │ └── validateEnv.ts │ ├── types.ts # 指标类型定义 │ └── globals.d.ts # Maestro 运行时全局类型声明 ├── dist/ # 编译产物GraalJS 兼容 JS ├── tsconfig.json ├── BUILD.md ├── LOCAL_INSTRUMENTATION_GUIDE.md ├── README.md ├── submit-local.sh ├── submit-metrics.js └── upload-metrics.js2.2 六个动作脚本的职责脚本职责产生的输出变量发出的指标init-tracking.ts初始化追踪会话CURRENT_FLOW_NAMEunknown、CURRENT_TEST_RUN_ID时间戳、CURRENT_STEP_NUMBER0、CURRENT_PLATFORM来自PLATFORM环境变量、METRICS_BUFFER[]无start-flow.ts标记 flow 开始CURRENT_FLOW_NAME、FLOW_START_TIMEflow_startend-flow.ts标记 flow 结束并计算总耗时—flow_end含durationstart-sub-flow.ts标记子流程共享 flow开始保留父 flow 上下文PARENT_FLOW_NAME、SUB_FLOW_START_TIMEsub_flow_startend-sub-flow.ts结束子流程、恢复父 flow 上下文清理上述临时变量sub_flow_endtrack-action.ts对单个 UI 操作计时每个动作调用两次start/endCURRENT_STEP_NUMBER自增、{action}_{target}_START临时时间戳action2.3 共享工具函数getTimestamp.ts基于Date.now()提供getTimestamp()/getTimestampString()/getElapsedTime()/formatTimestamp()。注释明确说明Date.now()为 GraalJS 原生支持validateEnv.ts在 GraalJS 中环境变量以全局变量形式暴露而非 Node 的process.env故通过globalThis[name]安全读取并提供getEnvVar带默认值、requireEnvVar缺失抛错、hasEnvVar、getMaestroEnvVarsemitMetric.ts将指标以MAESTRO_METRIC:${JSON.stringify(metric)}前缀输出到控制台供本地抽取解析bufferMetric.ts把指标追加进output.METRICS_BUFFERJSON 字符串数组供 Maestro Cloud 上传解析失败时仅打日志不中断流程metricCreators.ts五种指标对象的工厂函数createFlowStartMetric/createFlowEndMetric/createSubFlowStartMetric/createSubFlowEndMetric/createActionMetric。三、指标类型定义types.tstypes.ts 定义了统一的基础结构与五种具体指标interface BaseMetric { timestamp: number platform: string testRunId: string } interface FlowStartMetric extends BaseMetric { event: flow_start flowName: string } interface FlowEndMetric extends BaseMetric { event: flow_end flowName: string duration: number status: success | failure } interface SubFlowStartMetric extends BaseMetric { event: sub_flow_start parentFlowName: string subFlowName: string } interface SubFlowEndMetric extends BaseMetric { event: sub_flow_end parentFlowName: string subFlowName: string duration: number status: success | failure } interface ActionMetric extends BaseMetric { type: action flowName: string actionType: string actionTarget: string stepNumber: number duration: number status: success | failure } type Metric FlowStartMetric | FlowEndMetric | SubFlowStartMetric | SubFlowEndMetric | ActionMetric三个核心约定值得注意testRunId贯穿全程由init-tracking.ts用时间戳生成唯一 IDgetTimestampString()作为关联同一次运行内所有指标的键duration计算均以毫秒为单位由end时getTimestamp() - startTime得出timestamp字段在 action 指标中记录的是动作开始时间见track-action.ts中timestamp: startTimeMaestroOutput接口output对象内键均为字符串CURRENT_FLOW_NAME、CURRENT_TEST_RUN_ID、CURRENT_STEP_NUMBER、CURRENT_PLATFORM、METRICS_BUFFER、FLOW_START_TIME?、PARENT_FLOW_NAME?、SUB_FLOW_START_TIME?以及[key: string]允许动态存储各动作的开始时间这是脚本间共享状态的关键载体。四、构建系统从 TypeScript 到 GraalJS4.1 构建命令README.md 与 BUILD.md 共同描述了构建管线。在 mobile 应用中构建通过 Nx 任务e2e:build-js触发见 project.json# 安装依赖 npm install # 构建mobile 项目中等价于bun e2e:build-js bun run .maestro/scripts/tooling/buildPerformanceScripts.ts # 本地交互式运行含构建 bun e2e:interactive4.2 esbuild 双目标构建buildPerformanceScripts.ts 是构建入口它会递归发现src/actions/与src/utils/下所有.ts文件并按用途拆成两组不同的 esbuild 配置GraalJS 动作脚本actions/及名字含upload/submit的 utilstarget: es2015README 与 BUILD.md 中亦提及 ES2020 为 GraalJS 支持范围实际编译目标取更保守的 es2015format: iife立即执行函数包裹保证隔离platform: neutral不依赖 Node.js 或浏览器假设bundle: true且external: []把所有依赖内联进单文件minify: falsesourcemap: true保留可读性并便于调试。Node.js 脚本名字含extract或process-metricsplatform: node、target: node14、format: cjsexternal: [fs, path, util, child_process, readline]产物自动添加#!/usr/bin/env nodeshebang 并chmod 755。4.3 编译产物结构构建输出到dist/dist/ ├── actions/ │ ├── init-tracking.js │ ├── start-flow.js │ ├── end-flow.js │ ├── track-action.js │ ├── start-sub-flow.js │ └── end-sub-flow.js └── utils/ ├── extract-metrics.js ├── process-metrics.js └── ...每份 JS 均附带.js.map源映射。新增脚本的流程很简单在src/actions/或src/utils/新建.ts文件重新运行bun e2e:build-js即可——构建脚本会自动发现并打包。4.4 GraalJS 兼容性边界README 明确列出支持与限制这也是排查编译错误的总纲支持不支持ES2020 语法async/await、可选链等ES modulesimport/exportJSON 操作JSON.parse/JSON.stringifyNode.js APIDate / Math 对象npm 包console 日志Maestro 提供之外的全局变量全局变量globalThis读取环境变量—五、Maestro 集成全局变量与 YAML 接入5.1 运行时全局变量globals.d.ts 声明了 Maestro 在运行时注入的全局output脚本间持久化状态对象与types.ts的MaestroOutput一致FLOW_NAME、SUB_FLOW_NAME、ACTION、TARGET由 YAML 中runScript.env传入的字符串PHASEstart | end标记动作边界consoleGraalJS 提供log/error。注意与 Node 环境的差异环境变量直接作为全局变量存在不能使用process.envHTTP 请求必须用 Maestro 提供的httpAPI而不是XMLHttpRequest见upload-metrics.js中http.post(...)的调用。5.2 YAML 接入范式README 示例README 给出的最小接入模板- runScript: file: .maestro/scripts/performance/dist/actions/init-tracking.js - runScript: file: .maestro/scripts/performance/dist/actions/start-flow.js env: FLOW_NAME: swap - tapOn: Swap Button - runScript: file: .maestro/scripts/performance/dist/actions/track-action.js env: ACTION: tap TARGET: Swap Button PHASE: end - runScript: file: .maestro/scripts/performance/dist/actions/end-flow.js env: FLOW_NAME: swap5.3 仓库真实流程示例swap-base.yamlswap-base.yaml 是仓库中实际落地的完整范例展示了更多细节appId: com.uniswap.mobile.dev jsEngine: graaljs env: E2E_RECOVERY_PHRASE: ${E2E_RECOVERY_PHRASE} DATADOG_API_KEY: ${DATADOG_API_KEY} PLATFORM: ${PLATFORM} GITHUB_REF_NAME: ${GITHUB_REF_NAME} GITHUB_SHA: ${GITHUB_SHA} GITHUB_RUN_ID: ${GITHUB_RUN_ID} --- # 1) 初始化追踪 - runScript: file: ../../scripts/performance/dist/actions/init-tracking.js env: PLATFORM: ${PLATFORM} # 2) 开始 flow 计时包含前置 setup 时间 - runScript: file: ../../scripts/performance/dist/actions/start-flow.js env: FLOW_NAME: swap # 3) 前置共享 flow内部自动作为 sub-flow 追踪 - runFlow: ../../shared-flows/start.yaml - runFlow: ../../shared-flows/recover-fast.yaml # 4) 单个动作start / 动作 / end 三段式 - runScript: file: ../../scripts/performance/dist/actions/track-action.js env: ACTION: tapOn TARGET: Swap PHASE: start - tapOn: id: ${output.testIds.Swap} - runScript: file: ../../scripts/performance/dist/actions/track-action.js env: ACTION: tapOn TARGET: Swap PHASE: end # ... 对 ChooseOutputToken、inputText、ReviewSwap、ConfirmSwap 等重复上述模式 ... # 5) 结束 flow 追踪 - runScript: file: ../../scripts/performance/dist/actions/end-flow.js # 6) Maestro Cloud 场景下上传指标到 Datadog - runScript: file: ../../scripts/performance/upload-metrics.js env: DATADOG_API_KEY: ${DATADOG_API_KEY} GITHUB_REF_NAME: ${GITHUB_REF_NAME} GITHUB_SHA: ${GITHUB_SHA} GITHUB_RUN_ID: ${GITHUB_RUN_ID} ENVIRONMENT: maestro_cloud可观察到的实战要点jsEngine: graaljs显式声明运行引擎${output.testIds.*}test id 由e2e:generate-ids任务generateTestIds.ts预生成YAML 中通过 Maestro 模板变量引用动作计时采用 start/end 成对包裹track-action.js在start阶段把{ACTION}_{TARGET}_START写入outputend阶段读取并计算耗时、自增CURRENT_STEP_NUMBER、发出action指标后delete临时键防止内存累积见 track-action.ts共享 flow 不要手动包裹runFlow内部自带 sub-flow 追踪见下节避免重复指标类似模式同样应用于 deeplink-comprehensive.yaml 等其余十余个 flow。5.4 Sub-flow 追踪与父上下文恢复start-sub-flow.ts在进入共享 flow 前把CURRENT_FLOW_NAME保存为PARENT_FLOW_NAME并记录SUB_FLOW_START_TIMEend-sub-flow.ts计算完耗时后恢复父 flow 上下文output.CURRENT_FLOW_NAME output.PARENT_FLOW_NAME并清理临时变量从而支持父 flow 计时不受子流程污染、层次化性能分析。六、指标消费链路三条路径详解6.1 本地 / DeviceCloud 路径README 与LOCAL_INSTRUMENTATION_GUIDE.md给出的完整链路测试执行Maestro 运行已插桩的 flow指标输出各脚本以MAESTRO_METRIC:前缀写控制台抽取extract-metrics.ts 递归扫描日志目录默认$HOME/.maestro/tests逐行查找MAESTRO_METRIC:前缀用花括号计数法从混合日志中精确切出 JSON 对象并去重输出为 NDJSON.jsonl补全process-metrics.ts 读入 NDJSON为未收到flow_end的 flow 生成合成flow_end事件status: failure、synthetic: true保证失败用例也有完整指标时长取该testRunId下最后一条指标的时间戳与flow_start之差上报submit-metrics.js 读取处理后的 JSONL构建 Datadog series 并 HTTPS POST 到https://api.datadoghq.com/api/v1/series。对应 Nx 任务见 project.jsonexport DATADOG_API_KEYyour-key-here bun e2e:local:process-metrics # extract-metrics submit-metrics bun e2e:local:extract-metrics # 仅抽取 bun e2e:local:submit-metrics # 仅上报 bun e2e:clear-logs # 清空 ~/.maestro/testssubmit-local.sh是本地上报包装脚本未设置DATADOG_API_KEY时自动切到--dry-run只打印不上报并自动追加env:local,source:manual,branch:当前分支标签。6.2 Maestro Cloud 路径upload-metrics.js以 runScript 形式在每个 flow 末尾执行从output.METRICS_BUFFER解析全部指标convertToDatadogFormat将原始指标转换为 Datadog series含env:、test_run_id:、platform:基础标签以及可选的branch:/commit:/github_run_id:CI 标签以每批 100 条分块发送规避 Datadog 5MB 请求上限带最多 3 次指数退避重试1s / 2s / 4s使用 Maestro 的http.postAPIDD-API-KEY放在请求头成功判定为 HTTP 202DRY_RUNtrue时仅打印载荷上传成功后清空METRICS_BUFFER。6.3 上报到 Datadog 的指标与标签Datadog 指标名类型标签maestro.e2e.flow.durationgaugeflow_name、platform、status、env、test_run_id、CI 标签maestro.e2e.flow.countcount同上maestro.e2e.action.durationgaugeaction_type、action_target、step_number、flow_name、statusmaestro.e2e.sub_flow.durationgaugeparent_flow_name、sub_flow_name、status七、开发工作流与最佳实践7.1 标准开发流程在src/中编辑 TypeScript 文件运行bun e2e:build-js或npm run build/build:watch编译到 GraalJS用 Maestro 本地验证bun e2e:interactive源码与dist/产物一并提交。7.2 DO / DONT 清单应当每个 flow 开头先执行init-tracking.js只追踪有意义的用户操作tap、input、swipe共享 flow 让其在内部自行追踪使用描述性的TARGET命名定期用bun e2e:clear-logs清理日志。禁止对共享 flow 外层再包track-action会产生重复指标见LOCAL_INSTRUMENTATION_GUIDE.md中正确/错误实现对比追踪每一个细微交互忘记在流程末尾调用end-flow.js本地与 CI 指标混用而无明确标签区分。7.3 故障排查要点README Troubleshooting编译错误确认源文件无 ES module 语法import/export仅用于类型或将被 esbuild 消除检查是否误用了 Node.js 专属 API验证 TypeScript 版本与tsconfig.jsontarget: ES2020、module: node16、strict: true兼容。运行时错误查看 Maestro 控制台输出中MAESTRO_METRIC:行与脚本自身console.log调试信息确认output与各环境变量已正确注入保证脚本调用顺序init-tracking→start-flow→ ... →end-flow→upload-metrics。性能问题最小化 JSON 操作bufferMetric.ts每次 push 都会整体序列化缓冲过大时成本上升避免大规模字符串拼接保持METRICS_BUFFER规模合理必要时调整upload-metrics.js的BATCH_SIZE。八、运行时环境自动检测与合成事件8.1 环境检测动作脚本通过检查output.METRICS_BUFFER是否已定义来区分模式见LOCAL_INSTRUMENTATION_GUIDE.mdif (typeof output ! undefined output.METRICS_BUFFER ! undefined) { // Maestro Cloud 模式追加到缓冲 let buffer JSON.parse(output.METRICS_BUFFER || []) buffer.push(metric) output.METRICS_BUFFER JSON.stringify(buffer) } // 始终输出控制台日志以兼容本地链路 console.log(MAESTRO_METRIC: JSON.stringify(metric))实际上所有动作脚本都会同时调用emitMetric控制台与bufferMetric缓冲双写保证两条链路互不依赖。8.2 合成flow_end事件process-metrics.ts的第二遍扫描会针对每个只有flow_start、没有对应flow_end的testRunId生成合成结束事件以该 flow 最后一条指标的timestamp作为结束时刻status标记为failure附加synthetic: true标志便于后续区分真实数据该机制仅本地 / DeviceCloud 需要Maestro Cloud 下每个 flow 自己负责完成上报无需补全。结语这套performance埋点体系把性能观测从应用层下沉到测试层用一套 TypeScript 源码 esbuild 双目标编译 Maestro 全局变量约定同时覆盖本地、DeviceCloud 与 Maestro Cloud 三种运行环境最终统一汇入 Datadog 形成maestro.e2e.*系列指标。无论是想要理解 Uniswap 移动端如何做 E2E 性能回归监控还是希望在自己的 Maestro 测试套件中复刻同样的插桩模式本文所述的目录结构、构建管线、YAML 接入范式与双链路上报机制都可以直接作为落地参考。赞分享区块链DeFi前端移动开发【免费下载链接】interface Open source interfaces for the Uniswap protocol项目地址https://gitcode.com/gh_mirrors/in/interface点击查看免费下载相关推荐Uniswap Mobile 的 Maestro E2E 性能插桩指南从本地到 Maestro Cloud 的全链路指标采集与 Datadog 上报Uniswap Mobile 的 Maestro E2E 性能插桩指南从本地到 Maestro Cloud 的全链路指标采集与 Datadog 上报 本篇技术区块链DeFi前端移动开发Uniswap Mobile 的 Maestro 性能脚本 GraalJS 构建指南esbuild 打包流程与实战配置Uniswap Mobile 的 Maestro 性能脚本 GraalJS 构建指南esbuild 打包流程与实战配置 本篇技术指南以 apps/mobile区块链DeFi前端移动开发Omi 移动端 Maestro E2E 功能测试套件从 Flow 编写到自动化报告的完整实战指南Omi 移动端 Maestro E2E 功能测试套件从 Flow 编写到自动化报告的完整实战指南 本文以开源仓库 FriendOmi中 app/.maes人工智能AI 应用语音移动开发后端桌面应用智能硬件MCP 服务创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考