# 监控与 SLO

Raise 提供了基于 Prometheus、Alertmanager、Loki、Tempo 与 Grafana 的可观测性监控栈。你可以通过 Docker Compose 附加 `--obs` 参数拉起全套监控组件，并在 `kwork.rules.yml` 规则文件中评估服务指标与 30 天服务等级目标（SLO）。系统出厂预置的告警默认不发给任何人，需要运维人员配置接收方后生效。组织内部的「管理分析」页面仅用于用量计数，不属于这套运维监控栈。

## 谁能用

不同角色在系统监控与运维中的访问权限如下：

| 角色 / 身份 | 访问入口与权限 | 说明 |
|---|---|---|
| 部署运维方（`platform.ops`） | 经运营 SSO 访问 `*.ops.{base}:8443` | 可完整访问 Grafana、Prometheus 与 Alertmanager。负责配置告警接收方、接入外部心跳与维护系统 SLO。 |
| 租户管理员与审计员 | 组织「管理分析」 | 仅能在组织内部查看自身租户的应用使用、助理提问与管理操作统计，看不到 Grafana 与 Loki，Prometheus 应用指标中也没有租户标签。 |
| 开发者 | 应用「运行状态」 | 仅能查看自己应用的运行状态，列表中不包含租户列。 |

> **注意**
>
> Alertmanager 出厂预置的告警规则默认不路由给任何人。完成部署后，你必须复制配置文件并填入接收方信息，告警通知才会正常发出。

## 怎么打开

可观测性各组件与健康检查端点的访问地址如下（运维端点均需通过运营 SSO 认证，监听 8443 端口）：

| 组件 / 检查端点 | 访问地址或方式 | 说明 |
|---|---|---|
| Grafana | `https://grafana.ops.{base}:8443` | 运维监控仪表盘。登录需通过运营 SSO（oauth2-proxy），环境变量对应 `GF_SERVER_ROOT_URL`。 |
| Prometheus | `https://prometheus.ops.{base}:8443` | 指标采集与告警规则评估控制台。 |
| Alertmanager | `https://alertmanager.ops.{base}:8443` | 告警路由、静默与通知管理控制台。 |
| Loki / Tempo | Grafana Explore 数据源 | 分布式日志与链路追踪数据源，在 Grafana 的 Explore 页面中直接查询。 |
| Raise 内部指标 | 容器内 `:8009/metrics` | Raise 内部指标暴露端点，已由 `obs` 监控栈自动抓取。 |
| 内部存活探针 | 内部 8009 端口访问 `/livez` | 正常时返回 HTTP 200 与文本 `ok`。 |
| 内部就绪探针 | 内部 8009 端口访问 `/readyz` | 正常时返回 HTTP 200 与文本 `ready`；若数据库或密钥后端未就绪则返回 503。也可以执行 `kwork healthcheck` 命令检查。 |
| 对外健康检查 | 对外访问 `/healthz` | 正常时返回 HTTP 200 与文本 `ok`。 |

你可以通过以下部署参数开启或联动观测能力：
- 执行 `./install.sh --obs`（或传入 `--shell` 且所选环境包包含观测）拉起 Prometheus、Alertmanager、Loki、Tempo 与 Grafana 容器。
- 若需要查看大模型调用链路并在看板中获得 Langfuse 链接，需在安装时附加 `--obs-llm` 参数。
- 在 Kubernetes / Helm 部署中，通过设置 `monitoring.serviceMonitor.enabled=true` 与 `monitoring.prometheusRule.enabled=true` 启用指标采集与规则加载（两者使用同一份规则文件）。

> **提示**
>
> 代码仓库出厂不提供外部拨测工具。建议从集群外部网络每分钟定期拨测以下两个端点：
> - `https://app.{base}/brand.json`
> - `https://id.{base}/.well-known/openid-configuration`

## 界面一览

### Grafana 监控控制台

Raise 没有面向租户的监控产品界面。Grafana 专供部署运维人员使用，预置了 4 个核心数据源：

| 预置数据源 | 数据类型 | 说明 |
|---|---|---|
| Prometheus | 监控指标 | 存储并查询服务与系统指标数据。 |
| Tempo | 调用链追踪 | 存储并检索分布式链路追踪信息。 |
| Loki | 服务日志 | 收集并查询容器结构化日志。 |
| Alertmanager | 告警信息 | 展示当前触发的告警与静默状态。 |

在 Grafana 的 kwork 目录下，系统出厂预置了 2 个监控看板：

| 预置看板名称 | 所属目录 | 说明 |
|---|---|---|
| 「kwork 概览」 | kwork | 展示系统核心运行指标、吞吐量与请求错误率。 |
| 「LLM 网关」 | kwork | 展示模型网关 Bifrost 的调用量、延迟与失败率。若开启 `--obs-llm`，看板中提供跳转至 Langfuse 与 Bifrost 的链接。 |

### Alertmanager 告警控制台

在 Alertmanager 界面（`https://alertmanager.ops.{base}:8443`）中管理告警：

| 区域 / 元素 | 说明 |
|---|---|
| 告警列表 | 展示当前处于触发状态的各项告警。出厂状态下告警在此展示，但不外发。 |
| 静默规则 | 查看与配置告警静默规则，屏蔽已知的维护期告警。 |

### 组织「管理分析」界面

租户管理员在 [工作台](/guide/workspace) 中打开「管理分析」：

| 统计项目 | 说明 |
|---|---|
| 应用使用 | 统计本组织内部各应用的使用次数。 |
| 助理提问 | 统计本组织成员向助手的提问总数。 |
| 已应用变更 | 统计本组织通过草稿已应用的配置变更次数。 |
| 管理操作 | 统计本组织管理员执行的管理操作记录。 |
| 时间筛选 | 支持筛选 1–90 天的时间跨度。此界面用于业务用量计数，不是运维 SLO 看板。 |

## 常用操作

### 启用可观测性栈

1. 在服务器终端中，执行带有 `--obs` 参数的安装脚本 `./deploy/install.sh --obs`。执行后系统拉起 Prometheus、Alertmanager、Loki、Tempo 与 Grafana 容器。
2. 在浏览器中，打开 Grafana 控制台地址 `https://grafana.ops.{base}:8443`。页面通过运营 SSO（oauth2-proxy）完成登录认证，Grafana 信任请求头中的邮箱并进入监控界面。

### 配置告警接收方

1. 在服务器终端中，将出厂示例配置文件 `deploy/compose/config/alertmanager.yml` 复制到代码仓库外部保存。复制后获得可独立编辑的告警配置文件。
2. 在编辑器中，打开复制出的配置文件，填入企业微信机器人、邮件 SMTP 服务器或 Webhook 接收地址。保存后完成接收通道配置。
3. 在环境配置文件 `deploy/compose/.env` 中，设置 `ALERTMANAGER_CONFIG` 指向自定义配置文件路径，设置 `ALERTMANAGER_SECRETS` 指向密钥目录。保存后配置生效。
4. 在服务器终端中，执行命令 `docker compose --profile obs up -d alertmanager` 重启 Alertmanager 容器。重启后系统自动按新配置向指定接收方推送告警。

### 接入 Watchdog 外部心跳

1. 在外部监控平台（如 healthchecks.io 或 Opsgenie）中，创建一条心跳检查项。创建后获得心跳上报 Webhook 地址。
2. 在自定义 Alertmanager 配置文件中，将 `Watchdog` 告警的路由目标配置为该 Webhook 地址。保存后 Alertmanager 开始向外部定期推送心跳。
3. 在外部监控平台中，配置心跳丢失告警规则。当 Prometheus 或 Alertmanager 自身宕机时，外部平台因未收到心跳而发出报警。

### 校验告警规则与配置

1. 在代码仓库根目录终端中，执行命令 `make alerts-check`。
2. 终端调用 `promtool` 与 `amtool` 校验规则文件与配置文件。校验通过后终端提示无语法错误，表明 41 条规则加载正常。

### 调整单机环境 SLO 告警阈值

1. 在服务器终端中，打开告警规则配置文件 `deploy/compose/config/prometheus/kwork.rules.yml`。
2. 在文件中找到 `availability` 错误预算规则，将预算参数从 `0.001` 修改为 `0.005`。修改后可用性目标由 99.9% 调整为适合单机环境的 99.5%。
3. 在代码仓库根目录终端中，执行命令 `make alerts-check` 校验修改后的规则。校验通过后完成规则验证。
4. 在服务器终端中，重启或重载 Prometheus 容器。重载后系统按 99.5% 的质量目标评估告警。

### 巡检非监控采集项目

1. 在集群外部服务器中，配置定时任务每分钟请求 `https://app.{base}/brand.json` 与 `https://id.{base}/.well-known/openid-configuration`。请求失败时立即发出外部拨测报警。
2. 在运维管理终端中，每日执行全租户审计链验证（verify）操作。验证失败时立即定级为 P1 事故处理。
3. 在网关日志中，检查 TLS 证书的申请（`obtain`）与续期（`renew`）记录。当证书剩余有效期小于 14 天时跟进处理。
4. 在服务器终端中，检查 `pg-backup` 备份容器的运行健康状态。每季度组织一次数据恢复演练，演练记录归档备查。详细备份说明参见 [备份](/deploy/backup)。

## 状态说明

### 服务等级目标（SLO）

系统在告警规则文件中定义了 30 天周期的 SLO 监控目标（出厂规则默认按 99.9% 编写）：

| SLO 类别 | 服务水平指标（SLI）说明 | 目标值 | 错误预算 |
|---|---|---|---|
| 可用性 | 公共入口 HTTP 5xx 响应比例 | ≥ 99.9% | 0.1%（30 天内允许约 43 分钟不可用） |
| 登录服务 | 登录相关接口 HTTP 5xx 响应比例（HTTP 4xx 错误不算在内） | ≥ 99.9% | 0.1% |
| 草稿应用 | 草稿应用接口 HTTP 5xx 响应比例 | ≥ 99% | 1% |
| API 延迟 | 公共入口 P95 延迟（不含长耗时流式推送、数据同步与草稿变更路由） | ≤ 300 ms | 超出阈值直接告警，不扣减错误预算 |
| 草稿应用延迟 | 草稿应用路由 P95 延迟 | ≤ 2 s | 超出阈值直接告警，不扣减错误预算 |
| 审计写入 | 审计写入失败计数与写入耗时 P99 | 0 次失败；P99 ≤ 250 ms | 零容忍指标，出现失败立即告警 |

**指标统计口径展开说明**

- 指标统计只计算 Raise 自身返回的请求响应。
- 当 Raise 整体宕机时，网关返回的 HTTP 502 错误由 `KworkDown` 与 `KworkNotReady` 告警规则覆盖。
- Private 单机环境（N1）的质量目标为 99.5%。若要在单机环境下按 99.5% 触发告警，需把规则文件中的预算参数从 0.001 改为 0.005。

### 告警规则清单

系统出厂预置了 16 条核心监控告警规则：

| 告警名称 | 级别 | 触发条件 |
|---|---|---|
| `KworkErrorBudgetBurnFast` | critical | 1 小时内消耗 30 天预算的 2%（且近 5 分钟仍在持续消耗），或 6 小时内消耗 5%。 |
| `KworkErrorBudgetBurnSlow` | warning | 1 天内消耗 30 天预算的 10%，或 3 天内消耗 10%（快烧告警触发时被自动抑制）。 |
| `KworkApiLatencyHigh` | warning | API 请求 P95 延迟 > 300 ms，持续 15 分钟。 |
| `KworkDraftApplyLatencyHigh` | warning | 草稿应用 P95 延迟 > 2 s，持续 15 分钟。 |
| `KworkDown` | critical | 抓取 Raise 实例连续失败超过 2 分钟。 |
| `KworkTargetMissing` | critical | Prometheus 中连续 5 分钟没有 Raise 抓取目标（此时其它 Raise 告警全部失效）。 |
| `KworkNotReady` | critical | 就绪指标为 0 持续 1 分钟（对应就绪探针检测到数据库或密钥后端异常）。 |
| `KworkRestarting` | warning | 容器在 15 分钟内重启超过 2 次。 |
| `KworkDatabasePoolSaturated` | warning | 数据库连接池占用率 > 80%，持续 10 分钟。 |
| `KworkAuditAppendFailing` | critical | 5 分钟内出现审计写入失败。 |
| `KworkAuditAppendSlow` | warning | 审计写入耗时 P99 > 250 ms，持续 15 分钟。 |
| `KworkAgentDown` | warning | 连续 5 分钟抓取不到 Agent（未部署 Agent 时应关闭对应抓取配置）。 |
| `KworkModelCallsFailing` | warning | 模型调用失败率 > 10%，持续 10 分钟。 |
| `KworkModelGatewayDown` | warning | 连续 5 分钟抓取不到模型网关 Bifrost。 |
| `Watchdog` | none | 永久处于触发状态，作为向外部监控系统发送的心跳信号。 |

告警抑制机制：
- 快速燃烧告警（`KworkErrorBudgetBurnFast`）会抑制同一 SLO 的慢速燃烧告警（`KworkErrorBudgetBurnSlow`）。
- 当 Raise 实例下线（`KworkDown`）时，系统会自动抑制未就绪、预算燃烧与延迟告警。

### 依赖组件故障影响

当依赖组件异常时，系统的故障表现与排查定位依据如下：

| 故障组件 | 业务影响 | 监控表现与排查依据 |
|---|---|---|
| PostgreSQL | 全部业务 API 接口调用失败。 | 触发 `KworkNotReady` 告警。 |
| Zitadel | 新成员登录、开通租户与修改成员操作失败；已签发的访问令牌在过期前仍可继续使用。 | 身份认证与权限管理功能受阻。 |
| OpenBao | 处于封存状态时，Raise 处于未就绪状态。 | 就绪探针返回 503 错误。 |
| 对象存储 | 文件上传与下载接口失败。 | 存储相关操作报错。 |
| Redis | 请求限流策略退回到每个副本单机独立计数；服务启动时连不上 Redis 则 Raise 无法启动。 | 限流精度降级或容器无法启动。 |
| 网关 | 公网服务全部中断。Prometheus 位于内部网络无法感知网关宕机，需依赖外部拨测。 | 外部拨测端点请求失败。 |
| oauth2-proxy | 运维管理工具与后台无法登录进入。 | 运营后台页面打不开。 |
| kwork-agent / Temporal | 助手对话与后台定时任务不可用。 | Agent 任务停止运行。 |
| Bifrost | 全部大模型调用请求失败。 | 触发 `KworkModelGatewayDown` 告警。 |
| Gotenberg | PDF 文档导出与生成失败。 | PDF 打印转换报错。 |
| Cube / Superset / ClickHouse / Langfuse | 仅影响数据分析与模型链路追踪功能，不影响核心业务运行。 | 辅助面板无数据。 |
| Prometheus / Alertmanager | 监控指标采集与告警推送全部失效。 | 外部监控系统检测到 `Watchdog` 心跳中断。 |
| Loki / Tempo / Grafana | 仅影响日志查询、链路排查与可视化展示，不影响核心业务运行。 | 运维控制台无法查看。 |

## 让助手帮你做

Raise 目前未提供运维相关的助手操作指令（Agent op）。租户内部的助手也无权访问 Grafana 监控大盘，不能读取底层监控指标。

## 设置

系统可观测性涉及的环境变量与部署配置项如下：

| 配置项 | 作用说明 | 默认值 |
|---|---|---|
| `KWORK_LOKI_URL` | 指定 Raise 向 Loki 推送日志的地址。 | 启用 `--obs` 时为 `http://loki:3100/loki/api/v1/push` |
| `ALERTMANAGER_CONFIG` | 指定 Alertmanager 接收方配置文件的宿主机路径。 | 出厂预置的示例配置文件（默认不外发） |
| `ALERTMANAGER_SECRETS` | 指定 Alertmanager 接收方密钥目录的宿主机路径。 | `./config/alertmanager-secrets` |
| `monitoring.labels`（Helm） | 在 Kubernetes 中指定供 Prometheus Operator 匹配规则的标签。 | 常见配置为 `release: kube-prometheus-stack` |

数据流与联动配置：
- 应用网关请求计数会同步输出至 Prometheus（无租户标签）与租户内部的「管理分析」日表。
- Grafana 的「LLM 网关」看板中配置了指向 Langfuse 与 Bifrost 的跳转链接。
- Raise 统一输出结构化 JSON 日志，日志包含 `request_id`、`route`、`status` 与 `ms` 字段，并通过 `KWORK_LOKI_URL` 发送至 Loki。

## 注意事项

- **指标脱敏与隐私保护**：应用监控指标中不记录具体请求路径、请求头、请求正文、认证令牌或错误详细文本。
- **采集累加与落库间隔**：网关指标在内存中累加计算，每 15 秒向数据库批量写入一次。若容器发生异常崩溃，最近 15 秒内的指标数据将会丢失。
- **联邦自托管应用限制**：联邦自托管应用由于不经过平台网关，监控栈中不包含此类应用的流量与延迟数据。
- **百分位数估算口径**：延迟指标的百分位数取 Prometheus 直方图桶的上界，计算数值不会低估实际延迟。
- **审计归档限制**：租户的审计日志在执行归档出库后，不再纳入「管理分析」的数据统计。
- **登录活跃度缺失**：用户登录认证流程由独立的身份服务处理，应用监控指标中不包含成员登录活跃度数据。
- **管理边界隔离**：Grafana 监控控制台从不进行白标定制，从不向租户开放访问。

## 目前不支持

- **内置外部拨测**：代码仓库出厂不提供外部拨测服务，需要你在集群外部网络自行搭建定时拨测。
- **通知通路出厂验证**：系统在出厂安装时不自动校验告警能否真实送达企业微信或邮件通道。
- **Kubernetes 现网运行验证**：Helm 部署中的 ServiceMonitor 与 PrometheusRule 模板仅经过本地渲染验证，未在部署了 Prometheus Operator 的生产集群中实测，实际使用需以现网环境为准。

## 常见问题

### 为什么系统触发了告警，企业微信或邮箱却没有收到通知？
Alertmanager 出厂预置的规则默认不把告警发送给任何人。你必须将 `deploy/compose/config/alertmanager.yml` 复制到代码仓库外部，在文件中填入企业微信机器人、邮件或 Webhook 配置，并在 `.env` 中通过 `ALERTMANAGER_CONFIG` 与 `ALERTMANAGER_SECRETS` 指定配置路径后重启 Alertmanager 容器。

### 为什么在 Grafana 中无法按租户筛选指标？
Prometheus 采集的应用指标出于数据隐私与时序基数控制考量，未添加租户标签。各组织的业务使用统计请登录 [工作台](/guide/workspace) 后进入「管理分析」查看。

### 网关宕机导致公网不可用时，Prometheus 会报警吗？
不会。Prometheus 部署在内部网络并直接抓取内部服务，公网网关发生故障时内部指标抓取通常依然正常。你需要在集群外部网络配置定时拨测任务，每分钟请求 `https://app.{base}/brand.json` 与 `https://id.{base}/.well-known/openid-configuration`，以及时发现公网网关故障。

### 延迟百分位数指标是否会低于实际值？
不会。Raise 监控中的延迟百分位数采用直方图桶的上界进行计算，计算结果只会偏保守，不会低估实际延迟。

### 主机异常崩溃后，为什么「管理分析」中的统计数据会有些许偏差？
网关指标在内存中累加，每 15 秒向数据库批量写入一次。若容器发生意外崩溃，最近 15 秒内尚未写入数据库的数据会丢失。
