
Omi 真实流量 Journey 可观测性运行手册封闭指标契约、客户端分段与 critical 级 SLI 分页告警【免费下载链接】FriendAI that sees your screen, listens to your conversations and tells you what to do项目地址: https://gitcode.com/GitHub_Trending/fr/Friend本文基于仓库内运维手册 backend/docs/runbooks/real-traffic-journeys.md 展开并结合后端指标定义、标签契约、观测实现与 Grafana 告警规则源码进行纵深解析。本文适用于 Omi本仓库代号 Friend后端团队在 dev/beta 与生产环境维护实时转写、会话推送、语音捕获终结化等核心链路的可观测性体系读者读完可以掌握如何用「仅统计真实用户流量」的封闭指标契约区分用户故障与空闲系统、如何基于客户端分段 Journey 定位端到端失败归因、以及如何校准并部署分页级criticalSLI 告警而避免在安静时段误报。设计总纲只度量真实用户流量且绝不携带用户身份omi_journey_*与omi_live_stt_*两个指标家族在整个仓库的可观测性体系中承担一个特殊职责它们只统计用户发起的真实流量。这意味着这些计数器不会包含测试账号、合成金丝雀synthetic canary或脚本生成的请求。与此同时dev/beta 与生产环境被刻意隔离——每个 Prometheus 实例只评估自己抓取的流量指标上不携带任何跨环境比较标签避免把不同环境的语义混在一起得出错误结论。这个真实性 隔离性的设计直接决定了后续所有告警的表达方式没有真实流量时计数保持为零而不是制造一个虚假的成功率分母或 0% 成功率的假象。下文所有指标定义、告警门槛与 noDataState 语义都建立在这一前提之上。封闭指标契约omi_journey_*与omi_live_stt_*家族指标清单与含义原文档给出了 9 个核心指标的完整契约全部定义在 backend/utils/metrics.py 中MetricLabelsMeaning含义omi_journey_accepted_totaljourney生产边界接受了工作。omi_journey_terminal_totaljourney,outcome已接受工作的一次性终结结果one-shot terminal outcome。omi_journey_latency_secondsjourney,outcome从接受acceptance到终结terminal的时延。omi_live_stt_accepted_totalprovider,client_platform,deployment_environmentlistener 接受了第一帧非平凡nontrivial的实时 STT 音频帧。omi_live_stt_terminal_totalprovider,outcome,client_platform,deployment_environment,phase已接受的实时 STT 尝试的一次性终结结果。omi_live_stt_terminal_failures_totalprovider,outcome,client_platform,deployment_environment,phase与实时 STT 终结事件关联的 provider 失败明细。omi_capture_finalization_reconciliations_totaloutcome过期stale的持久化捕获任务被重新入队requeued或其重新入队交接失败enqueue_failed。omi_capture_finalization_failures_totalreason持久化终结器失败且 reason 只能是以下隐私安全取值之一memory_fence、memory_config、provider、stale、processing。listen_finalization_oldest_nonterminal_age_seconds无最老的已排队/已租约leased/被 BYOK 阻塞的捕获终结化任务的年龄。listen_finalization_durable_jobsstate权威的 Firestore 任务投影accepted、success、failure、stale、nonterminal、blocked_byok或terminal_unknown。其中journey的封闭取值恰好为chat_response、pusher_session、capture_finalization三种通用 journey 的outcome恰好为success、failure、cancelled、stale四种reconciliation 的outcome恰好为requeued或enqueue_failed实时 STT 终结outcome恰好为success、failure、cancelled其终结phase恰好为transcript_delivery、initialization、connection、send、teardown。provider与client_platform沿用各自已有的封闭词表deployment_environment是prod、dev、local、offline、unknown之一。整个体系不携带任何 user、conversation、request、error-text、revision、image、provider-model 或 content 标签——这是该体系的隐私安全底线。源码级佐证封闭标签如何在运行时被强制代码层面对封闭的强制体现在两处指标定义处的封闭词表校验。在 backend/utils/observability/journeys.py 中_JOURNEYS与_OUTCOMES是两个 frozenset_journey()与_outcome()两个辅助函数会在写入指标前校验标签值非法的 journey 名或 outcome 直接抛出ValueError如unknown journey: user-123。测试 backend/tests/unit/test_journey_observability.py 明确断言了这一点record_journey_accepted(user-123)必须抛错record_journey_terminal(chat_response, raw exception text, 1.0)也必须抛错——原始异常文本永远不会成为标签。零初始化导出。在 backend/utils/metrics.py 中进程启动时会遍历完整封闭组合预先为每个 journey × outcome 组合创建零值标签子序列。这样健康但空闲的 exporter 导出的是一组明确的零而不是一个缺失的序列——运维可以把没有流量与抓取目标丢失区分开详见下文抓取健康小节。记录函数与语义JourneyAttempt是一个进程内的一次性终结模型backend/utils/observability/journeys.py构造时调用record_journey_accepted自增接受计数finish()只允许调用一次_finished标志守卫且同时写入OMI_JOURNEY_TERMINAL_TOTAL计数与OMI_JOURNEY_LATENCY_SECONDS直方图观测值。对于跨进程完成的持久化工作如捕获终结化record_capture_finalization_terminalbackend/utils/observability/journeys.py使用持久化的接受时间created_at而非进程内monotonic()计算时延对没有created_at的遗留任务则只记录 outcome、不伪造时延值。对应的单元测试test_capture_terminal_uses_persisted_acceptance_time验证了持久化接受时间 5 秒会得到 4~6 秒的观测值。客户端分段 Journeyomi_client_journey_*家族为什么需要独立家族原文档强调了一个关键约束既有的omi_journey_*家族刻意保持不动。它是一个封闭的、有历史stale语义、并且已经接了告警的契约。为了给客户分段client segmentation腾出空间而又不悄悄改写旧契约新语义 Journey 使用独立的指标家族。这避免了两种风险历史告警语义被漂移破坏以及把客户端分段这个新维度硬塞进旧标签集造成基数爆炸。指标清单MetricLabelsMeaning含义omi_client_journey_accepted_totaljourney,client_kind接受了一个语义 Journey。omi_client_journey_terminal_totaljourney,client_kind,outcome其一次性粗略终结结果。omi_client_journey_issues_totaljourney,client_kind,issue_class失败/降级/未知终结的一个有界明细。omi_client_journey_duration_secondsjourney,outcome从接受到终结的持续时间。outcome是success、failure、degraded、cancelled或强制收敛哨兵unknown。degraded表示请求完成了、但没有交付所请求的主产品结果。canned_fallback与quota_capped必须保持为独立的issue_class值禁止从粗略 outcome 反推失败/降级明细是独立计数器。特别注意client_kind被有意从直方图中剔除——直方图按journeyoutcome分桶避免把每个直方图桶再乘上客户端种类数量。从源码看这些封闭词表定义在 backend/utils/journey_metrics_contract.py 中9 种ClientJourneyName含desktop_chat、mobile_chat、live_transcription、conversation_finalization、memory_retrieval、desktop_proactivity、app_webhook_delivery、realtime_voice、unknown、5 种ClientJourneyOutcome、12 种ClientJourneyIssueClassupstream_rejected、upstream_timeout、provider_error、empty_answer、invalid_response、dependency_unavailable、quota_capped、rollout_disabled、canned_fallback、incomplete_attempt、incomplete_stream、unknown以及 10 种ClientKind。bounded_*系列函数会对任何未经允许的输入做归一化、截断默认 128 字符并收敛到unknown测试 backend/tests/unit/test_client_journey_foundation.py 验证了 1 万个字符的用户输入最终只产生 128 字符标签并收敛为unknown——用户输入永远不会直接变成标签。client_kind解析优先X-App-PlatformUser-Agent 只是兜底resolve_client_kindbackend/utils/journey_metrics_contract.py的解析优先级如下存在非空的X-App-Platform头时按封闭映射解析android→mobile_android、ios→mobile_ios、macos→desktop_macos、windows→desktop_windows、linux→desktop_linux、desktop→desktop_unknown_os、mobile→dart_mobile_unknown_os、web→web未识别的新平台收敛为unknown且不会回退去猜 User-Agent避免自相矛盾。无头时只识别已知的 User-Agent 家族CFNetwork/Darwin→desktop_macosElectronWindows→desktop_windows无头 Dart →dart_mobile_unknown_os。两个 pi-mono 扩展目前发送相同的OpenAI/JS 6.26.0User-Agent 且不带平台头两者都会被解析为pi_mono_unknown_os。服务器在客户端发送X-App-Platform之前无法区分它们也不得猜测操作系统——把一个无法归因的群体硬编成误导性遥测比诚实的unknown更糟。对应的参数化测试backend/tests/unit/test_client_journey_foundation.py覆盖了上述全部分支包括同一OpenAI/JS 6.26.0UA 在带/不带平台头时分别解析为desktop_macos/desktop_windows与pi_mono_unknown_os。零初始化、系列上限与零也有意义该家族是零初始化的只有下节列出的已接线 Journey 会产出真实流量且目前尚不存在任何基于客户端分段的告警。这里有一个微妙的语义零只有在与所属抓取作业/版本一起选择时才有意义因为一个无关的健康 exporter 也会导出这些有界零子序列。这也是为什么零初始化在 backend/utils/metrics.py 中按完整笛卡尔积完成——测试test_client_journey_metrics_zero_initialize_the_complete_bounded_contract用_sample_label_sets断言 accepted/terminal/issues/duration 的子序列数量分别等于len(CLIENT_JOURNEYS)×len(CLIENT_KINDS)等精确乘积。原文档给出了一个硬性容量结论在启用固定客户端_created系列的情况下该封闭笛卡尔积每个进程被限制在 3,915 个 Prometheus 系列——180 个 accepted、900 个 terminal、1,980 个 issue、855 个直方图系列。任何接入点如果试图超出这个封闭乘积都会被bounded_*收敛机制拉回unknown从而保护基数不失控。流式调用的语义契约observe_stream与错误帧优先流式调用方必须把数据源通过ClientJourneyAttempt.observe_stream传递并同时提供两个语义谓词backend/utils/observability/journeys.pysuccess_when判定某个帧是成功候选。一个[DONE]帧只是成功候选——还需要流的干净耗尽clean exhaustion才最终成立failure_when必须识别每一个带内错误帧并给出有界的failure_class。检测到错误帧会立即终结terminalize且不能被后面的[DONE]或干净的流耗尽覆盖。这正是HTTP 200 响应头已提交之后才到达的错误能被检测出来的机制observe_stream在async for中先对每个 item 执行failure_when失败立即fail(failure_class)成功则置success_observed标记但不终结循环正常结束且未终结时若见过成功帧则succeed()否则fail(missing_success_class)若抛asyncio.CancelledError/ClientDisconnect/OSError则abandon_stream()以cancelled终结。_ObservedClientJourneyStream还负责在流未被耗尽包括垃圾回收析构时关闭被放弃的 attempt防止泄漏未终结的 Journey。__exit__的失败闭合语义同样值得注意正常退出上下文却未显式终结的 attempt 会被记为incomplete_attempt失败。桌面端调用边界desktop_chat覆盖/v2/chat/completions含托管网关分支与直连 Anthropic 分支。流式成功要求至少一个非空 content/tool delta、一个[DONE]帧以及干净耗尽非流式成功要求非空 assistant content 或 tool call。带内error帧、空回答、provider 错误与不完整流都不算成功。desktop_proactivity覆盖严格的/v1/desktop/proactivity/completions门面与经由遗留桌面 Gemini 代理的生成调用。严格门面只有在请求的 JSON schema 校验通过后才算成功遗留 Gemini 流需要非空候选文本加终结finishReason普通响应需要非空候选文本。按用户的 Redis 限额记为degradedquota_capped而 provider 错误与非法响应形状记为failure。写指标是 fail-open 的客户端 Journey 的指标写入是fail-open的collector 或 registry 异常在可观测性边界被吞掉绝不能改变产品响应。实现上backend/utils/observability/journeys.py 的_record_fail_open捕获所有异常、静默返回给调用方但会以 60 秒为上限节流打印client_journey_metric_record_failed警告——可观测性既不能破坏它所观测的对象也不能安静地死掉一个悄悄停止写入的 recorder 与健康但无事可报无法区分而这恰恰是这个指标家族要消灭的失败模式。事件率 vs 在途量禁止用减法推断积压原文档特别警示accepted 与 terminal 计数器是事件速率不是 in-flight gauge永远不要用两者之差去推断跨进程或重启的在途工作。如果一个 Journey 在进程 A 被接受、在进程 B 完成必须持久化接受时间用于时延、两侧导出到同一遥测后端并用持久化生命周期投影/队列 gauge 表示未完成工作——capture_finalization的listen_finalization_durable_jobs就是现成的范式它在 backend/utils/metrics.py 中定义为权威 Firestore 终结化任务按封闭持久化生命周期状态的全局计数且注释明确要求用max()聚合、绝不能用sum()否则会按副本数放大真实值。已接线的四个客户端边界live_transcription在首个非平凡音频帧后随既有实时 STT attempt 一起被接受首个非空 transcript 发出后成功provider/实时会话终结时失败其余情况取消。既有的omi_live_stt_*契约保持权威且不变。realtime_voice语音消息 WebSocket 被准入后接受非空 transcript 发出后成功provider 建立/发送或空终结回答时失败客户端断开则取消。conversation_finalization仅当 Firestore outbox 创建新任务时被接受仅当持久化终结化完整完成时成功任务 dead-letter 时失败生命周期 fencing 使任务过期时取消。既有capture_finalizationJourney 保持不变。app_webhook_delivery每个符合条件的 app/developer webhook 一次尝试仅 2xx 响应算成功拒绝、超时、目标无效、依赖熔断开启、传输/provider 错误都算失败。入队或调度发送不算成功。跨进程终结的一个实现细节record_conversation_finalization_client_terminalbackend/utils/observability/journeys.py只有在能够解析出客户端的场景才终结客户端 Journey——从任务记录的client_platform字段解析client_kind并用任务的created_at计算时延缺失平台字段或时间戳时直接跳过而不是伪造。边界语义每个 Journey 的接受与终结定义chat_response在/v2/messages持久化人类消息并准备好其 SSE 响应后被接受。服务器产出终结done:帧时记录success服务端流抛出异常为failure流在终结帧前结束消费者断开或取消为cancelled。这无法证明客户端在服务器产出响应之后真正渲染了它。pusher_session仅在/v1/trigger/listen完成 WebSocket accept 后被接受。关闭码1000与1001为success除非服务器已识别出应用层失败1011或更强的应用层失败为failure其余传输/客户端结束方式为cancelled不是产品失败。实时 STT/v4/listen收到第一个非平凡音频帧时被接受。只有在服务器已向该 WebSocket 发送第一个非空 transcript 载荷后才记录success同样无法证明客户端渲染了载荷。上游/实时会话失败或意外的 listen worker 失败为failuretranscript 发送之前的其余所有结束方式为cancelled。Provider 失败在有界标签provider outcome 与 phase下保留在omi_live_stt_terminal_failures_total对应的已接受尝试在omi_live_stt_terminal_total中有一个failure终结。capture_finalization只在 Firestore 终结化 outbox 创建新的持久化任务时接受一次。成功完成为successdead-letter 为failure生命周期被 fencing 的持久化任务为stale。既有的任务重新派发不会增加接受计数缺少有界字段的历史终结行是terminal_unknownblocked_byok刻意保持非终结nonterminal。这个 Firestore 投影就是捕获任务的分母PromQL 先跨 listener pod 取max再用clamp_min(delta(...), 0)计算移动量绝不求和复制后的全局 gauge。一个死发射dead-emission条件是有界的新accepted移动、而success/failure/stale移动全为零。对应的实现细节可以在 backend/tests/unit/test_journey_observability.py 中看到_publish_job_metrics测试断言LISTEN_FINALIZATION_DURABLE_JOBS恰好以accepted/success/failure/stale/nonterminal/blocked_byok/terminal_unknown七种状态写出而test_terminal_finalization_failure_records_once_after_dead_letter验证 dead-letter 后record_capture_finalization_terminal(failure, accepted_at)恰好调用一次。仪表盘、告警与抓取健康Resilience / Fallbacks 仪表盘Resilience / Fallbacks仪表盘保留chat_response、pusher_session、capture_finalization的通用 Journey 终结成功率面板并新增独立的实时 STT 失败/已接受尝试速率面板。通用速率刻意只使用终结success与failure两类 outcomecancelled的客户端/传输结束与stale的 fenced 捕获任务保持可见但不会伪装成应用失败。终端成功率面板在某个 Journey 出现 success-or-failure 终结之前保持空N/A——它永远不会把空闲流量展示成 0% 成功率。对应测试断言了这些面板标题与 PromQL 表达式如omi_journey_terminal_total{outcome~success|failure}与and on (journey)、max by (state) (listen_finalization_durable_jobs)见 backend/tests/unit/test_journey_observability.py。告警门槛warning 级实时 STT 产品失败告警30 分钟内至少 20 个已接受的 listener 尝试且有界的实时 STT 失败终结超过这些尝试的 10%持续 10 分钟才告警。其他产品失败告警30 分钟内至少 20 个终结 success-or-failure 结果且终结失败占比高于 10% 持续 10 分钟。没有流量 → 接受计数为零 → 不触发寻呼。独立的抓取源告警要求两个 Prometheus 作业backend-listen-metrics与pusher-metrics都存在且每个目标 up——它区分的是指标源缺失与健康但空闲的产品。Grafana 查询错误保持为错误而不是产品结果告警。上述告警规则实体化在 backend/charts/monitoring/alerts/resilience.json 中测试 backend/tests/unit/test_journey_observability.py 对每个产品规则断言了$A 20 $B 0.10结构、实时转写规则noDataState OK、其余noDataState NoData、抓取缺失规则noDataState Alerting且表达式含backend-listen-metrics|pusher-metrics。实际表达式示例来自该文件sum(increase(omi_journey_terminal_total{journeychat_response,outcomefailure}[30m])) / clamp_min(sum(increase(omi_journey_terminal_total{journeychat_response,outcome~success|failure}[30m])), 1)。抓取目标与零初始化dev/beta 与生产环境预期的经过认证的/metrics抓取目标是backend-listen-metricschat 加上 Cloud Tasks 捕获终结化 workerpusher-metricspusher 会话加上内联捕获终结化。指标子序列在进程启动时初始化因此被抓取的空闲目标导出零缺失的系列应作为抓取或部署健康问题调查而不是读成零流量。Pusher 发布流程的实时 Grafana 契约验证两个 Pusher 发布工作流在任何镜像发布或提升前都会验证实时 Grafana 供给契约。这要求受保护的MONITOR_GRAFANA_TOKEN密钥monitor.omiapi.com使用 dest repo 密钥、monitor.omi.me使用 prod 环境密钥绝不使用 TV 的GRAFANA_TOKEN并证明memory-admission 与 capture-outcome 规则的身份与表达式完全一致、规则未暂停、Prometheus 数据源健康、Pusher/backend-listen 抓取目标当前健康、Telegram 联系点路由存在。发布后的证明还额外要求两个作业的所有三个终结化指标家族都存在发布前阶段刻意不要求候选引入的指标家族存在避免引导死锁bootstrap deadlock。缺失凭据、发布后指标家族缺失、或任何 live/source 不匹配都会阻塞发布。实时转写失败告警使用 GrafananoDataState: OK在该流量出现之前空结果是被预期的不是故障。Page-class Journey SLI 告警对用户结果本身寻呼原文档用一次真实事故说明了 warning 级规则为何不够2026-08-30 的捕获终结化故障期间capture_finalization成功率为 0% 持续数小时失败约 360/h、stale 约 290/h、accepted 约 750/h而 listen pods、WebSocket、LB 流量与 5xx 速率全部保持绿色。warning 级规则只报告降级没有寻呼。以下severity: critical规则直接对用户结果寻呼全部位于Resilience组并链接对应的Omi Core Features面板RuleFires when触发条件Traffic gate流量门槛noDataStateomi-journey-capture-success-critical捕获成功占比 0.90 持续 10m30m 内 ≥ 20 个 acceptedNoDataomi-journey-pusher-success-criticalpusher 成功占比 0.90 持续 10m30m 内 ≥ 20 个 acceptedNoDataomi-journey-chat-success-criticalchat 成功占比 0.90 持续 10m30m 内 ≥ 20 个 acceptedNoDataomi-journey-capture-settle-gapaccepted − settled 50 / 1h 持续 15m1h 内 ≥ 100 个 acceptedNoDataomi-capture-oldest-nonterminal最老非终结任务年龄 3600s 持续 15m无队列年龄与流量无关Alertingomi-capture-dead-letter-surgedead letters 50 / 1h 持续 15m无每一个都是一次丢失的捕获Alertingomi-capture-finalization-memory-fence5m 内出现任何memory_fence或memory_config失败无首次 admitted-runtime 违规即可操作Alerting这些规则在 backend/charts/monitoring/alert-rules.json 中都有完整实体。以omi-journey-capture-success-critical为例其表达式为sum(increase(omi_journey_terminal_total{journeycapture_finalization,outcomesuccess}[30m])) / clamp_min(sum(increase(omi_journey_terminal_total{journeycapture_finalization,outcome~success|failure}[30m])), 1)数学条件为$A 20 $B 0.90for: 10m且标注了user_impact语音录音被接受但没有变成会话用户完全丢失捕获与safe_next_action先确认成功磁贴与 accepted-vs-settled 面板再介入。分子分母同源与安静时段防护成功占比的分子与分母都读取同一个 emitter 上同一journey的omi_journey_terminal_total并以该 journey 的omi_journey_accepted_total作为流量门槛。这样两个目标同时达成安静时段quiet hours不会误报部分 emitter 故障无法伪造一个健康的比例。而有真实 accepted 流量但终结完全停滞会通过clamp_min(..., 1)得到 0 占比并同样在此寻呼。校准依据源自 2026-08-30 事故指纹原文档给出了各阈值的初始校准并注明在规则导入时应针对生产历史进行回放验证0.90 寻呼下限Core Features 磁贴展示 95/99 阈值真实流量下持续 90% 下限就是明确的用户伤害。事故期间成功率为 0% 达数小时。30m 内 ≥ 20 accepted事故约 375 accepted/30m20 与既有 warning 规则对终结结果使用的下限一致。1h 内 gap 50 且 ≥ 100 accepted事故每小时遗留约 100 个被接受但从未结算的 Journey积压老化到 5.9 天正常在途工作在数分钟内结算因此 1h 窗口的 gap 应接近零。最老任务 3600s健康终结化在数分钟内排空事故最老任务约 5.9 天。1h 内 dead letters 50事故每天约 2.5k dead letters约 104/h每个 dead letter 都是一次耗尽所有重试的捕获。任何 memory admission 失败一个接受持久化终结化工作但无法通过 canonical-memory fence 的主机违反了其声明的能力。操作指引是停止提升halt promotion、保留持久重试队列、对比服务镜像与 PodTemplate 收据与合格版本不要为了诊断而记录或检查 transcript 内容。这条规则在 alert-rules.json 中的safe_next_action注解里被完整复述Halt promotion, preserve the durable retry queue, and restore a capability-admitted image plus config bundle before replay。Chat 存活门槛omi-journey-signal-dead的 chat 臂omi:auto:chat-agent通道在 7 个生产日内测得 min 9、p01 15、p05 23 请求/小时 20/1h只在高于 p05 的 chat 需求下要求存活。两条队列规则的noDataState: Alerting两条队列规则omi-capture-oldest-nonterminal与omi-capture-dead-letter-surge使用noDataState: Alerting因为它们对应的系列无标签且零初始化每个被抓取的 backend-listen 副本都以零导出它们因此缺失意味着 emitter 或其抓取消失——在真实流量期间这本身就值得寻呼。已知盲区这套体系的诚实边界原文档最后明确列出了一组无法消除的盲区服务器只能观察到它控制的 SSE/WS 边界无法观察客户端渲染——chat_response的done:帧与实时 STT 的 transcript 载荷都不能证明客户端真正渲染了内容。进程重启可能推迟终结指标直到持久化 worker/reconciler 恢复——重启期间的终结事件不是立即可见的。仍处于有界 reconcile 延迟内的持久化任务被刻意视为非终结nonterminal而不是立即失败——这避免了把正常重试窗口误报为失败但也意味着延迟与卡死之间需要靠年龄与 gap 类规则而非单条终结率来区分。如何在本仓库继续深入指标定义与零初始化见 backend/utils/metrics.py重点看OMI_JOURNEY_*第 57-90 行、OMI_CLIENT_JOURNEY_*第 210-256 行、LISTEN_FINALIZATION_*第 262-335 行与OMI_LIVE_STT_*第 481-526 行。封闭标签契约与client_kind解析见 backend/utils/journey_metrics_contract.py。Journey 记录实现JourneyAttempt、ClientJourneyAttempt、observe_stream、fail-open 写入见 backend/utils/observability/journeys.py。契约级单元测试见 backend/tests/unit/test_journey_observability.py 与 backend/tests/unit/test_client_journey_foundation.py。告警规则实体warning 级见 backend/charts/monitoring/alerts/resilience.jsoncritical 级见 backend/charts/monitoring/alert-rules.json。相关姊妹篇文档backend/docs/runbooks/silent-failure-detection.md 与 backend/docs/runbooks/cloud-run-metrics-ingestion.md 分别覆盖静默失败检测与指标摄取管线可与本文形成完整闭环。综上Omi 的真实流量 Journey 体系回答了可观测性领域一个核心问题当所有基础设施指标都健康时如何证明用户旅程本身没有在静默地失败。它的答案是只度量真实流量、把每个 Journey 的接受与终结边界精确到协议层事件、用封闭词表杜绝用户身份进入标签、用零初始化和noDataState区分空闲与缺失、最后用分子分母同源的 critical 规则直接对用户结果寻呼——这套组合既保证了隐私安全与基数可控又保证了在下次0% 成功率但一切绿的事故来临时寻呼一定会响起。【免费下载链接】FriendAI that sees your screen, listens to your conversations and tells you what to do项目地址: https://gitcode.com/GitHub_Trending/fr/Friend创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考