AI 助手 07:不用 Kibana,如何把 Elasticsearch 日志检索接入业务管理后台

基于 ai-study V1.6 已实现基线,记录 Java、Python、Filebeat、Elasticsearch 与管理员日志页面如何通过 requestId 形成可控的排查链路。

字数 927 阅读时长 ≈ 3 分钟 2026-7-28 2026-7-28
所属项目:AI-assistant
AI 助手 07:不用 Kibana,如何把 Elasticsearch 日志检索接入业务管理后台

做 AI 应用时,模型调用记录和运行日志不能混为一谈。前者适合进入 PostgreSQL,用于统计 token、成本、请求和审计;后者适合进入可检索的日志系统,用来定位一次请求在哪个服务、哪个时间点失败。ai-study 的 V1.6 选择 Elasticsearch + Filebeat,但没有把 Kibana 当作项目运行必需品,而是直接把受限检索能力接到管理后台。

Java 与 Python stdout 经 Filebeat 采集后由受限管理 API 查询的路径

为什么不让浏览器直连 Elasticsearch

Elasticsearch DSL 非常强,但也意味着浏览器一旦直连就能绕过查询范围、字段脱敏和分页限制。当前系统只提供管理员接口:

GET /api/admin/runtime-logs
GET /api/admin/runtime-logs/status

服务端先验证 ADMIN 角色,再将时间、服务名、日志级别、requestId、关键词、页码和条数转换为受限查询。单页最多 100 条,默认查询最近 24 小时;返回给前端的只有安全字段,例如时间、级别、服务、事件、requestId、脱敏后的消息和错误摘要。

这使前端得到的是“排查任务需要的信息”,而不是整个 Elasticsearch 索引、节点元数据或任意 DSL 的执行权。

一次请求如何串到两个服务

认证过滤器会把 requestId、tenantId、userId 同时写入 Java 的 RequestContext 与 SLF4J MDC。Java 调 Python 时继续透传 requestId 和已认证的上下文;Python 也以结构化方式记录关键事件。Filebeat 只采集带 ai-study.logs=true 标签的 Java 和 Python 容器日志,避免把 Postgres、Redis、Milvus 等基础设施噪声一并塞进业务日志索引。

因此,发生一次失败 Chat 请求后,管理员先从响应或调用记录拿到 requestId,再在运行日志页按该 ID 查询,就可以看到 Java 接收请求、下游 Python 调用和错误事件的关联信息。这比用时间猜日志、在多个容器里手工搜索更稳定。

普通 log.info 也会带上 MDC 尾部上下文;结构化运行事件还额外使用 serviceNameeventName,避免与 Elasticsearch ECS 的对象字段发生冲突。异步任务、定时任务或启动日志没有请求上下文时,这些字段为空是预期行为,不应伪造一个用户身份。

日志里最重要的不是“尽可能多”

运行日志禁止记录密码、JWT、refresh token、Cookie、API Key、Authorization Header、完整 prompt 和完整模型回答。这既是安全要求,也能控制索引成本与敏感数据扩散范围。模型调用参数、用量和审计需要保留时,应进入职责明确的业务表,并按权限查询,而不是把所有原始内容打到 stdout。

本地环境的索引保留策略为 7 天,Elasticsearch 仅绑定 127.0.0.1:9200。Filebeat 状态写入 Docker 卷,避免重启后从头重复采集。单节点数据流出现 YELLOW 也属正常:副本没有第二个节点可分配,并不阻止本地读写。

失败时如何降级

Elasticsearch 是排查能力,不是 Chat 主流程的强依赖。日志服务未启用或不可访问时,管理 API 返回 503,页面明确提示不可用;登录、聊天和 PostgreSQL 中的业务审计仍应继续工作。把可观测性系统做成核心路径依赖,只会把“无法查看日志”放大为“业务也无法使用”。

当前版本还没有日志 TLS、Elasticsearch 用户认证、租户级日志可见范围、独立链路时间线和告警指标。它解决的是本地/开发环境中“无需 Kibana、可在项目内按 requestId 排查”的基线;生产部署前仍需补充更严格的权限、留存和安全设计。