feat(observability): add structured application logging
Emit correlated JSON logs from the API and FunASR services, propagate request IDs to the client, and configure bounded opt-in Docker logging. Document the host-wide Grafana/Loki query workflow and keep observability deployment ownership outside the application repository.
This commit is contained in:
174
docs/observability-runbook.md
Normal file
174
docs/observability-runbook.md
Normal file
@@ -0,0 +1,174 @@
|
||||
# 中央日志接入与查询手册
|
||||
|
||||
教学反馈服务通过容器标签接入宿主机中央观测栈。本项目不包含也不启停 Loki、Alloy 或
|
||||
Grafana;中央栈位于 `/home/shay/data/docker-service/observability`,Grafana 地址为
|
||||
`http://192.168.193.237:39300`。
|
||||
|
||||
## 登录 Grafana
|
||||
|
||||
1. 在可信局域网或已接入该主机网络的浏览器中打开 `http://192.168.193.237:39300`。
|
||||
2. 用户名使用 `admin`。
|
||||
3. 初始密码读取中央栈的
|
||||
`/home/shay/data/docker-service/observability/.env` 中的 `GRAFANA_ADMIN_PASSWORD`。
|
||||
|
||||
需要在目标机终端确认初始密码时使用:
|
||||
|
||||
```bash
|
||||
sed -n 's/^GRAFANA_ADMIN_PASSWORD=//p' /home/shay/data/docker-service/observability/.env
|
||||
```
|
||||
|
||||
不要把密码粘贴到 issue、提交信息、聊天记录或截图中。如果已经在 Grafana 页面修改过密码,
|
||||
应使用修改后的密码;`.env` 只保证记录首次创建管理员时使用的值。
|
||||
|
||||
## 发布与接入检查
|
||||
|
||||
业务镜像构建时注入版本信息:
|
||||
|
||||
```bash
|
||||
export APP_VERSION="$(git describe --tags --always)"
|
||||
export GIT_SHA="$(git rev-parse --short HEAD)"
|
||||
docker compose -f compose.deploy.yml config -q
|
||||
docker compose -f compose.deploy.yml up -d --build --force-recreate
|
||||
docker compose -f compose.deploy.yml ps
|
||||
```
|
||||
|
||||
仅修改采集标签或日志轮转时不需要构建镜像:
|
||||
|
||||
```bash
|
||||
docker compose -f compose.deploy.yml up -d --force-recreate --no-build api funasr
|
||||
```
|
||||
|
||||
确认运行容器配置:
|
||||
|
||||
```bash
|
||||
docker inspect teaching-feedback-api-1 --format '{{json .HostConfig.LogConfig}}'
|
||||
docker inspect teaching-feedback-api-1 --format '{{json .Config.Labels}}'
|
||||
docker inspect teaching-feedback-funasr-1 --format '{{json .HostConfig.LogConfig}}'
|
||||
docker inspect teaching-feedback-funasr-1 --format '{{json .Config.Labels}}'
|
||||
curl -fsS http://127.0.0.1:39180/health
|
||||
```
|
||||
|
||||
预期日志驱动为 `local`,`max-size=20m`、`max-file=5`;两个服务都应包含
|
||||
`observability.logs=true`、`observability.application=teaching-feedback` 和
|
||||
`observability.environment=lan`。
|
||||
|
||||
## 使用预置仪表盘
|
||||
|
||||
登录后打开 `Dashboards`,进入 `Host Observability / Host Service Logs`,然后设置:
|
||||
|
||||
- `Application`:`teaching-feedback`
|
||||
- `Environment`:`lan`
|
||||
- `Service`:按需选择 `api`、`funasr` 或 `All`
|
||||
- 右上角时间范围:复现问题时优先选择最近 5 至 30 分钟
|
||||
|
||||
仪表盘适合浏览和筛选;需要精确关联请求或比较版本时,打开 `Explore`,数据源选择 `Loki`。
|
||||
|
||||
## 常用 LogQL
|
||||
|
||||
查看教学反馈的全部日志:
|
||||
|
||||
```logql
|
||||
{application="teaching-feedback"}
|
||||
```
|
||||
|
||||
按服务、级别和文本筛选:
|
||||
|
||||
```logql
|
||||
{application="teaching-feedback", service="api"} | json
|
||||
{application="teaching-feedback", service="funasr"} | json
|
||||
{application="teaching-feedback", level=~"WARN|ERROR"}
|
||||
{application="teaching-feedback"} |= "database"
|
||||
```
|
||||
|
||||
按 HTTP 状态和耗时寻找优化目标:
|
||||
|
||||
```logql
|
||||
{application="teaching-feedback", service="api"} | json | status >= 500
|
||||
{application="teaching-feedback", service="api"} | json | latency_ms >= 1000
|
||||
{application="teaching-feedback", service="api"} | json | event="http_request_finished"
|
||||
```
|
||||
|
||||
按关联 ID 追踪一次请求或转录任务:
|
||||
|
||||
```logql
|
||||
{application="teaching-feedback", service="api"} | json | request_id="<request-id>"
|
||||
{application="teaching-feedback", service="api"} | json | feedback_session_id="<session-id>"
|
||||
{application="teaching-feedback", service="api"} | json | lesson_id="<lesson-id>"
|
||||
{application="teaching-feedback", service="api"} | json | segment_id="<segment-id>"
|
||||
{application="teaching-feedback", service="funasr"} | json | segment_id="<segment-id>"
|
||||
```
|
||||
|
||||
按部署版本确认问题发生在哪份代码:
|
||||
|
||||
```logql
|
||||
{application="teaching-feedback"} | json | app_version="0.2.0"
|
||||
{application="teaching-feedback"} | json | git_sha="<git-sha>"
|
||||
```
|
||||
|
||||
`request_id`、`segment_id`、`git_sha` 等字段位于 JSON 正文,不能直接放进流选择器的 `{...}`,
|
||||
也不能新增为 Loki 标签。查询无结果时先扩大时间范围,再从只包含 `application` 的查询逐步增加条件。
|
||||
|
||||
## 用日志定位代码
|
||||
|
||||
优化或修复代码时采用以下流程:
|
||||
|
||||
1. 复现问题,记录发生时间和小程序错误界面显示的 `request_id`。
|
||||
2. 用 `request_id` 查询 API 的完整事件序列,确认状态码、`event`、`latency_ms` 和
|
||||
`error_class`。
|
||||
3. 涉及录音时,从 API 日志取得 `segment_id`,分别查询 API worker 和 FunASR,判断耗时发生在
|
||||
排队、上传、推理还是结果写回阶段。
|
||||
4. 用 `app_version` 和 `git_sha` 确认运行代码版本,避免根据旧镜像日志修改新代码。
|
||||
5. 修改后使用相同路径复现并比较事件数量、失败分类和耗时,不以“没有 ERROR”代替性能验收。
|
||||
|
||||
日志事件主要对应以下代码:
|
||||
|
||||
- HTTP 请求开始、结束、请求 ID:`server/src/main.rs`
|
||||
- API 错误分类和响应:`server/src/error.rs`、`server/src/recording_routes.rs`
|
||||
- 转录队列、租约、重试和状态写回:`server/src/transcription_worker.rs`
|
||||
- API 到本地 ASR 的请求关联:`server/src/speech.rs`
|
||||
- FunASR 请求和推理耗时:`asr-service/app.py`
|
||||
- 小程序请求 ID 展示与复制:`utils/api.ts` 及各页面的错误处理代码
|
||||
|
||||
## 历史范围
|
||||
|
||||
中央栈首次接入时回采了当时仍存在的 Docker 容器日志。2026-07-22 验收时可查询到的最早记录为:
|
||||
|
||||
- API:2026-07-22 11:48:42(北京时间)
|
||||
- FunASR:2026-07-22 11:53:42(北京时间)
|
||||
|
||||
已删除容器中更早的日志无法恢复。Loki 当前保留期为 14 天,Docker 本地日志还受到
|
||||
`20m x 5` 轮转限制,因此长期比较应记录 `git_sha`、问题时间和关键查询结果,而不能假设日志永久存在。
|
||||
|
||||
## 故障定位
|
||||
|
||||
应用健康但 Grafana 无日志:
|
||||
|
||||
1. 检查业务容器是否具有采集标签。
|
||||
2. 检查业务容器是否持续向 stdout/stderr 输出日志。
|
||||
3. 检查中央栈运行状态;命令见中央目录 `README.md`。
|
||||
4. 使用 `{application="teaching-feedback"}` 查询,避免一开始叠加过多过滤条件。
|
||||
|
||||
Grafana/Loki 不可用时,不要重启或回滚业务容器来尝试修复中央栈。先确认:
|
||||
|
||||
```bash
|
||||
curl -fsS http://127.0.0.1:39180/health
|
||||
docker compose -f compose.deploy.yml ps
|
||||
docker compose -f compose.deploy.yml logs --since 10m api funasr
|
||||
```
|
||||
|
||||
如果本地 Docker 日志仍正常,则问题属于中央观测栈。中央栈的启停、数据卷、备份、恢复和升级
|
||||
统一由 `/home/shay/data/docker-service/observability/README.md` 管理。
|
||||
|
||||
Grafana 不可用时,可以先用 Docker 本地日志继续定位:
|
||||
|
||||
```bash
|
||||
docker compose -f compose.deploy.yml logs --since 30m api funasr
|
||||
```
|
||||
|
||||
不要为了临时查询而把 Loki `3100` 或 Alloy `12345` 发布到宿主机。
|
||||
|
||||
## 应用侧回滚
|
||||
|
||||
结构化日志代码出现回归时,回滚对应代码并重建业务镜像。仅日志驱动不兼容时,修改
|
||||
`compose.deploy.yml` 后必须 `--force-recreate`;普通 restart 不会更新容器日志驱动。任何应用侧
|
||||
回滚都不得删除中央 Loki 或 Grafana 数据卷。
|
||||
Reference in New Issue
Block a user