Files
teaching-feedback-assistant/docs/observability-runbook.md
shay7sev a875fe9f63 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.
2026-07-22 13:52:40 +08:00

6.9 KiB
Raw Blame History

中央日志接入与查询手册

教学反馈服务通过容器标签接入宿主机中央观测栈。本项目不包含也不启停 Loki、Alloy 或 Grafana中央栈位于 /home/shay/data/docker-service/observabilityGrafana 地址为 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

需要在目标机终端确认初始密码时使用:

sed -n 's/^GRAFANA_ADMIN_PASSWORD=//p' /home/shay/data/docker-service/observability/.env

不要把密码粘贴到 issue、提交信息、聊天记录或截图中。如果已经在 Grafana 页面修改过密码, 应使用修改后的密码;.env 只保证记录首次创建管理员时使用的值。

发布与接入检查

业务镜像构建时注入版本信息:

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

仅修改采集标签或日志轮转时不需要构建镜像:

docker compose -f compose.deploy.yml up -d --force-recreate --no-build api funasr

确认运行容器配置:

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

预期日志驱动为 localmax-size=20mmax-file=5;两个服务都应包含 observability.logs=trueobservability.application=teaching-feedbackobservability.environment=lan

使用预置仪表盘

登录后打开 Dashboards,进入 Host Observability / Host Service Logs,然后设置:

  • Applicationteaching-feedback
  • Environmentlan
  • Service:按需选择 apifunasrAll
  • 右上角时间范围:复现问题时优先选择最近 5 至 30 分钟

仪表盘适合浏览和筛选;需要精确关联请求或比较版本时,打开 Explore,数据源选择 Loki

常用 LogQL

查看教学反馈的全部日志:

{application="teaching-feedback"}

按服务、级别和文本筛选:

{application="teaching-feedback", service="api"} | json
{application="teaching-feedback", service="funasr"} | json
{application="teaching-feedback", level=~"WARN|ERROR"}
{application="teaching-feedback"} |= "database"

按 HTTP 状态和耗时寻找优化目标:

{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 追踪一次请求或转录任务:

{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>"

按部署版本确认问题发生在哪份代码:

{application="teaching-feedback"} | json | app_version="0.2.0"
{application="teaching-feedback"} | json | git_sha="<git-sha>"

request_idsegment_idgit_sha 等字段位于 JSON 正文,不能直接放进流选择器的 {...} 也不能新增为 Loki 标签。查询无结果时先扩大时间范围,再从只包含 application 的查询逐步增加条件。

用日志定位代码

优化或修复代码时采用以下流程:

  1. 复现问题,记录发生时间和小程序错误界面显示的 request_id
  2. request_id 查询 API 的完整事件序列,确认状态码、eventlatency_mserror_class
  3. 涉及录音时,从 API 日志取得 segment_id,分别查询 API worker 和 FunASR判断耗时发生在 排队、上传、推理还是结果写回阶段。
  4. app_versiongit_sha 确认运行代码版本,避免根据旧镜像日志修改新代码。
  5. 修改后使用相同路径复现并比较事件数量、失败分类和耗时,不以“没有 ERROR”代替性能验收。

日志事件主要对应以下代码:

  • HTTP 请求开始、结束、请求 IDserver/src/main.rs
  • API 错误分类和响应:server/src/error.rsserver/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 验收时可查询到的最早记录为:

  • API2026-07-22 11:48:42北京时间
  • FunASR2026-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 不可用时,不要重启或回滚业务容器来尝试修复中央栈。先确认:

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 本地日志继续定位:

docker compose -f compose.deploy.yml logs --since 30m api funasr

不要为了临时查询而把 Loki 3100 或 Alloy 12345 发布到宿主机。

应用侧回滚

结构化日志代码出现回归时,回滚对应代码并重建业务镜像。仅日志驱动不兼容时,修改 compose.deploy.yml 后必须 --force-recreate;普通 restart 不会更新容器日志驱动。任何应用侧 回滚都不得删除中央 Loki 或 Grafana 数据卷。