接入可观测平台
Luna DevOps 可以通过 OpenTelemetry 同时发送链路、指标和结构化日志。平台不内置或绑定某一种可观测后端;先准备一个支持 OTLP HTTP 的 OpenTelemetry Collector,再把同一个地址配置给 API、Worker 和 Agent。
最小配置
把下面的环境变量注入三个服务:
重启后,服务会分别以 luna-devops-api、luna-worker 和 luna-agent 上报遥测。该变量留空时不会启动导出器,Collector 不可用也不会阻止业务请求。
AI 请求进入排队状态时会保留 W3C Trace Context,因此同一次操作中的 API 请求、Agent Run、模型请求、工具调用、平台回调和数据库访问可以在 Tempo 中沿同一个 Trace 查看。等待审批或用户输入后恢复执行时仍使用同一上游 Trace,并通过 Run ID 区分执行阶段。
Agent 全内容观测(高敏)
默认遥测只记录模型、Run、工具和依赖的元数据,不记录用户提示词或工具正文。需要排查模型行为时,可以只在 Agent 容器临时开启:
重启 Agent 后,会额外采集:
- 模型请求中的系统提示词、会话历史、当前用户输入、页面上下文、工具定义和工具选择;
- 模型回复、推理摘要、工具调用请求、Token 用量和 Provider 错误响应;
- 平台工具与 Agent 内部工具的输入参数、返回状态、返回正文和请求编号。
内容会同时作为 Span Event 写入 Trace,并作为带 Trace ID 的 debug 结构化日志写入 Logs。每个序列化字段最多 32 KiB,超出时设置 luna.ai.content.truncated=true。Token、Cookie、密码、API Key、URL 内嵌凭据和 Secret 表单值无论开关状态如何都会替换为 [REDACTED];这不是数据隔离措施,提示词和业务返回仍可能包含个人或平台数据。
在 Tempo 中先按会话、轮次或 Run 查询,再展开 agent.model.stream、gen_ai.chat.complete、agent.tool.execute 或 agent.tool.internal Span 的 Events。在 Loki 中可以按 Agent 服务和事件名检索:
排障结束后把开关恢复为 false 并重启 Agent。生产环境应为 Tempo/Loki 配置最小访问权限和较短保留周期,不要把该开关作为常驻审计日志使用。
导入 Agent / LLM 仪表盘
仓库提供两套可直接导入 Grafana 的仪表盘:
grafana/dashboards/luna-devops-overview.json:平台服务、API、Worker、交付链路、Agent 和数据库的全局概览;grafana/dashboards/luna-agent-llm-observability.json:专门查看 Agent Run、模型延迟、Token、工具、人工交互、Prompt/回复和 Trace。
导入 Agent / LLM 仪表盘时,分别选择已有的 Prometheus、Tempo 和 Loki 数据源。顶部筛选器提供 Conversation ID、Turn ID、Run ID、Trace ID 和工具名称;不指定时使用 .* 查看当前时间范围内的全部数据。仪表盘的 Trace 列表只检索 agent.run.execute 根 Span,默认不会把 pg.query:*、pg-pool.connect 等数据库子 Span 当作 Agent 结果展示。推荐的排查顺序是:
- 先看 Run 成功率、模型错误率和首 Token p95,判断问题属于编排、Provider 还是响应体验;
- 再看 Run、模型、Token 和工具趋势,定位异常发生的时间与工具;
- 填入会话、轮次或 Run ID,在 Trace 表中打开完整链路;
- 只有需要检查模型原始行为时,临时启用高敏内容观测,再查看 Prompt、回复和工具输入输出面板。
Agent Run 中产生的内容日志会自动携带 gen_ai.conversation.id、luna.turn.id、luna.run.id、trace_id 和 span_id。因此同一组筛选条件可以同时约束 Tempo 与 Loki,不需要从日志正文手工复制关联信息。
查询 Trace
Luna DevOps 使用请求级 Trace:一次 AI 会话可以包含多轮对话,因此会话不是一条无限增长的 Trace。通常每轮用户消息对应一条 Trace;等待审批或用户输入后恢复的同一个 Run 仍接续原 Trace。会话、轮次和执行实例分别使用以下稳定属性关联:
在 Grafana Tempo 的 TraceQL 查询编辑器中,可以直接使用:
TraceQL 的 Span 名内建字段写作 span:name;打开一条 Trace 后,详情页筛选栏使用 span.name。详情页筛选只影响当前浏览器视图,仪表盘 JSON 不能为随后打开的 Explore 页面永久预设它。Agent 默认不采集 PostgreSQL 自动查询 Span;需要逐条 SQL 诊断时,临时设置 AI_OBSERVABILITY_CAPTURE_DATABASE_SPANS=true 并重启 Agent,完成后再关闭。
主要 Span 名称
Worker 的具体阶段会继续携带 task.type、task.id、task.retry_count 等属性。按一次异步任务查询时,优先使用:
按任务类型查看部署链路时,可以使用:
需要标记环境或集群时,可以增加资源属性:
Collector 需要鉴权时,再增加 Header;不要把密钥写入 Compose 或 Helm values,生产环境应从 Secret 注入:
Helm 部署可以直接设置 endpoint 和资源属性:
本地验证
本地临时验证可以使用 Grafana 的 OpenTelemetry LGTM 一体化镜像。它不属于 Luna DevOps,不需要写入平台 Compose:
源码运行时设置:
容器中的 Luna DevOps 访问宿主机时,把 endpoint 改为 http://host.docker.internal:4318。打开 http://localhost:3000 后,可以按 service.name 查看 Trace、Metrics 和 Logs。
至少验证一次数据库列表查询、一次 Worker 异步任务和一次 Agent 工具调用。正常链路应能看到入口请求、数据库或外部依赖子调用及业务阶段;失败链路应能使用同一个 Trace ID 关联到结构化错误日志。
生产建议
/healthz、/internal/health/live、/internal/health/ready等机器探针的成功请求只保留健康指标,不生成 Trace 或访问日志;Agent 就绪检查失败时仍记录结构化告警。用户主动发起的 Provider、集群和镜像站连通性测试不属于探针,仍保留完整观测数据。- 在 Collector 使用 batch 和 memory limiter processor,避免后端短时不可达拖垮应用。
- 错误和慢链路可以完整保留,正常链路按容量采样。采样应在 Collector 统一完成,不要让不同服务各自使用冲突策略。
- Collector 与可观测后端放在受控网络中;跨网络上报时使用 TLS 和认证 Header。
- 日志和链路默认不会记录 Cookie、Token、Secret、密码、请求正文、模型 Prompt 或工具敏感参数。只有显式开启 Agent 高敏内容观测时才会记录经过强制脱敏和长度限制的 AI 内容;下游系统仍应设置访问控制和保留周期。
- API 的独立 Prometheus
/metrics入口只作为兼容抓取面;Worker 和 Agent 不开放独立指标端口。完整平台指标统一通过 OTLP 进入 Collector 和指标后端,避免跨进程抓取、重复采集和多副本 Counter 抖动。 - 导入
grafana/dashboards/luna-devops-overview.json后,先看服务上报数、错误率和成功率,再依次查看 API 延迟、Worker 队列与交付结果、Agent 首 Token/工具调用和数据库容量。需要分析模型行为时再进入grafana/dashboards/luna-agent-llm-observability.json,避免在平台概览里堆叠高基数内容。Stat 用于当前健康,Time series 用于趋势与分位数,Logs 用于按 Trace 关联原始事件,Table 用于 Trace 搜索和慢依赖明细。
OTel Collector 的接收器、处理器和后端导出器请按所选后端配置,参考 OpenTelemetry Collector 部署文档。