Files
moeka-project/apps/server/docs/ai-context/observability-conventions.md
T
2026-04-02 04:24:04 +08:00

160 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Observability Conventions
这份约定定义 AIRI 服务端新增 trace / metric attributes 时应该遵守的命名规则,目标是减少自定义前缀扩散,并让 Grafana / Tempo / Loki 查询尽量对齐 OpenTelemetry 语义约定。
## 总原则
- 能直接映射到 OpenTelemetry semantic conventions 的字段,优先使用标准字段。
- 不能映射到标准字段、但确实属于 AIRI 业务语义的字段,统一放到 `airi.*` 命名空间下。
- 不要新增新的顶级前缀,例如 `llm.*``gateway.*``telegram.*` 之类的 attribute key。
- span name、event name、metric name 不等于 attribute key;是否迁移它们要单独评估兼容性。
- 代码里不要继续散落新的 observability key 字符串字面量;统一从 [packages/server-shared/src/observability.ts](/packages/server-shared/src/observability.ts) 引用。
## 标准字段优先级
### GenAI
优先使用:
- `GEN_AI_ATTR_OPERATION_NAME`
- `GEN_AI_ATTR_REQUEST_MODEL`
- `GEN_AI_ATTR_USAGE_INPUT_TOKENS`
- `GEN_AI_ATTR_USAGE_OUTPUT_TOKENS`
- `SERVER_ATTR_ADDRESS`
- `SERVER_ATTR_PORT`
适用场景:
- chat completion
- embeddings
- 其他能明确归类到 GenAI 上游调用的请求
注意:
- 当前 OpenTelemetry GenAI semantic conventions 仍处于 `Development` 状态,因此只在“语义明确匹配”时采用。
- 没有明确标准归属的字段不要硬塞进 `gen_ai.*`
### Database / Redis
优先使用:
- `db.system.name`
- `db.operation.name`
- `db.namespace`
- `db.query.text`
- `db.response.status_code`
- `server.address`
- `server.port`
Redis 相关优先复用 instrumentation 自动产生的标准属性,不要重复造一套并行命名。
## AIRI 自定义字段
以下场景使用 `airi.*`
- 计费或余额语义
- 仅 AIRI 内部存在的流式控制字段
- 临时调试但仍需要进入可观测系统的业务字段
当前示例:
- `AIRI_ATTR_BILLING_FLUX_CONSUMED`
- `AIRI_ATTR_GEN_AI_STREAM`
- `AIRI_ATTR_GEN_AI_STREAM_INTERRUPTED`
- `AIRI_ATTR_GEN_AI_OPERATION_KIND`
- `AIRI_ATTR_GEN_AI_INPUT_MESSAGES`
- `AIRI_ATTR_GEN_AI_INPUT_TEXT`
- `AIRI_ATTR_GEN_AI_OUTPUT_TEXT`
## Metric Name 策略
当前 `apps/server` 仍保留以下 metric name
- `llm.request.duration`
- `llm.request.count`
- `llm.tokens.prompt`
- `llm.tokens.completion`
- `flux.consumed`
这是有意为之,不是遗漏。
原因:
- metric name 改动比 attribute 改动更容易破坏现有 Prometheus 查询、Grafana 面板和告警。
- 目前更高价值的是先统一 metric attributes,使查询维度稳定。
- 如需迁移 metric name,应该走兼容迁移方案,而不是在普通功能改动里直接重命名。
## Grafana / Prometheus 查询策略
面板和告警查询优先依赖 metric labels,对齐我们已经统一的 attributes。
### GenAI 面板应该查什么
优先使用这些 Prometheus label
- `gen_ai_request_model`
- `gen_ai_operation_name`
- `airi_gen_ai_operation_kind`
- `http_response_status_code`
说明:
- Prometheus 暴露时会把 attribute key 里的 `.` 转成 `_`,所以 `gen_ai.request.model` 会变成 `gen_ai_request_model`
- `gen_ai_operation_name` 适合 chat、embeddings 这类有明确 semconv 的操作。
- `airi_gen_ai_operation_kind` 适合当前没有明确 semconv 的 AIRI 自定义操作类型,例如 `tts``asr`
### 不再新增使用的旧查询维度
新增 dashboard、录制规则、告警时,不要再新增依赖这些旧 label:
- `model`
- `type`
旧面板可以渐进迁移,不要求一次性全部替换,但新改动必须直接使用新标签。
### 当前已落地的 dashboard 例子
[apps/server/otel/grafana/dashboards/airi-server-overview-cloud.json](/apps/server/otel/grafana/dashboards/airi-server-overview-cloud.json) 已经按以下方式查询:
- Request rate by model: `gen_ai_request_model`
- Request rate by operation: `gen_ai_operation_name` + `airi_gen_ai_operation_kind`
- Latency by model: `gen_ai_request_model`
- Flux consumed by model: `gen_ai_request_model`
- Token throughput by model: `gen_ai_request_model`
如果未来新增本地 dashboard 或新的 cloud dashboard,默认按这一套 label 维度来。
## Span Name 策略
span name 目前允许保留业务可读格式,例如:
- `llm.gateway.chat`
- `llm.gateway.tts`
- `llm.gateway.asr`
原因:
- span name 主要服务于人工浏览和局部检索。
- 语义筛选应优先依赖 attributes,而不是依赖 span name 文本。
如果未来统一 span name,也应保证查询主要依赖 `gen_ai.*` / `db.*` / `airi.*` attributes。
## 修改前检查
新增 observability 字段前,先问自己:
1. 这个字段能否映射到已有 OTel semconv
2. 如果不能,它是否明确属于 AIRI 业务语义?
3. 如果属于 AIRI,是否应该挂到 `airi.*`,而不是新造顶级前缀?
4. 我改的是 attribute key 还是 metric name / span name
5. 如果是 metric name,是否已经评估 Prometheus / Grafana / alerting 兼容性?
6. 如果要改 dashboard,我是否优先用了 `gen_ai_request_model``gen_ai_operation_name``airi_gen_ai_operation_kind`,而不是旧的 `model` / `type`
## 当前参考实现
- [packages/server-shared/src/observability.ts](/packages/server-shared/src/observability.ts)
- [apps/server/src/routes/v1completions.ts](/apps/server/src/routes/v1completions.ts)
- [apps/server/src/libs/otel.ts](/apps/server/src/libs/otel.ts)
- [services/telegram-bot/src/llm/actions.ts](/services/telegram-bot/src/llm/actions.ts)
- [services/telegram-bot/src/bots/telegram/agent/actions/read-message.ts](/services/telegram-bot/src/bots/telegram/agent/actions/read-message.ts)