
Grafana/Prometheus/Promtail/Loki/Tempo监控栈文档Grafana / Prometheus / Promtail / Loki / Tempoloop-agent 的本地可观测性栈链路(trace) 日志(log) 指标(metric)三支柱统一在 Grafana 查询。Jaeger 已下线,由 Tempo 接管链路。1. 组件与职责组件版本职责地址容器内数据目录Grafana11.0.0统一查询/可视化 UI(三种数据源)http://localhost:3000/var/lib/grafanaTempo2.5.0链路(trace)后端,收 OTLP查询 :3200 / OTLP :4317,:4318/var/tempoLoki2.9.8日志(log)后端:3100/lokiPromtail2.9.8日志采集, 推给 Loki(无 UI) :9080/promtailPrometheus2.52.0指标(metric)后端,抓应用指标:9090/prometheusPushgateway1.9.0短命 CLI 批处理任务推指标的中转:9091(无状态)角色一句话Tempo 存链路、Loki 存日志、Prometheus 存指标、Promtail 送日志、Grafana 统一看。2. 数据流图3. 组件如何相互作用应用 → Tempo链路应用用 OpenTelemetry 走 OTLP gRPC 发到localhost:4317OTEL_EXPORTER_OTLP_ENDPOINT。每个 span 带gen_ai.*模型/token/prompt/completion等属性;根 spanturn.N带run_id/session_id/user_id/model。trace_id 带年月日见第 7 节。应用 → trace_archive → Promtail → Loki日志应用把每步事件写成./trace_archive/run_id.jsonl每行一个 JSON 事件。Promtail 挂载该目录、tail 新增行,解析 JSON 后把run_id、etype事件类型提为标签,推到 Loki 的/loki/api/v1/push。Kong → Prometheus指标应用本身不推业务指标;有价值的是 Kong 的/metrics各 key 的请求数/延迟/带宽,按 consumer 拆分。Prometheus 按prometheus.yml抓取。Grafana → 三个数据源Grafana 用 provisioning 预置了 Tempo / Loki / Prometheus 三个数据源(observability/grafana/provisioning/datasources/),开箱即用。trace ↔ log 关联关联键是run_id——它既是 Tempo 里turn.Nspan 的属性,又是 Loki 里日志的标签。Tempo 数据源配了tracesToLogsV2,在一条 trace 的根 span 上点 “Logs for this span” 会自动用{run_id...}跳到 Loki。4. 快速部署前置Docker Desktop。镜像(国内 Docker Hub 常拉不动,用 daocloud 镜像再 retag)for i in grafana/tempo:2.5.0 grafana/loki:2.9.8 grafana/promtail:2.9.8 \ grafana/grafana:11.0.0 prom/prometheus:v2.52.0 prom/pushgateway:v1.9.0; do docker pull docker.m.daocloud.io/$i docker tag docker.m.daocloud.io/$i $i done启动cd repo # 只起监控组件不启动没在用的 kong-dp-ai docker compose up -d tempo loki promtail prometheus grafana # 应用把链路发到 Tempo确认 .env # OTEL_EXPORTER_OTLP_ENDPOINThttp://localhost:4317 # LOOP_TRACE_DIR./trace_archive # 启动应用 uv run --env-file .env python -m service.app验证docker compose ps # 组件是否 Up curl -s http://localhost:3200/ready # Tempo ready curl -s http://localhost:3100/ready # Loki ready curl -s http://localhost:3200/api/search?q%7B%7Dlimit3 # 有没有 trace curl -s -G http://localhost:3100/loki/api/v1/query_range \ --data-urlencode query{servicecatalystm-loop-agent} # 有没有 log停止 / 清理docker compose stop tempo loki promtail prometheus grafana # 停,保留数据 docker compose down -v # 停并删卷(清空数据,谨慎)5. 数据持久化本地当前这套用 docker具名卷落盘,stop/restart不丢数据卷组件存什么保留期tempo-dataTempotrace 块(parquet) WAL48h(block_retention)loki-dataLoki日志 chunks 索引(boltdb-shipper)30 天(retention_period)prometheus-dataPrometheusTSDB 块15 天(默认)grafana-dataGrafanaSQLite(仪表盘/设置)永久promtail-positionsPromtail读取位点(读到哪)—保留期各自在 config 里调:observability/tempo/tempo.yaml、observability/loki/loki-config.yaml、Prometheus 启动参数--storage.tsdb.retention.time。备份某个卷docker run --rm -v catalystm-loop-agent_loki-data:/d -v $PWD/backup:/b \ alpine tar czf /b/loki-data.tgz -C /d .生产上正常怎么存Tempo / Loki把块和索引放对象存储(S3 / GCS / Azure Blob),本地只留 WAL。→ 天然持久、可水平扩展、成本低。Tempo 配storage.trace.backend: s3|gcs|azure;Loki 配storage_configschema_config指向对象存储(新版用 TSDB common.storage.object)。Prometheus数据盘用PV/PVC;长期存储 降采样用remote_write → Thanos / Mimir / Cortex(底层也是对象存储)。Grafana用外部数据库(Postgres/MySQL)替代 SQLite,支持多副本共享;数据源/仪表盘用 provisioning 版本化(本仓库已这么做)。k8s各组件挂 PVC,或直接用官方 Helm chart(Tempo/Loki 的 distributed 版 对象存储 backend)。6. 如何使用Grafana 匿名是 Viewer,看不到 Explore。先右上角Sign in → admin / admin。6.1 查链路 traceExplore → Tempo,TraceQL{ resource.service.name catalystm-loop-agent } # 全部 agent 链路 { span.run_id run-20260717-151046-141652900-20f4b8 } # 某次 run { span.session_id sess-20260717-... } # 某个会话(多轮) { name llm.chat span.gen_ai.request.model gpt-4o } # 某模型的 LLM 调用 { span.gen_ai.usage.output_tokens 500 } # 大输出的调用 { name ~ tool\\..* } # 所有工具检索点开 trace 看瀑布图 → 点llm.chatspan → 右侧看 model / tier / input/output tokens / prompt / completion。6.2 查日志 logExplore → Loki,LogQL{servicecatalystm-loop-agent} # 全部 {run_idrun-20260717-151046-141652900-20f4b8} # 某次 run 全过程 {run_idrun-..., etypedecide} # 只看 decide 事件 {servicecatalystm-loop-agent} | 美妆 # 全文过滤 {servicecatalystm-loop-agent} | json | line_format {{.type}} {{.data}} # 解析 JSON标签run_id(带日期的 run 号)、etype(plan/tool/observe/reflect/decide/…)、service、filename。6.3 查指标 metricExplore → Prometheus,PromQLkong_http_requests_total{servicellm-azure-openai} # 各路由请求数 sum by (consumer) (kong_http_requests_total) # 各 key(consumer)消耗 histogram_quantile(0.95, sum by (le) (rate(kong_request_latency_ms_bucket[5m]))) # p95 延迟6.4 trace ↔ log 互跳trace → logTempo 里打开 trace 的根 spanturn.N(带 run_id)→ “Logs for this span” → 自动{run_id...}跳 Loki。log → traceLoki 日志行里点run_id派生链接,或复制 run_id 去 Tempo 查{ span.run_id ... }。7. trace_id / run_id 约定OTEL trace_idTempo 里显示,32 hex带年月日YYYYMMDD(8)HHMMSS(6)微秒(6)随机(12),如2026071715104614165201d9ff16e960。每会话稳定不变。run_id / session_id业务号,trace_archive 文件名 / Loki 标签run-YYYYMMDD-HHMMSS-ns-rand。三者时间戳一致,可按时间对齐。8. 配置文件位置docker-compose.yml # 所有服务定义 卷 prometheus.yml # Prometheus 抓取配置 observability/ tempo/tempo.yaml # Tempo loki/loki-config.yaml # Loki promtail/promtail-config.yaml # Promtail(采集 ./trace_archive) grafana/provisioning/datasources/{tempo,loki,prometheus}.yml # Grafana 数据源(含关联) dashboards/ # 预置仪表盘(挂载)9. 排查docker compose ps # 谁没起来 docker logs catalystm-loop-agent-promtail-1 # promtail 有没有在推 docker logs catalystm-loop-agent-tempo-1Explore 里没有 Tempo/Loki → 先登录 admin/admin(Viewer 看不到 Explore)。Loki 查不到某次 run → 确认./trace_archive/run.jsonl存在,且LOOP_TRACE_DIR./trace_archive(promtail 挂的就是这个目录)。Tempo 刚跑完查不到 → 等 10–30 秒(ingester 切块后才可搜)。拉不到镜像 → 用docker.m.daocloud.io/image前缀再 retag(Docker Hub 在国内常 EOF)。