
Friend macOS 发布健康指标规范面向 Sentry 与 PostHog 的权威查询契约解析【免费下载链接】FriendAI that sees your screen, listens to your conversations and tells you what to do项目地址: https://gitcode.com/GitHub_Trending/fr/Friend导读本文基于Friend开源仓库desktop/macos桌面端的《macOS Release-Health Metric Specification》展开系统讲解一套服务于 macOS 桌面应用的发布健康release-health遥测指标规范。该规范回答了一个指标何时算回归、何时算噪音、何时算未知这类可观测性工程的核心问题通过为每个信号定义精确的分子numerator、分母denominator、时间窗口、最小样本量minimum cohort、缺失数据处理规则与跨版本比较规则确保中间生命周期事件和预期噪音不会被误读为客户可见的回归。读完本文你将掌握 PTT 音频捕获漏斗、Realtime 令牌铸造、Provider 会话健康、回退fallback结果、崩溃率、主动建议投递、更新器投递与三类内存指标的具体查询口径以及这套规范在Friend仓库中的实际代码落点。一、规范的定位与权威性release-health-metrics.md仓库路径 desktop/macos/docs/release-health-metrics.md是 macOS 发布健康遥测的权威查询契约authoritative query contract。它定义了每个信号的精确口径目的是让中间生命周期事件和预期噪音不能被读成客户可见的回归。该文档是desktop/macos/AGENTS.md中 Product analytics integrity产品分析完整性与 Fallback / resilience telemetry回退/韧性遥测两个章节的完整展开版。文档状态信息Status:active ·Schema version:4 ·Owner:desktop/macos。当任何分子/分母定义、封闭枚举closed enum或字段名发生变化时需要升级 Schema version 并在文档中显式记录变更。telemetry_schema_versionPTT 生命周期快照上以及expected/outcome/mint_attempt_id/phase/close_attempt_id/turn_outcome等字段是本文档的机器可读伴生约定。统一的发布身份Release identity在 Sentry 与 PostHog 两个遥测面上发布身份字段保持一致维度PostHog keySentry来源App 版本app_versionreleasev{ver}{build}-macosCFBundleShortVersionStringApp 构建号app_buildrelease同一标签CFBundleVersion发布渠道update_channelstable/betadistupdate_channeltagAppBuild.currentUpdateChannelBundle id—bundle_idtagAppBuild.bundleIdentifierPostHog 侧的app_version/app_build/update_channel通过PostHogManager.register注册为超级属性super-properties因此每一个事件——包括floating_bar_ptt_ended——都携带发布身份。Sentry 侧的原生崩溃、App 挂起app-hang、看门狗watchdog事件通过SentrySDK.start时设置的options.releaseName/options.dist实现构建可归属build-attributable。跨切面规则Cross-cutting rules中间事件不是失败Intermediate events are not failures指标的分子必须是终态、有界的结果terminal, bounded outcome绝不能是中间的生命周期转换。如果一个信号没有显式的 outcome 字段它只是构建块building block不是发布健康指标。预期生命周期从错误汇总中排除带expected truelifecycle_class expected的实时事件——如空闲拆除idle teardown与计划内的会话轮换planned session rotation——可以单独检查但必须从实时错误率和发布回归率中过滤掉。错误率只使用expected false的事件。最小样本量Minimum cohort低于最小样本量时比率是unknown既不是100%也不是0%。跨发布比较要求两侧都满足最小样本量。比较基准build 对 build、beta 对 stable 的比较使用相同的窗口与分母定义只有当两个队列都满足最小样本量且方向对所关注的 outcomes 不利时才判定为回归regression。隐私边界自定义指标负载只使用有界维度。任何 PostHog 属性或 Sentry tag 中都不允许出现转录文本、音频、提示词、自定义设备标识符或自由形式的本地错误文本。该边界由 DesktopDiagnosticsManagerTests.swift 与TelemetryPrivacyBoundaryTests强制保证。从源码侧看事件名称的权威清单定义在 DesktopDiagnosticsManager.swift 的DesktopHealthEventName枚举中包括pttAudioCaptureLifecycle、realtimeTokenMintFailed、realtimeProviderExpectedIdleTeardown、realtimeProviderPolicyClose、realtimeProviderSessionError、realtimeProviderCloseResolution、fallbackTriggered等与本文档的指标一一对应。二、指标总览与承载层文档指出每个指标只要存在对应项就映射到desktop_release_doctor_report.METRIC_CONTRACTS名称没有 doctor 条目桌面端 outcome 指标则是客户端输入由发布证据层release-evidence layer消费。指标清单速览指标关键事件最小样本窗口PTT 终态漏斗ptt_audio_capture_lifecycledesktop_health_event每 build 50 次可判定尝试PT24HRealtime 令牌铸造realtime_token_mint_faileddesktop_health_event每 build 30 个铸造用户PT24HRealtime Provider 会话健康realtime_provider_*5 个相关事件每 build 40 个活跃会话用户PT24H回退结果fallback_triggereddoctor:fallback_outcomesdesktop_health_event每 build 50 个回退用户PT24H崩溃安全会话doctor:crash_free_sessionsSentry 会话跟踪每 build 100 个会话PT24H主动建议投递doctor:proactive_deliveryAdvice Generated/Advice Delivery Outcome50 DAU / 10 个合格投递PT24H更新器投递doctor:updater_deliveryUpdate Check Started/Completed每 build 30 次尝试PT24H录音客户端输入recording_error低于最小值 →unknown—内存三漏斗产品分析三个独立事件——三、PTT 终态漏斗ptt_audio_capture_lifecycle这是文档中最详细、最能体现中间事件不是失败原则的指标。来源事件desktop_health_eventevent ptt_audio_capture_lifecycle要求telemetry_schema_version 2turn_kind从版本 3 起引入。分母尝试次数窗口内所有ptt_audio_capture_lifecycle事件按failure_class分组。由于每一个终态处置——包括成功——都会远程上报所以分母是可查询的。分子捕获失败failure_class IN (capture_never_operational)。恢复类结果recovery_outcome_recovered/_still_silent/_not_judgeable通过recovery_attempt_id关联不计入新的失败。明确排除在失败分子之外不算回归committed成功released_before_usable_audio/too_short_audible轻点即松 / 过早松开cancelled用户取消zero_or_near_zero_samples且turn_disposition silent_rejected安静丢弃 / 无语音其中first_chunks_energy_bucketturn_disposition两个字段用于把真正的零采样捕获失败与有意的安静丢弃区分开。弃用事件floating_bar_ptt_ended携带had_transcript把上述四类结果折叠成单个布尔值绝不能作为 PTT 成功/失败的分母仅保留用于向后兼容。窗口与样本PT24H 滚动窗口每 build 最小队列 50 次可判定尝试若某 build 没有任何ptt_audio_capture_lifecycle事件 → 判为unknown。源码佐证在 DesktopDiagnosticsManager.swift 中PTT 看门狗watchdog逻辑有明确阈值pttWatchdogThreshold 3、15 分钟去重窗口、最小音频 0.35 秒并且注释明确写着cancel 是有界failure_class值与capture_never_operational相区别与规范口径完全一致。四、Realtime 令牌铸造realtime_token_mint_failed来源事件desktop_health_eventevent realtime_token_mint_failed。阶段warm vs activephase是封闭集合——warm后台预预热与barge_in_replacement活跃轮次中的 socket 替换任何其他值被归入other。这是暖 vs 活跃维度。即时结果degraded/exhausted铸造失败事件本身会记录控制器是启动了备用提供者回退degraded还是没有任何剩余的受管路径exhausted。后续的回退结果保留在关联的fallback_triggeredarea realtime_hub事件上。当铸造触发故障切换failover时通过mint_attempt_id关联两个事件再用 provider 加有界时间窗口过滤。分子铸造耗尽、用户受影响铸造失败事件上的outcome exhausted没有剩余受管路径。详细的替换路径使用关联的realtime_hub回退事件。degraded备用提供者回退已启动是可恢复的不是终态失败分子。窗口与样本PT24H每 build 最小队列 30 个铸造尝试用户无铸造事件 →unknown。五、Realtime Provider 会话健康realtime_provider_*来源事件5 个realtime_provider_expected_idle_teardown、realtime_provider_expected_session_rotation两者expected truerealtime_provider_policy_close、realtime_provider_session_error两者expected falserealtime_provider_close_resolution客户回合customer-turn决策每个 provider 关闭事件携带进程内close_attempt_id配对的realtime_provider_close_resolution携带封闭集合的turn_outcome与即时的recovery_action/recovery_result。该 id 仅在同一个分析会话内有效绝不是用户、设备、回合或 provider 会话标识符。错误率分子活跃回合的realtime_provider_session_errorrealtime_provider_policy_closeexpected false且配对 resolution 的turn_outcome failed。pending_replacement是中间恢复状态不是终态客户失败分子。分母活跃 realtime 会话以发出任意realtime_provider_*的独立会话为代理。排除项两个expected_*事件expected true——正常的空闲拆除和计划内的 60 分钟 OpenAI 会话轮换。它们仍可单独检查但不得抬高 realtime 错误率或发布回归率。窗口与样本PT24H每 build 最小队列 40 个活跃会话用户。源码佐证RealtimeProviderCloseTurnOutcome枚举定义在 DesktopDiagnosticsManager.swift封闭集合为not_interrupted/failed/pendingReplacement注释明确说明关闭事件在控制器选择替换、故障切换或终态路径之前被捕获而该封闭集合记录的是不含 provider 负载的决策——这正是close 与 close-resolution 分离设计的实现。六、回退结果fallback_triggereddoctor 指标fallback_outcomes来源事件desktop_health_eventevent fallback_triggered。维度全部为封闭枚举area、reason、from、to、outcomerecovered/degraded/exhausted。未知的area/reason归入other。发布健康分子客户可见降级outcome IN (degraded, exhausted)按(area, reason, from, to)分组。recovered是静默的 UX 自愈silent UX heal不是失败。已知良性抖动known-benign flaparea screen_capture、reason capability_mismatch、from/to ∈ {screen_capture, capture_paused, recovery_poll}属于 ProactiveAssistants 屏幕捕获健康抖动目标暂时不可用后恢复。这是预期的能力抖动——应针对其速率告警绝不能对绝对计数或recovered支路发 page。area other策略剩余的other只折叠真正未分类的路径非平凡的other比率是插桩缺陷instrumentation defect应进行 triage而不是产品回归。命名所有者screen_capture、memory_scope、desktop_update、tts_fallback、task_workflow、auth_storage、realtime_hub、ptt_cascade等确保已知路径不落入other。窗口与样本PT24H每 build 最小队列 50 个发出回退事件的用户。源码佐证DesktopFallbackOutcome枚举recovered/degraded/exhausted定义于 DesktopDiagnosticsManager.swift。此外仓库中的memory_scope回退路径被用于内存操作可靠性跟踪见后文内存可靠性一节与文档memory_scope仍是降级信号的表述一致。七、崩溃安全会话doctor 指标crash_free_sessions来源Sentry release health自动会话跟踪以releaseName/dist为键。分子发生硬崩溃hard crash的会话数。分母该 release 的总启动会话数。按releaseversionbuild与update_channel过滤原生崩溃通过options.releaseName/options.dist实现构建可归属。窗口与样本PT24H每 build 最小队列 100 个会话。隐私原生事件只携带update_channel/bundle_idtags外加diagnostic_area/failure_class无用户内容。八、主动建议投递doctor 指标proactive_delivery这是唯一带告警作业alarm job描述的指标规范对其自动化运行机制描述得最为详尽。可用性Availability来源发出Advice Generated的独立用户数 ÷ 同一滚动 PT24H 窗口内的 macOS DAU。两侧都限定$app_namespace com.omi.computer-macos且$os_name macOS。投递Delivery来源Advice Delivery Outcome终态事件。合格的投递结果只有delivered与failed偏好/策略类抑制被排除。当合格结果 ≥ 10 时若delivered恰好为 0 则视为不健康。告警规则精确零 advice 用户且 macOS DAU ≥ 50或精确零合格投递结果 →不健康。DAU 50 或合格投递结果 10 →unknown既不是成功也不是失败。计划任务desktop_release_doctor.yml每小时运行一次不健康期间保持一个持久的 GitHub issue 打开测得恢复后关闭它并将PostHog 查询失败当作告警处理而非静默通过。监控凭据计划任务读取仓库 Actions secretPOSTHOG_PERSONAL_API_KEY与 Actions 变量POSTHOG_PROJECT_ID、POSTHOG_HOST。它刻意不使用需要人工审批的prod环境否则每小时检查将等待人来批准。配置缺失时产生中性的unconfigured结果且不产生健康告警因为没有发生测量已配置但查询失败时产生monitor_error并打开持久 issue两种状态都不会让指标变绿。投递结果每个Advice Generated事件携带不透明的进程内delivery_idAdvice Delivery Outcome记录封闭的outcomedelivered/suppressed/failed与有界的reason。通知偏好只抑制投递不抑制分析。排队的浮条项是中间态在呈现边界接受之前绝不能算作已投递。隐私查询只导出聚合计数。两个事件的定制负载都不包含建议文本、屏幕内容、提示词、转录或设备标识符。PostHog 标准的person_id仅就地用于聚合基数计算不由监控器返回。九、更新器投递doctor 指标updater_delivery来源Update Check Started通过不透明的attempt_id关联到其唯一的终态Update Check Completed。两者都携带触发器、源 app 版本/build 以及归一化更新渠道。失败分子终态result failed。no_update与update_available是成功的检查结果。network_unavailable是自动后台检查其 URL 错误专门是NSURLErrorNotConnectedToInternet-1009它单独上报不是更新器缺陷。超时、DNS 与服务器可达性错误仍算失败这样真实的更新服务故障不会被掩盖。离线时的手动检查仍为failed以便用户获得反馈。遗留事件Update Check Failed仅保留诊断用途绝不能作为分母或用户影响率。它现在遵守每次检查一个终态契约Sparkle 对单次检查会重投didAbortWithError而直到 2026-08遗留事件对每个回调都会触发一次在 0.12.187–0.12.212 构建上达到权威result failed计数的3x–47x。修复前的历史Update Check Failed数据量被放大了不能与修复后的构建进行比较。分母不同的已开始尝试。缺失终态是独立的插桩健康缺陷当下一次被 Sparkle 接纳的检查关闭一个陈旧身份时记为callback_missing。开始记录仅在 Sparkle 序列化的mayPerform边界进行周期结束 delegate 是省略 abort 回调路径的最终回退。被拒绝的请求不会产生幻影尝试重复回调也不能产生额外终态。窗口与样本PT24H每 build 最小队列 30 次尝试。十、录音错误客户端输入recording_errorPostHog 事件只携带error_class无音频。分子 错误数分母 录音会话数。低于最小值 →unknown。十一、内存指标三个独立漏斗产品分析文档明确指出macOS 的memory面是三个独立漏斗而非一个录音用户不是主动内存的分母Memory Created不是抽取内存的代理——它跟踪的是录音/会话与后端的对账reconciliation。以下三个指标就是让每个漏斗可测量的查询契约。所有负载只携带有界维度不发送屏幕像素、OCR/窗口/App 名称、内存内容、提示词、Gemini 响应、原始模型材料、会话 id、转录文本或异常字符串由MemoryAssistantTelemetryTests与test_conversation_memories_telemetry.py强制保证。1. 主动内存助手激活Memory Assistant Setting Changed来源事件Memory Assistant Setting Changed桌面端主动MemoryAssistant。封闭属性setting ∈ {enabled, notifications_enabled}、布尔value。存在原因分析被硬性门控在enabled notificationsEnabled而通知默认关闭因此通知开关处的激活悬崖activation cliff此前不可见。该事件让真正的分母可测量。发射规则对任一设置的每次用户主动发起的持久化变更恰好发射一个事件——远程设置同步、App 启动、默认读取、迁移或程序化重置时绝不发射。两个 UI 开关路径使用专用的用户意图 API比较旧值新值并跳过无操作no-op裸 setter 故意静默。激活指标主动抽取用户Memory Extracted÷ 监控用户Monitoring Started且notifications_enabled true限定$app_namespacecom.omi.computer-macosAND$os_namemacOS。不要再拿抽取量除以录音用户数。源码佐证MemoryAssistantTelemetry.swift 中Setting枚举enabled/notifications_enabled与settingChangeIsPersistedChange纯函数oldValue ! newValue完全对应上述发射规则文件头注释明确写着通知开关是实际的分析门控默认关。2. 主动分析结果分布Memory Assistant Analysis Run来源事件Memory Assistant Analysis Run桌面端。封闭属性outcome ∈ {synced, filtered_low_confidence, no_new_memory, sync_failed, local_persistence_failed, sync_state_persistence_failed, analysis_failed}可选的confidence_bucket封闭十分位区间如70_80仅在模型返回了置信度的结果上出现。发射规则对每次实际的 Gemini 分析尝试恰好发射一个事件——不是每帧也不在禁用/门控路径上。每个可达的终态映射到恰好一个 outcome。它补充——不替换、不改写——现有Memory Extracted成功终态后者仍只在本地 SQLite 插入后触发包括synced、sync_failed、sync_state_persistence_failed在local_persistence_failed后绝不触发。指标分析尝试中的 outcome 分布。synced是唯一完全成功的终态sync_failed隔离后端创建丢失local_persistence_failed隔离任何后端调用之前的 SQLite 持久化失败sync_state_persistence_failed隔离后端成功后本地同步状态回执失败。filtered_low_confidence展示 0.70 置信度阈值的效果。源码佐证MemoryAssistantTelemetry.swift 的AnalysisOutcome枚举与confidenceBucket把原始置信度钳制到[0,1]后向下取整到十分位上限 90 以确保1.0落到90_100而不是100_100。MemoryAssistantDurability.emitPersistenceTerminal同文件 L221-L229证明持久化终态发射memoryAssistantAnalysisRun且仅当shouldEmitMemoryExtracted即! .localPersistenceFailed时才补发历史Memory Extracted成功事件——与文档本地插入失败后 Memory Extracted 绝不触发的表述精确一致。3. 转录会话内存抽取成功Conversation Memories Extracted后端来源事件Conversation Memories Extracted后端服务端转录内存路径分析身份distinct_id uid。封闭属性memory_count_bucket ∈ {1, 2, 3, 4_9, 10_plus}、source ∈ {transcription, external_integration}、path ∈ {canonical, legacy}。存在原因这次录音是否产生了记忆步骤在服务端运行并写入 DB但没有发出任何分析事件——这正是录音→内存可观测性缺口observability gap的根因。发射规则在持久化成功结果之后、于extract_memories公共边界至多发射一次投递尝试。零抽取 → 不发射事件无假成功。持久化异常 → 传播不发射。在权威的(uid, conversation)文档下的持久化、原子性 Firestore 标记允许在重新终结/重试之间至多一次PostHog 投递尝试无缓存 TTL 或驱逐窗口。标记在 SDK 构建/捕获之前认领由于 PostHog 捕获是排队而非投递确认这明确是至多一次尝试语义——可选遥测可以丢失但重试不能重复该值。若标记不可查询这个可选指标失败关闭不捕获而终结流程继续。会话 id 仅是标记路径组件绝不是 PostHog 属性。认领、PostHog 构建与捕获降级都记录共享的有界回退信号任一失败都不能撤销持久化的抽取。指标转录内存抽取成功 发出Conversation Memories Extracted的用户 ÷ 已终结会话分母Memory Created录音对账代理。按 uid 窗口关联。源码佐证后端实现位于 memory_extraction_telemetry.pydocstring 完整复述了上述契约封闭枚举、零抽取不发射、持久化失败跳过、(uid, conversation_id)维度下的原子 Firestore 标记实现幂等、失败关闭语义CONVERSATION_MEMORIES_EXTRACTED常量与封闭的_VALID_SOURCES集合直接对应文档口径。配套测试 test_conversation_memories_telemetry.py 与抽取主流程 process_conversation.py 覆盖了该发射路径。十二、内存可靠性客户端输入保持不变内存操作可靠性仍通过memory_scope回退结果跟踪设备作用域拒绝不发射任何内存内容。上面三个指标是激活/漏斗/价值契约memory_scope仍是降级信号。十三、功能路径成功与后端错误率doctor 指标feature_path_success/backend_error_rate这两个指标分别归 doctor 报告与后端所有本规范只要求桌面客户端喂给 doctor 的feature_path_success分子聊天终态结果、PTT 漏斗、回退结果使用上述 outcome 语义使其永远不会是中间事件。十四、版本控制当任何分子/分母定义、封闭枚举或字段名发生变化时升级Schema version并在文档中显式说明变更。PTT 生命周期快照上的telemetry_schema_version以及expected/outcome/mint_attempt_id/phase/close_attempt_id/turn_outcome字段是本文档的机器可读伴生约定。结语把规范落成可执行的查询这份规范的可贵之处在于可执行每一个信号都有精确的分子、分母、窗口、最小样本、缺失数据规则与比较规则配合 DesktopDiagnosticsManager.swift 中的事件枚举与failure_class约束、MemoryAssistantTelemetry.swift 中的封闭 outcome 集合、memory_extraction_telemetry.py 中的至多一次发射语义以及 Sentry/PostHog 两侧统一发布身份的注册方式团队可以据此写出稳定、可复现、不会把预期噪音误报为客户回归的发布健康查询。阅读 AGENTS.md 可以了解这些指标背后的产品分析完整性与韧性遥测原则而 integration-connect-telemetry.md 展示了同一遥测基础设施在其他功能面上的应用方式。【免费下载链接】FriendAI that sees your screen, listens to your conversations and tells you what to do项目地址: https://gitcode.com/GitHub_Trending/fr/Friend创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考