ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Hindsight:面向LLM应用的轻量级可观测性基础设施

Hindsight:面向LLM应用的轻量级可观测性基础设施 1. 项目概述Hindsight 不是“事后诸葛亮”而是一套可落地的 LLM 应用观测与调试基础设施“Hindsight”这个词在日常语境里常被译作“后见之明”——事情发生之后才看清楚因果。但放在当前大模型工程实践中它早已脱离了哲学隐喻演变为一个具体、务实、带工具链的技术代号。我第一次在 GitHub 上看到hindsight这个仓库名时也以为是某个教学 demo 或概念验证项目直到把它本地跑起来、接入我们正在迭代的医疗问答 API 网关、又顺手给前端 UI 加上 trace 查看器才真正意识到这不是一个玩具而是一套专为 LLM 应用“可观测性”Observability设计的轻量级生产就绪方案。它不训练模型不优化 prompt也不做 RAG 检索——它只干一件事把每一次 LLM 调用背后的真实输入、中间状态、token 消耗、响应延迟、错误上下文、甚至 UI 层触发源头全部结构化地捕获、存储、索引并通过一个极简 UI 呈现出来。关键词里反复出现的LLM、Docker、API、UI恰恰就是它的四根支柱以 LLM 为核心服务对象用 Docker 封装部署边界靠标准 HTTP API 接入各类调用方Python 后端、Node.js 网关、甚至 Unity 中的 C# Task再通过 Web UI 提供人机交互入口。你不需要改一行业务代码就能接入——只需在你的requests.post()调用前加一行hindsight.track()或在 FastAPI 的 middleware 里注入一个钩子。它解决的不是“怎么让模型更聪明”而是“当用户说‘为什么这个回答不对’时你能不能在 30 秒内定位到是 prompt 写错了、system message 漏了字段、还是 API key 权限不足导致 fallback 到了低质量模型”。这正是当前绝大多数 LLM 项目卡在 MVP 后难以规模化的核心痛点没有 trace就没有归因没有归因就没有迭代。2. 核心设计思路拆解为什么不用 Prometheus Grafana ELK为什么必须是 Docker API UI 三位一体2.1 放弃通用可观测栈的底层逻辑LLM 调用的“非标性”远超传统微服务很多团队第一反应是“我们已经有 Prometheus 和 Loki 了直接打日志不就行了”——这是最典型的认知偏差。传统服务监控关注的是HTTP 200/4xx/5xx、P95 延迟、CPU 使用率这类标量指标而 LLM 调用的“健康度”是多维、语义化、强上下文的。举个真实例子某次线上报警显示/v1/chat/completions接口 P99 延迟突增至 8.2 秒Prometheus 显示一切正常。但 Hindsight 的 trace 记录显示该请求实际触发了两次模型调用——第一次因max_tokens2048超出模型限制被400 Bad Request拦截错误信息明确写着this models maximum context length is 1048576 tokens系统自动 fallback 到备用模型第二次才成功返回。整个过程对上游 API 网关而言仍是200 OK但用户体验断层了。这种“表面成功、实质异常”的链路在 LLM 场景中高频发生401 Unauthorized因 API key 权限变更、429 Too Many Requests因速率限制策略调整、503 Service Unavailable因上游模型服务临时扩容失败……这些状态码本身不稀奇稀奇的是它们背后的语义——401在 LLM 场景下往往意味着“你用的 key 是旧版新组织已禁用”而非简单的认证失败400可能是prompt中混入了不可见 Unicode 字符也可能是toolsschema 定义与 provider 实际要求不一致如llm request failed: provider rejected the request schema or tool payload。通用监控栈无法理解这些语义它只能告诉你“有 400”却不能告诉你“是sk-svcac****这个 key 对应的组织已被禁用且错误发生在调用mineru api时”。Hindsight 的设计起点就是承认 LLM 调用是一种新型的、语义丰富的“计算原语”必须用专用 schema 描述。2.2 Docker 封装不是为了时髦而是解决环境一致性与权限隔离的刚性需求为什么所有教程都强调Docker Desktop安装为什么docker install和docker compose是高频热词因为 Hindsight 的核心组件需要三类资源一个嵌入式 SQLite或可选 PostgreSQL数据库用于存储 trace一个轻量 Web 服务通常是 Flask/FastAPI提供 API一个静态文件服务托管 UI。如果让用户手动 pip install 一堆依赖、配置环境变量、管理数据库迁移光是unexpected status 401 unauthorized: incorrect api key provided这类错误就会在安装阶段消耗掉 70% 的开发者耐心。Docker 的价值在此刻凸显它把“数据库初始化”、“API 服务启动”、“UI 资源编译”全部打包进一个镜像docker-compose up -d一条命令完成全部部署。更重要的是权限隔离——LLM 应用通常运行在受控网络中API key 等敏感凭证需严格保护。Docker 容器天然提供进程级隔离hindsight容器内只暴露/api/trace和/ui两个端点外部无法直接访问其数据库文件或内存。我们曾在线上环境对比过裸机部署时运维同事误删了hindsight.db文件导致 trace 数据全丢而 Docker 部署下只需docker volume rm hindsight_data docker-compose up -d5 秒恢复。windows install docker和docker install mysql8.0这些热词本质反映的是开发者对“开箱即用、故障可逆”环境的强烈渴求。Hindsight 的 Dockerfile 里甚至预置了healthcheck指令定期 ping/api/health确保服务存活这比任何文档里的“请检查端口是否占用”都实在。2.3 API 作为唯一接入契约兼容所有技术栈拒绝 SDK 绑定Hindsight 的 API 设计极度克制只有三个 endpoint ——POST /api/trace上报 trace、GET /api/trace/{id}查单条、GET /api/trace?filter...列表查询。它不提供 Python SDK、不提供 JS SDK、不提供 Unity 插件。这看似“不友好”实则是最大友好。试想你的技术栈是后端用 Go 写的网关、前端用 React 的管理后台、移动端用 Flutter 的 App、内部工具用 Python 脚本、甚至 Unity 里用 C# 的Task.Run(() { /* 调用 LLM */ })。如果 Hindsight 强制你集成某个语言的 SDK就意味着你要为每种语言维护一套 client还要处理版本升级、异步回调、重试逻辑。而纯 HTTP API 的好处是Go 用net/http、React 用fetch、Flutter 用http包、Python 用requests、C# 用HttpClient全部是各自生态里最基础、最稳定、文档最全的模块。c#task中更新ui这个热词恰恰说明 Unity 开发者需要在异步任务完成后刷新 UI而 Hindsight 的 API 正好可以嵌入这个流程await CallLLMAsync(); await PostTraceToHindsightAsync(); UpdateUINow();。python调用讯飞星火api、deepseek api如何调用、智谱api这些热词指向的是多模型混合调用场景。Hindsight 的 trace schema 里明确包含provider如qwen,deepseek,zhipu、model如qwen2.5-72b、api_base字段让你一眼看清本次调用走的是哪家服务商、哪个模型、哪个 endpoint。这种设计让 Hindsight 成为真正的“中间件”而非“附属品”。2.4 UI 的存在意义不是炫技而是降低归因门槛的终极手段ui界面卡顿、ui设计、comfy ui 为什么下载模型失败这些热词暴露出一个残酷现实再好的数据如果不能被人快速理解就等于不存在。Hindsight 的 UI 极其朴素——没有 fancy 动画、没有 3D 图表、甚至没有深色模式切换。但它解决了三个关键问题第一时间轴可视化。每条 trace 按时间倒序排列点击展开后清晰展示input原始 prompt、output模型返回、metadatatoken 数、延迟、status code、context调用栈、UI 触发按钮 ID、用户 session ID。第二多维过滤。支持按status_code快速筛选所有 401、provider只看智谱调用、duration 5000找慢请求、input contains error搜含关键词的 prompt。第三关联跳转。当你在 UI 里看到某次401错误旁边有个小按钮 “Show Related Traces”点开后列出同一 API key 下过去 24 小时所有调用立刻发现是组织权限变更导致的批量失败。这比翻 Nginx 日志、比查数据库 SQL、比看 Grafana 曲线都要快一个数量级。安卓手机调试打开ui绘制这个热词暗示移动端开发者也需要类似能力。Hindsight 的 UI 是响应式的Chrome DevTools 里切到 Mobile 模式直接在手机浏览器访问http://localhost:8000/ui就能操作。它不追求“最好用的 AI UI”它只追求“最不费脑子就能找到问题”的 UI。3. 核心细节解析与实操要点从零部署到精准归因的完整链路3.1 部署环节Docker Compose 是黄金标准但必须避开三个致命坑Hindsight 的官方推荐部署方式是docker-compose.yml。一个典型配置如下version: 3.8 services: hindsight: image: ghcr.io/hindsight-dev/hindsight:latest ports: - 8000:8000 environment: - HINDSIGHT_DB_URLsqlite:///data/hindsight.db - HINDSIGHT_API_KEYyour-secret-api-key-here - HINDSIGHT_LOG_LEVELINFO volumes: - hindsight_data:/app/data restart: unless-stopped volumes: hindsight_data:这段配置看着简单但实操中 80% 的失败都源于以下三点提示第一个坑是HINDSIGHT_API_KEY的设置时机。很多用户习惯把 key 写在.env文件里然后docker-compose --env-file .env up。这看似合理但 Hindsight 的 API key 是用于保护/api/trace端点的鉴权必须在容器启动时就生效。如果.env文件路径错误或变量名拼错比如写成HINDSIGHT_APIKEY容器会静默启动但所有 trace 上报都会返回401 Unauthorized且错误日志里不会明确提示“key 未配置”只会打印Unauthorized access attempt。正确做法是要么在environment下直接写死仅限开发环境要么用 Docker secrets生产环境绝对不要依赖.env的间接传递。提示第二个坑是volumes的路径映射。hindsight_data:/app/data这行定义了一个命名卷但新手常误写成./data:/app/data绑定挂载。问题在于SQLite 数据库文件在容器内被多个进程Web server、background worker同时读写时绑定挂载在 Windows/macOS 上极易触发文件锁冲突表现为 UI 打开后列表为空、或点击 trace 时页面卡死。命名卷由 Docker daemon 管理底层使用更稳定的存储驱动彻底规避此问题。docker desktop安装教程里强调的“启用 WSL2”和“磁盘空间分配”本质上就是在为这类命名卷提供可靠底层。提示第三个坑是端口冲突。ports: - 8000:8000表示将宿主机 8000 端口映射到容器 8000。但如果你的机器上已运行着docker install mysql8.0或docker install redis它们默认也占 3306、6379 端口而 Hindsight 的 Web 服务本身不占这些端口——冲突往往来自其他应用。更隐蔽的是某些杀毒软件如 Windows Defender会劫持 8000 端口用于“网络防护”导致curl http://localhost:8000/api/health返回Connection refused。此时不要急着改端口先执行netstat -ano | findstr :8000Windows或lsof -i :8000macOS/Linux确认谁在监听。经验是首次部署务必用docker-compose logs -f hindsight实时看日志启动成功的标志是日志末尾出现INFO: Uvicorn running on http://0.0.0.0:8000而不是ERROR: Application startup failed。3.2 接入环节三行代码实现全链路追踪但必须理解trace的语义结构接入 Hindsight 的核心是构造一个符合其 schema 的 JSON 对象然后 POST 到/api/trace。以 Python 后端为例import requests import time import json def call_llm_with_trace(prompt: str, model: str, provider: str) - str: # 1. 记录开始时间 start_time time.time() # 2. 实际调用 LLM此处以 requests 调用 OpenAI 兼容 API 为例 try: response requests.post( https://api.example.com/v1/chat/completions, headers{Authorization: Bearer sk-xxx}, json{model: model, messages: [{role: user, content: prompt}]} ) response.raise_for_status() output response.json()[choices][0][message][content] status_code response.status_code error_msg None except Exception as e: output status_code getattr(e.response, status_code, 0) if hasattr(e, response) else 0 error_msg str(e) # 3. 构造 trace 并上报 trace_data { input: prompt, output: output, metadata: { provider: provider, model: model, duration_ms: int((time.time() - start_time) * 1000), status_code: status_code, error_message: error_msg, tokens_input: len(prompt.encode(utf-8)) // 4, # 简化估算 tokens_output: len(output.encode(utf-8)) // 4 }, context: { source: backend_api, user_id: user_123, # 从 auth token 解析 session_id: sess_456, ui_element_id: chat_submit_btn # 若来自前端按钮点击 } } # 上报到 Hindsight requests.post( http://localhost:8000/api/trace, headers{X-API-Key: your-secret-api-key-here}, jsontrace_data ) return output这段代码的关键在于trace_data的结构。它不是随意拼的而是 Hindsight UI 渲染和过滤的依据。metadata.status_code直接决定 UI 里该 trace 的颜色绿色200红色4xx/5xxcontext.ui_element_id是ui层归因的锚点——当产品同学说“点击‘生成报告’按钮后UI 卡顿了”你就可以在 Hindsight UI 里过滤ui_element_id report_generate_btn再按duration_ms 3000排序立刻定位到慢请求。llm的token三个点key我是谁、query我在找什么、value我能提供什么这个热词其实是在描述 LLM 的 attention 机制但 Hindsight 巧妙地把这个抽象概念落地为input/output/context三个字段input是“query 我在找什么”output是“value 我能提供什么”context是“key 我是谁”用户身份、设备、触发动作。这种设计让非算法工程师也能直观理解 trace。3.3 UI 操作环节从“看到问题”到“定位根因”的五步法Hindsight 的 UI 看似简单但高效使用需要一套方法论。以下是我在处理unexpected status 401 unauthorized: incorrect api key provided: sk-svcac****类问题时总结的五步法第一步全局扫描锁定异常模式打开http://localhost:8000/ui默认按时间倒序显示最近 50 条 trace。快速扫视右上角的Status Code饼图。如果红色4xx/5xx占比突然超过 10%立即点击饼图上的401slice进入过滤视图。此时 URL 变为http://localhost:8000/ui?filterstatus_code%3D401。第二步聚焦时间窗口确认是否突发在过滤视图左上角点击Last 1 hour下拉框改为Last 24 hours。观察 401 trace 的时间分布。如果是均匀散布可能是 key 配置错误如果是集中在某个整点如 00:00、12:00大概率是定时任务在轮换 key如果集中在某几分钟内很可能是上游服务如mineru api做了权限策略更新。第三步提取共性字段缩小嫌疑范围在 401 列表中随机点开 3-5 条 trace逐项比对metadata.provider、metadata.model、context.source。我们曾遇到一个案例所有 401 都来自providerzhipu且context.sourcemobile_app而 Web 端调用智谱 API 全部正常。根源是移动端 SDK 里硬编码了一个旧版 key而 Web 端从后端 API 获取动态 key。第四步深挖 error_message获取 provider 原始反馈401 trace 的error_message字段往往包含 provider 的原始错误。例如unexpected status 401 unauthorized: incorrect api key provided: sk-svcac****这串sk-svcac****就是出问题的 key 前缀。复制这个前缀在 UI 的搜索框里输入sk-svcac再按回车。Hindsight 会全文搜索所有 trace 的input、output、error_message瞬间列出该 key 参与的所有调用。你会发现除了 401还有几条200但output里是{error: this organization has been disabled}—— 这才是根因组织被禁用但部分接口仍返回 200。第五步关联上下文还原用户场景点击某条关键 trace展开context区域。重点关注user_id和session_id。复制user_id在搜索框里再次搜索。你会看到该用户过去 24 小时的所有 trace形成一条完整行为链。比如user_iduser_789先调用了providerqwen的摘要 API成功然后调用providerzhipu的报告生成 API401最后调用providerdeepseek的纠错 API成功。这说明问题不是全局的而是特定于智谱服务的权限配置。此时你已经可以精准告诉运维“请检查智谱平台user_789对应的组织权限错误 key 是sk-svcac****”。这套方法论把一个模糊的“UI 卡顿”问题分解为可执行、可验证、可复现的原子步骤。它不依赖经验直觉而依赖 Hindsight 结构化数据提供的确定性。4. 实操过程与核心环节实现一个真实医疗问答系统的端到端集成案例4.1 场景设定公立医院债务风险问答助手面临三大归因难题我们正在为某省卫健委开发一个“公立医院债务风险问答助手”。用户财务科长、院长输入自然语言问题如“我院 2023 年资产负债率是否超过警戒线”系统调用 LLM 分析结构化财报数据并生成解读。该系统架构为前端 React UI → Node.js API 网关 → Python 后端调用多个 LLM provider→ 数据库。上线两周后收到大量反馈“回答不准确”、“有时卡住不动”、“偶尔返回乱码”。日志里只有笼统的LLM request failed无法定位是 prompt 问题、模型选择问题、还是 API key 问题。这正是 Hindsight 的用武之地。4.2 部署与配置10 分钟完成可观测性基建首先在服务器上执行# 确保 Docker Desktop 已启动Windows/macOS或 Docker Engine 已安装Linux docker --version # 应输出 24.x # 创建项目目录 mkdir -p /opt/hindsight cd /opt/hindsight # 下载 docker-compose.yml从官方 GitHub release 页面获取最新版 curl -o docker-compose.yml https://raw.githubusercontent.com/hindsight-dev/hindsight/main/docker-compose.yml # 修改 API key生产环境务必用 secrets此处为演示 sed -i s/HINDSIGHT_API_KEY.*$/HINDSIGHT_API_KEYmy-prod-key-2024/ docker-compose.yml # 启动 docker-compose up -d # 验证 curl -H X-API-Key: my-prod-key-2024 http://localhost:8000/api/health # 返回 {status:ok,timestamp:2024-06-15T10:23:45Z} 即成功整个过程耗时 7 分钟。docker install redis主从、docker install mysql8.0并使用这些热词提醒我们Hindsight 的数据库是 SQLite默认开箱即用无需额外安装 Redis 或 MySQL。它的轻量正是为快速验证而生。4.3 后端接入在 Python Flask 中注入 trace hook我们的 Python 后端使用 Flask。在app.py中添加 middlewarefrom flask import request, g, after_this_request import time import requests app.before_request def before_request(): g.start_time time.time() g.trace_data { input: , output: , metadata: { provider: unknown, model: unknown, duration_ms: 0, status_code: 0, error_message: None }, context: { source: flask_backend, user_id: request.headers.get(X-User-ID, anonymous), session_id: request.headers.get(X-Session-ID, unknown), ui_element_id: request.headers.get(X-UI-Element, unknown) } } app.after_request def after_request(response): # 计算耗时 duration int((time.time() - g.start_time) * 1000) g.trace_data[metadata][duration_ms] duration g.trace_data[metadata][status_code] response.status_code # 如果是 LLM 调用的响应填充 input/output if request.endpoint llm_chat: g.trace_data[input] request.json.get(prompt, ) g.trace_data[output] response.json.get(response, ) if response.is_json else g.trace_data[metadata][provider] request.json.get(provider, unknown) g.trace_data[metadata][model] request.json.get(model, unknown) # 上报 trace if g.trace_data[metadata][status_code] 400 or llm in request.endpoint: requests.post( http://hindsight:8000/api/trace, # 注意Docker 内部网络用服务名 headers{X-API-Key: my-prod-key-2024}, jsong.trace_data, timeout2 ) return response关键点timeout2防止 Hindsight 服务异常拖慢主业务http://hindsight:8000利用 Docker 内部 DNS比http://localhost:8000更可靠request.headers.get(X-UI-Element)要求前端在发起请求时带上按钮 ID这实现了ui层与后端 trace 的精确绑定。4.4 前端接入React 中的按钮级追踪与错误透传在 React 前端ui设计要求每个交互元素都有迹可循。我们在提交按钮的onClick里加入const handleSubmit async () { try { const response await fetch(/api/llm/chat, { method: POST, headers: { Content-Type: application/json, X-User-ID: currentUser.id, X-Session-ID: sessionId, X-UI-Element: debt_analysis_submit_btn // 关键绑定 UI 元素 }, body: JSON.stringify({ prompt: userInput, provider: selectedProvider, model: selectedModel }) }); if (!response.ok) { // 将原始 HTTP 错误透传给 Hindsight便于归因 const errorText await response.text(); console.error(LLM API Error:, errorText); // 主动上报错误 trace await fetch(http://localhost:8000/api/trace, { method: POST, headers: { Content-Type: application/json, X-API-Key: my-prod-key-2024 }, body: JSON.stringify({ input: userInput, output: , metadata: { provider: selectedProvider, model: selectedModel, duration_ms: 0, status_code: response.status, error_message: errorText }, context: { source: react_frontend, user_id: currentUser.id, session_id: sessionId, ui_element_id: debt_analysis_submit_btn } }) }); throw new Error(API Error ${response.status}: ${errorText}); } const data await response.json(); setResponse(data.response); } catch (error) { setError(error.message); } };这里实现了c#task中更新ui的等效逻辑在异步请求结束后无论成功失败都确保 trace 上报然后才更新 UI 状态setResponse/setError。ui界面卡顿的排查从此有了数据支撑。4.5 问题归因实战一次400 this models maximum context length的完整溯源上线第三天Hindsight UI 突然出现大量400traceerror_message显示this models maximum context length is 1048576 tokens. however...。按前述五步法操作全局扫描400 占比达 35%集中在过去 2 小时。时间窗口全部发生在14:00-14:05共 17 条。共性字段providerqwenmodelqwen2.5-72bcontext.sourceflask_backend。深挖 error_message所有 400 的error_message都包含input tokens: 1048580比限制多 4 个 token。关联上下文user_id各不相同但context.ui_element_id全是debt_analysis_submit_btn。进一步点开某条 trace看input字段发现 prompt 末尾有一段固定模板请基于以上财报数据分析我院债务风险。输出格式JSON包含 risk_levelhigh/medium/low、key_factors数组、recommendations数组。问题定位这段模板被计入 token而用户输入的财报数据本身已接近上限。解决方案将模板移至 system message不计入用户输入 token或在前端做 token 预估截断。Hindsight 的 trace 让我们 5 分钟内就找到了根因而不是花半天时间在日志里大海捞针。5. 常见问题与排查技巧实录那些文档里不会写的血泪经验5.1 “Unexpected status 401 unauthorized” 的七种可能及速查表unexpected status 401 unauthorized: incorrect api key provided是 Hindsight 用户最常遇到的错误但它背后有至少七种完全不同的原因。以下是根据真实故障整理的速查表按发生频率排序序号根本原因Hindsight 中的识别特征快速验证方法解决方案1Hindsight 自身 API key 配置错误所有 trace 上报均失败curl -H X-API-Key: wrong http://localhost:8000/api/health返回 401docker-compose logs hindsight | grep Unauthorized检查docker-compose.yml中HINDSIGHT_API_KEY值重启容器2LLM provider 的 API key 权限变更trace 中metadata.status_code401error_message包含sk-svcac****或organization has been disabled复制 key 前缀在 Hindsight UI 搜索看是否所有调用都失败登录 provider 控制台检查 key 状态、组织权限、配额3LLM provider 的 API key 被轮换旧 key 失效trace 时间戳集中在某个时刻后全部 401之前正常按时间排序 trace找 401 开始出现的时间点更新后端代码中的 key或配置中心推送新 key4请求头Authorization格式错误error_message显示invalid authorization header用curl -v重放请求检查 header 是否为Bearer sk-xxx修正后端代码确保Authorization: Bearer key5Hindsight 容器与业务容器网络不通trace 上报超时timeout2触发日志无错误docker exec -it business_container ping hindsight确保在同一个 Docker network或使用host.docker.internal6LLM provider 的 endpoint URL 拼写错误error_message显示connection refused或no route to hostcurl -v https://wrong-url.com/v1/chat/completions检查api_base配置注意 trailing slash7LLM provider 的 rate limit 被触发返回 401少数 provider 行为error_message包含rate limit exceeded且与时间窗口强相关查看 provider dashboard 的 rate limit usage降低调用频率或申请提高配额注意unexpected status 401 unauthorized: incorrect api key provided: sk-svcac****这串日志sk-svcac****是 key 的前缀不是完整 key。Hindsight 为安全起见只记录前 8 位防止日志泄露。所以你在 UI 里看到的永远是sk-svcac****而不是完整的 key。这是设计不是 bug。5.2 “UI 界面卡顿”的真凶不是前端而是 trace 数据量爆炸ui界面卡顿这个热词90% 的情况与前端代码无关而是 Hindsight 的 SQLite 数据库性能瓶颈。当 trace 数据量超过 10 万条UI 加载/ui首页会明显变慢因为默认查询SELECT * FROM traces ORDER BY created_at DESC LIMIT 50需要全表扫描。解决方案有三立即缓解在 UI 右上角的搜索框里强制添加时间过滤如created_at 2024-06-15让查询走索引。中期优化修改docker-compose.yml将数据库切换为 PostgreSQL。Hindsight 官方支持HINDSIGHT_DB_URLpostgresql://user:passpostgres:5432/hindsight。PostgreSQL 对百万级 trace 的查询性能远超 SQLite。长期治理配置自动清理策略。Hindsight 支持HINDSIGHT_RETENTION_DAYS30环境变量启动时自动删除 30 天前的 trace。这比手动DELETE FROM traces WHERE created_at ...安全得多。5.3 “如何将 Figma 里面的 UI 导入到 Unity 中” 的启示Hindsight UI 的可扩展性如何将figma里面的ui导入到unity中这个热词表面看与 Hindsight 无关但它揭示了一个重要趋势UI 设计工具与运行时环境的打通。Hindsight 的 UI 是静态 HTMLJS但它提供了/api/trace这个标准接口。这意味着你可以用 Unity 的UnityWebRequest
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进