分析¶
移动端产品分析¶
apps/mobile/src/features/analytics 拥有 React Native OpenPanel 客户端、类型化事件允许列表、账户作用域操作、本地 SecureStore 偏好设置以及前台/连接事件。在创建会话之前,它会在内存中缓冲最多 100 条已清理的事件,自首条缓冲事件起持续 30 分钟。下一个账户认领此缓冲区;identify 先于按原始时间戳的有序投递。重连不会重放该缓冲区。过期、选择退出和进程退出都会丢弃它。账户变更会使先前操作作用域失效;从匿名到账户的转换保留配对作用域,以便记录其完成。移动端使用与桌面端和网站共享的现有 Openbot OpenPanel 项目中的只写客户端。
工作区命令包装器在移动端调用方处记录一次结果;对话可用性在可见的聊天视图中测量,包括缓存读取,而非来自后台广播。宿主仍然是回合生命周期事件的唯一来源。不需要更改 Team API 或数据库 schema。
只有在偏好设置加载完成后,具有移动端写入凭据的原生生产构建才会初始化客户端。UI 操作从不等待分析传输。账户/同意代次会拒绝迟到的结果;有序的身份变更会保留已接受事件的归因。最后一道 SDK 过滤器会替换属性,以移除 SDK 添加的 Android 引荐来源和路由路径。SDK 的可选持久队列和屏幕跟踪未启用。配置、事件语义和原生验证步骤见移动端 README。
网站分析¶
公共网站跟踪位于 apps/auth-api/src/lib/analytics.ts。它只在生产环境 openbot.run 主机名上运行。落地页和邀请事件携带受限的 source_platform、现有的 acquisition_source 类别以及仅包含域名的引荐来源。
被识别的 utm_source 标签优先于引荐域名。精确域名和子域名匹配会选中已知平台;URL 路径和子字符串匹配不会。未被识别的平台使用 unknown。没有任何引荐信号保留粗略的 direct 类别,因为该类别并不能证明访问者输入了地址。
文章报告自身路径,因此可以区分不同文章。safeScreenPath 和 slug 属性检查会对照 src/lib/news.ts 和 src/lib/guides.ts 注册表解析路径,因此可报告集合保持封闭:未知 slug 报告 / 并从负载中丢弃。articleFromPath 为委托的点击监听器提供相同的查找逻辑,这正是它能够跟踪文章卡片的原因;这些卡片的 href 携带 slug,无法通过其他链接使用的精确 href 允许列表匹配。页面组件调用 start 之前,主视觉选择器通过 trackDownloadSelected 报告其检测到的平台,因此一个短的有界队列会保存事件,直到客户端存在,而不是丢弃第一个事件。
landingCampaignPath 仅使用五个已列入允许列表的 utm_* 标签重建报告屏幕路径,将其小写化并限制为 64 个安全字符;所有其他参数和哈希值在构造时即被丢弃。该路径随页面加载的每个事件一起发送,而不仅仅是 screen_view,因为 OpenPanel 从创建会话的任一事件中读取活动归因,并且这两个事件是并发发送的。
数据边界见 PRIVACY.md。
rememberLandingFirstTouch 将首次访问保存在 localStorage 中(@openbot/contracts/first-touch 拥有其结构、解析器和 90 天有效期)。Web 客户端在 email/verify 时发送它,/billing/return 将它与 Checkout 会话 ID 一起发送到 POST /api/browser/checkout-attribution。AccountAttribution(src/server/account-attribution.ts)再次检查它,在 D1 account_attribution 中为每个账户保留第一个值,并发送 account_attributed。BillingSales 将其复制到 payment_succeeded 和 revenue 账本事件。该流程及其限制见 ANALYTICS.md。
OpenPanel Growth 仪表板使用从 landing_viewed 到 landing_download_clicked 的会话漏斗。下载点击并不等于已完成下载或安装。先按 acquisition_source 细分漏斗,一旦 schema 版本 8 事件到达 OpenPanel,再按 source_platform 细分。历史事件不包含新的平台属性。
当 GitHub 清单无法读取时,/download/<os>/latest Worker 处理器会回退到发布页面。该回退写入 Worker 日志,而非 OpenPanel:服务器事件没有会话,落地页仪表板是基于会话定义的。
对于下载点击报告,platform 表示请求的 macOS、Windows 或 Linux 下载;placement 表示按钮位置。这些属性仅存在于下载步骤中。用它们来比较点击次数,而不是作为共享的访问到点击漏斗细分。邀请页面漏斗是独立的:join_page_action 带有 action=view,随后是 action=download 或 action=open_app。
资源采样¶
ResourceMonitor(src/main/resource-monitor.ts)在计算机处于唤醒状态时每分钟采样一次。它读取 Electron 进程的 app.getAppMetrics() 并按类型分组:工具进程的 name 区分数据库和语音宿主,BrowserHost.tabProcessIds() 区分浏览器标签页和窗口。在 macOS 和 Linux 上,一次 ps 调用即可列出所有进程。主进程的非 Electron 后代进程构成提供者树:生成站点在 src/backend/provider-processes.ts 中注册的 PID 会命名其提供者,其子进程继承该名称,未注册的 claude、codex、opencode 或 grok 可执行文件以自身命名,其他所有进程均为 other。Windows 报告 provider_tree_supported: false。ps 失败的采样不记录总数。CPU 来自两次列出之间每个进程 CPU 时间的变化,因此在两次采样之间启动并结束的命令(例如短工具运行)不会被计入。主事件循环使用 monitorEventLoopDelay,减去其 20 ms 定时器间隔。
数据库时间来自 AgentDatabaseSupervisor,从语句发送到其应答或宿主结束;宿主进程保持不变。渲染进程和子进程的退出若不是干净退出,会立即作为 crash span 写入 trace,并在下一次采样时计数。原因是 killed 的工具进程既不属于干净退出,也不属于 crash:OpenBot 自行停止这些进程。应用退出前最后一分钟内发生的进程退出不计入:停止信号可能在主进程开始清理之前就结束了子进程。trace 仍然会在该退出的 exit span 之后保留它。
index.ts 在 OpenBot 开始退出时写入一个 exit span 和 logs/main/main.log 中的一行。名称是首要原因:main_window_closed(Windows 和 Linux 中关闭主窗口即退出)、signal、session_end 或 quit(菜单、托盘、更新或重启)。主日志包含 main logger 的每一行(已脱敏),保存在两个 1 MB 的文件中。crashReporter 将本地崩溃转储保存在 app.getPath("crashDumps") 中,并且永远不会上传。一个没有 exit span 且没有转储就结束的进程是从 OpenBot 外部停止的(#2675)。
纯逻辑部分(resource-summary.ts)将每天保存为具有两位有效数字的稀疏直方图、峰值和计数器,因此 p95 在没有样本列表的情况下也足够精确。摘要文件包含当前天和上一个已关闭的天;它最多每 15 分钟写入一次,并在日期切换和关闭时写入;文件损坏则会开启新的一天。HostAnalytics.checkResources() 将已关闭的天作为 system_resources 发送,并在发送前于文件中将其标记为已处理,因此崩溃不会导致其被发送两次。该文件会保留已处理的天以用于诊断导出,直到被更新的天替换。任何包含 PID、命令或路径的信息都不会离开进程:摘要键是组名、provider ID 和原因词,分析允许列表会再次检查每个值。
Agent 用量分析¶
AgentUsage 拥有本地的数值用量记录、累计计数器检查点和活动计数。迁移 15 在两条数据库创建路径上都添加了这些表。它们不引用对话投影:清除对话必须保留用量。删除 Agent 会在其现有事务中删除用量、检查点、活动以及相关的命令回执。
轮次生命周期仅接受属于该 Agent 的 provider 会话中的用量,该会话位于其自己的聊天或某个任务中。它会在 provider 线程的公共线程中查找该会话。Codex 总量使用持久的会话检查点。Codex 计数器 :codex:cache-writes 取代了 :codex,后者将缓存写入计为未缓存的输入。当计数器没有检查点时,它会从上次请求之前的会话总量开始(total 减去 last)。因此,:codex 曾计数的请求、任务计量之前的任务请求,以及迁移 15 之前的请求都不会被计数。最后一次请求会计数,即使是在迁移 15 之前的会话中也一样。没有 last 或没有轮次 ID 的更新会建立基线。
Claude 使用按模型的查询总量,并为每个查询进程使用单独的计数器身份。ACP 用量是可选的。缺失的字段保持未知。ACP 用量是会话总量,每个会话一个计数器,但 Antigravity 除外:1.4.3 会发送单个提示词的 token,因此每个提示词结果都有自己的计数器,其 thoughtTokens 计为输出。已完成的助手消息不包含评述和工具输出。只有安装后的消息会进入活动计数。
agent:get-analytics 以及受能力门控的 GET /v1/agents/:agentId/analytics 返回聚合数据。它们与 provider 账户限额是分开的。请求指定 Agent、包含首尾的日历日期以及查看者的时区。host 会按该时区将记录分组到各个日历天。日期比较使用包含起始日、排除次日的边界;自定义范围限制为 367 天。桌面端显式指定 host,移动端则将读取绑定到其已认证的活动 host。该 host 团队的每个成员都可以读取总量。公共 Web 端和 Signal 服务不存储用量记录。
用量视图显示 7、30、90 或自定义天数,默认 30 天。两者都在 SVG 图表旁显示精确的每日数值。成本是 USD API 等效估算值,不是订阅费用。内置费率引用官方来源,并带有验证日期。有预定变更的费率会使用轮次开始时生效的费率。Claude 目录价估算来自 SDK 模型用量;未知或托管定价不视为目录价估算。Codex 缓存写入使用 30 分钟缓存写入费率。低于 provider 长上下文阈值的更新使用短费率。超过该阈值的更新仅在它是单个请求时使用长费率(其输入等于 last 提示词);ACP 不报告此类提示词,因此超过阈值的 Grok 更新保持未定价。未知模型、缺失的缓存数据以及无法解析的上下文或缓存写入定价保持未定价。工具和媒体费用不在估算范围内。存储的估算保留其价格基准。
主机级用量¶
桌面端从服务器上下文菜单打开用量。它保持先前的工作区挂载且处于非活动状态,直到点击返回,因此对话草稿和设置可在导航后保留。Agent 设置会打开带有 Agent 筛选器的同一报告。Host 变更会清除筛选器,并拒绝过期的响应。iPhone 应用会从服务器菜单中以弹出面板形式打开用量。它通过 @openbot/team-client 中的 readHostAnalytics 读取同一路由,并显示按 Agent 列出的行;点击一行或使用标题筛选器可将报告缩小到单个 Agent。Agent 用量页面使用 Agent 筛选器读取同一路由,因此其图表也具有 provider 拆分;没有 host-analytics 的 host 会获得 agent 作用域的路由和单个区域。系列数据透视位于 @openbot/team-client/usage-series,桌面端图表也读取该模块。
host:get-analytics 和可选的 host-analytics 能力公开了 GET /v1/analytics。host 仅查询一次本地用量表,以获取日期范围和可选的 Agent 筛选器;它不会添加按 Agent 的 API 响应。同一次遍历按 agent id(以及天和模型)分组,因此 host 级响应包含按 Agent 列出的行,客户端会根据其已读取的 Agent 列表来标注这些行。同一次遍历还按天和 provider 分组,从而使图表可以在共享基线上为每个 provider 绘制一个区域;单元格仅包含 token 计数和成本估算,因为这是图表读取的两个度量。这两个数组仅在 host 报告中,这就是 agent 作用域路由及其编解码器保持不变的原因。会话和轮次身份包含 agent 和 provider。HTTP 和 WebRTC 使用显式的 host 分析编解码器。现有的 agent 分析和账户限额保持其约定不变。所有经过身份验证的团队成员都可以读取这些聚合数据;账户服务或 Signal 服务不会存储额外的分析数据。
桌面图表改编自 Zaidan 的图表与交互区域构成。固定的 solid-recharts 依赖包含一个 Solid 2 兼容性补丁,并使用应用程序的单一 Solid 运行时。图表颜色使用 OpenBot 令牌。每日表格提供精确的无障碍值。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 openbo/openbot