feat(观测): 阶段四第一波观测栈 compose(五件+脱敏+MinIO后端,不起容器)
deploy/infra/observability/:OTel Collector+Prometheus+Tempo+Loki+Grafana docker-compose,照已签设计施工(opus 写 + fable 源码级终审)。 - 端口逐个不撞现有(Grafana 3002 避 new-api 3000/gitea 3001;Collector 4317-4318/Prom 9090/Tempo 3200/Loki 3100) - 资源三上限(mem 合计 3.4G / cpus / cpu_shares=512 CPU 争用让路 new-api) - 脱敏 redaction 三 pipeline 导出前(手机号/token/JWT/密钥)= 安全红线 - Tempo/Loki 存 MinIO 独立桶 obs-tempo/obs-loki(minio-init 幂等建、不碰 ragflow) - 镜像全钉版本、密钥全走 .env 不入仓 终审验通:git 纯新增未 commit / compose config exit=0 / infra-minio 在 infra-shared 网 DNS 可解析(最大风险排除)/ grafana:11.4.0 经 daocloud mirror 拉取成功。起容器待创始人 go(碰生产 mini-infra)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e1f5a66a5d
commit
62ce5531b6
16
deploy/infra/observability/.env.example
Normal file
16
deploy/infra/observability/.env.example
Normal file
@ -0,0 +1,16 @@
|
||||
# =============================================================================
|
||||
# 观测栈运行时密钥模板 —— 部署时复制为 .env 并填真实值,权威副本见
|
||||
# docs/内网凭据与端点.md。.env 只在服务器 chmod 600 存在、不入仓(见 .gitignore)。
|
||||
# cp .env.example .env && chmod 600 .env # 然后把占位换成真实值
|
||||
# =============================================================================
|
||||
|
||||
# ── MinIO S3 后端凭据 ──
|
||||
# Tempo/Loki 的对象存储复用既有 infra-minio(ragflow 共用实例),各存 obs-tempo/obs-loki 桶。
|
||||
# ACCESS_KEY 非机密(账号名),SECRET_KEY 是机密、从凭据文档取。
|
||||
MINIO_ACCESS_KEY=ragflow
|
||||
MINIO_SECRET_KEY=__FILL_FROM_docs/内网凭据与端点.md__
|
||||
|
||||
# ── Grafana 管理员 ──
|
||||
# 首次进盘用它登录(admin 一键进盘)。口令从凭据文档取,首登后可改。
|
||||
GF_ADMIN_USER=admin
|
||||
GF_ADMIN_PASSWORD=__FILL_FROM_docs/内网凭据与端点.md__
|
||||
4
deploy/infra/observability/.gitignore
vendored
Normal file
4
deploy/infra/observability/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# 运行时密钥文件:.env 只在服务器上 chmod 600 存在,权威副本在 docs/内网凭据与端点.md,不入仓。
|
||||
.env
|
||||
# 若改用 bind-mount 的运行时产物目录(当前用 named volume,一般不落此目录)。
|
||||
data/
|
||||
95
deploy/infra/observability/README.md
Normal file
95
deploy/infra/observability/README.md
Normal file
@ -0,0 +1,95 @@
|
||||
# 可观测性栈(observability)
|
||||
|
||||
这套栈把五个组件起在 mini-infra:Collector 收信号,Prometheus 存指标,Tempo 存追踪,Loki 存日志,Grafana 看板。所有服务和两条生成线把 OpenTelemetry 信号推到同一个 Collector,Collector 先脱敏、再采样、再分发到三个存储,Grafana 从三个存储读出来,在一块盘上把「用户点一下到模型返回」这条链路串起来看。
|
||||
|
||||
配置控制面阶段四的第一波只做后端五件加自监控,不碰生产;给 game-cloud 挂 agent、重定向 Python 线的 OTLP、打通三跳 traceparent、落业务埋点,是后续波的事。权威设计见 `docs/agent-specs/2026-07-05-全链路可观测性-OTel三信号全栈-设计.md`。
|
||||
|
||||
## 起停
|
||||
|
||||
部署目录假设是 `/opt/infra-observability`(把本目录同步过去)。
|
||||
|
||||
```
|
||||
cd /opt/infra-observability
|
||||
cp .env.example .env && chmod 600 .env # 首次:填真实密钥,见下"密钥与配置"
|
||||
docker compose up -d # 起
|
||||
docker compose ps # 看状态
|
||||
docker compose logs -f otel-collector # 看某件日志
|
||||
docker compose down # 停(保留数据卷)
|
||||
```
|
||||
|
||||
起的时候 compose 会先跑一个一次性的 `minio-init` 容器,在既有 MinIO 上把 `obs-tempo` 和 `obs-loki` 两个桶建好(幂等,重复起不报错),Tempo 和 Loki 等它成功退出后才启动。
|
||||
|
||||
## 探活
|
||||
|
||||
```
|
||||
HOST=100.64.0.8 bash health-check.sh
|
||||
```
|
||||
|
||||
逐个探五件的就绪端点,全绿退 0,任一没起来退 1。Tempo 和 Loki 刚起的头几十秒 `/ready` 会返 503,属正常就绪过程,等一会儿再探。脚本默认绕过本机 fake-ip 代理直连 Tailscale 地址。
|
||||
|
||||
## 端口账
|
||||
|
||||
对外端口都逐个核对过没和 mini-infra 现有占用撞(new-api=3000、gitea=3001、ragflow=9380-9381、postgres=5433、minio=9000-9001、mysql=3306、redis=6379、nacos=8848、rocketmq=9876/10911、nginx=80/443、infinity=23817/23820)。
|
||||
|
||||
| 组件 | 对外端口 | 用途 |
|
||||
|---|---|---|
|
||||
| Grafana | 3002 | Web 看板(默认 3000/3001 已被占,改 3002) |
|
||||
| Prometheus | 9090 | Web UI / 查询 API |
|
||||
| Loki | 3100 | HTTP API + OTLP 日志摄入(`/otlp`) |
|
||||
| Tempo | 3200 | 查询 API |
|
||||
| Collector | 4317 / 4318 | OTLP gRPC / HTTP 入口(跨机信号源推这里) |
|
||||
| Collector | 13133 | 健康探针 |
|
||||
|
||||
Collector 自身遥测 8888、业务指标出口 8889 不对外映射,Prometheus 在同网内用服务名 scrape。Tempo 收 Collector 转发的 OTLP 走容器内 4317,不对外映射,不和 Collector 对外的 4317 冲突(不同容器各自监听)。五件之间用 compose 服务名(otel-collector / prometheus / tempo / loki / grafana)在 `infra-shared` 网内互通,连既有 MinIO 用它的容器名 `infra-minio`。
|
||||
|
||||
## 内存和 CPU 账
|
||||
|
||||
同箱的是跨项目生产件,失控的 Prometheus 或 Tempo 在 CPU/IO 上挤兑 new-api 就是事故,所以每件都设了内存和 CPU 双上限,`cpu_shares` 压到 512(生产件默认 1024 的一半),CPU 抢起来观测让路。
|
||||
|
||||
| 组件 | mem_limit | cpus | cpu_shares |
|
||||
|---|---|---|---|
|
||||
| Collector | 512m | 0.50 | 512 |
|
||||
| Prometheus | 1g | 0.75 | 512 |
|
||||
| Tempo | 768m | 0.50 | 512 |
|
||||
| Loki | 768m | 0.50 | 512 |
|
||||
| Grafana | 384m | 0.50 | 512 |
|
||||
|
||||
内存上限合计约 3.4G。mini-infra 扩到 32G 后 available 约 24Gi,装下这套还有大量余量。上限是纪律不是配额,扩了内存也照设。
|
||||
|
||||
## 存储
|
||||
|
||||
Tempo 的追踪块和 Loki 的日志块都存在既有 MinIO 上,各用独立的 `obs-tempo` / `obs-loki` 桶,和 ragflow 的桶完全分开。Tempo 的 WAL、Loki 的 index、Prometheus 的 TSDB、Grafana 的状态都落 docker 托管的本地卷(`tempo-data` / `loki-data` / `prometheus-data` / `grafana-data`),用 named volume 而非挂宿主目录,免掉 RocketMQ 那种 uid 权限坑。
|
||||
|
||||
保留期:Prometheus 指标 15 天(compose 里 `--storage.tsdb.retention.time`),Loki 日志 15 天(`limits_config.retention_period`),Tempo 追踪 7 天(`compactor.block_retention`)。MinIO 连不上的时候,Tempo/Loki 写不进对象存储会重试并在本地缓冲,Collector 那侧的队列满了会丢弃而不是把上游堵死。
|
||||
|
||||
## 脱敏(安全红线)
|
||||
|
||||
追踪的 span 属性里会带生成的输入输出,日志正文里会有报错原文,里面可能有用户手机号或 token。Collector 上有一道 `redaction` 处理器,在写进 Tempo 和 Loki 之前把手机号、token、密钥、JWT 这类打码,匹配规则在 `otel-collector-config.yaml` 里。这是进存储前的最后一道、也是不能绕过的一道:三条 pipeline(traces/metrics/logs)导出前都过它。验收时要专门造一条带构造手机号和 token 的生成,跑完在 Tempo 和 Loki 里查不到明文才算过。
|
||||
|
||||
## 密钥与配置
|
||||
|
||||
MinIO 的 access/secret key 和 Grafana 管理员口令都经 `.env` 的 `${VAR}` 注入,compose 文件和各配置文件里不落明文。`.env` 只在服务器上 `chmod 600` 存在、不入仓,权威副本在 `docs/内网凭据与端点.md`。
|
||||
|
||||
Tempo 和 Loki 的配置文件里写的是 `${MINIO_ACCESS_KEY}` 这种占位,靠各自启动参数 `-config.expand-env=true` 从容器环境变量展开,所以 compose 给这两件显式注入了环境变量。Collector 不直接连 MinIO,配置里不含密钥。
|
||||
|
||||
## 出事怎么回滚
|
||||
|
||||
观测是纯增量的旁路,回滚很干净,主链和业务代码一行不动:
|
||||
|
||||
```
|
||||
docker compose down # 停容器,数据卷和 MinIO 桶留着
|
||||
docker compose down -v # 连本地数据卷一起删(Prometheus/Grafana/WAL/index)
|
||||
```
|
||||
|
||||
MinIO 里的 `obs-tempo` / `obs-loki` 桶要清的话,用 mc 单独删,不会碰到 ragflow 的桶:
|
||||
|
||||
```
|
||||
mc rb --force obs/obs-tempo
|
||||
mc rb --force obs/obs-loki
|
||||
```
|
||||
|
||||
停掉整套栈之后,信号源那边推 OTLP 推不上会 best-effort 丢弃,生成主链行为不变。
|
||||
|
||||
## 后续波要接的
|
||||
|
||||
第一波之后,按设计 §8 的顺序:给 game-cloud 挂 OTel Java agent 加 actuator,把 Python 便宜档主路的 jsonl 换成真发 OTLP、tier2 的 studio_sink 改发 Collector,打通 Java→worker→本机 Service→回调 的三跳 traceparent,最后落业务埋点、建告警规则、把飞书/钉钉 webhook 接上。`prometheus.yml` 里已经把跨机抓 game-cloud / nacos / rocketmq 的 scrape 目标注释占位,那几件的指标端点就位后取消注释即可。
|
||||
217
deploy/infra/observability/docker-compose.yml
Normal file
217
deploy/infra/observability/docker-compose.yml
Normal file
@ -0,0 +1,217 @@
|
||||
# =============================================================================
|
||||
# 全链路可观测性栈 —— OTel Collector + Prometheus + Tempo + Loki + Grafana
|
||||
# 配置控制面阶段四 · 第一波(纯增量、不碰生产)
|
||||
# -----------------------------------------------------------------------------
|
||||
# 设计权威:docs/agent-specs/2026-07-05-全链路可观测性-OTel三信号全栈-设计.md
|
||||
# 五件的形状 = 多源汇一口、一口先脱敏再分三库、一板看到底(设计 §4)。
|
||||
# Collector 收 OTLP → 脱敏 + 尾部采样 + 批量 → Prometheus(指标)/ Tempo(追踪)
|
||||
# / Loki(日志);Grafana 统一看板 + 三联下钻。
|
||||
#
|
||||
# 落点 = mini-infra(100.64.0.8,已扩容到 32G / available 24Gi,设计 §10.6)。
|
||||
# 同箱的是跨项目生产件(new-api / gitea / nacos / rocketmq / ragflow),所以资源纪律
|
||||
# 要比 nacos/rocketmq 那套更严 —— 见下方"资源双上限"。
|
||||
#
|
||||
# ── 部署纪律(全部编进了本文件)──────────────────────────────────────────
|
||||
# 1) 网络:接既有 infra-shared 网(external、不新建),与 infra-minio / new-api /
|
||||
# infra-nacos / infra-rmq-namesrv 同网,容器间用 DNS 名互通。观测栈五件之间用
|
||||
# compose 服务名(otel-collector / prometheus / tempo / loki / grafana)解析;
|
||||
# 连既有件用其容器名(infra-minio)。
|
||||
#
|
||||
# 2) 端口避撞(逐个核对过 mini-infra 现有占用:new-api=3000 / gitea=3001 /
|
||||
# ragflow=9380-9381 / postgres=5433 / minio=9000-9001 / mysql=3306 / redis=6379 /
|
||||
# nacos=8848 / rocketmq=9876,10911 / nginx=80,443 / infinity=23817,23820):
|
||||
# Grafana → 3002 (3000/3001 已占,绝不用默认 3000)
|
||||
# Prometheus → 9090
|
||||
# Loki → 3100
|
||||
# Tempo → 3200 (query API)
|
||||
# Collector → 4317(gRPC OTLP)/ 4318(HTTP OTLP)/ 13133(健康探针)
|
||||
# Collector 自身遥测 8888 与业务指标出口 8889 不对外映射 —— Prometheus 同网 scrape。
|
||||
#
|
||||
# 3) 资源双上限(设计 §5 面三 / §9 硬红线):每件设 mem_limit + cpus 双上限,
|
||||
# 并把 cpu_shares 压到 512(生产件默认 1024 的一半),CPU 争用时观测让路,
|
||||
# 绝不让失控的 Prometheus/Tempo 在 CPU/IO 上挤兑 new-api(生成命脉)。
|
||||
# 五件 mem_limit 合计约 3.4G,落进 24Gi 余量绰绰有余。
|
||||
#
|
||||
# 4) 存储:Tempo / Loki 的对象存储后端复用既有 infra-minio(不占新端口),各用独立
|
||||
# 新桶 obs-tempo / obs-loki(绝不碰 ragflow 现有桶),桶由 minio-init 一次性建。
|
||||
# Prometheus 用本地卷、保留 15 天。WAL/index 等本地态落 named volume(避 uid 权限坑)。
|
||||
#
|
||||
# 5) 密钥:S3 凭据与 Grafana 口令经 ${VAR} 从同目录 .env 读(compose 起时自动加载),
|
||||
# 本文件与各配置文件都不落明文;.env 只在服务器 chmod 600 存在、不入仓,权威副本见
|
||||
# docs/内网凭据与端点.md。Tempo/Loki 配置内的 ${VAR} 由各自 -config.expand-env 从
|
||||
# 容器环境变量展开(故下面给这两件显式注入 environment)。
|
||||
#
|
||||
# 起停:cd /opt/infra-observability && docker compose up -d;探活见 health-check.sh。
|
||||
# 本文件由第一波交付,起容器由主控终审后择窗口做 —— 交付阶段不 up、不 ssh。
|
||||
# =============================================================================
|
||||
services:
|
||||
|
||||
# ── 一次性:在既有 infra-minio 上建观测专用桶(幂等,建完即退出)────────────
|
||||
# 用 mc 客户端连同网 MinIO,--ignore-existing 保证可重复执行不报错。
|
||||
# tempo / loki 经 depends_on 等它成功退出后再起,确保桶已就位。
|
||||
minio-init:
|
||||
image: minio/mc:RELEASE.2024-10-29T15-34-59Z
|
||||
container_name: infra-obs-minio-init
|
||||
networks: [infra-shared]
|
||||
environment:
|
||||
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
|
||||
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
|
||||
# $$ 转义:让 $ 原样传给容器内 shell 读环境变量,而非被 compose 提前替换。
|
||||
entrypoint: >
|
||||
/bin/sh -c "
|
||||
mc alias set obs http://infra-minio:9000 $${MINIO_ACCESS_KEY} $${MINIO_SECRET_KEY} &&
|
||||
mc mb --ignore-existing obs/obs-tempo &&
|
||||
mc mb --ignore-existing obs/obs-loki &&
|
||||
echo 'obs buckets ready: obs-tempo / obs-loki'
|
||||
"
|
||||
restart: "no"
|
||||
|
||||
# ── OTel Collector(统一入口)────────────────────────────────────────────
|
||||
# 收 OTLP(跨机经 Tailscale 推来)→ 脱敏 + 尾部采样 + 批量 → 分发三库。
|
||||
# 脱敏是进库前最后一道安全红线(手机号/token 打码)。健康探针在 13133。
|
||||
otel-collector:
|
||||
image: otel/opentelemetry-collector-contrib:0.116.0
|
||||
container_name: infra-otelcol
|
||||
restart: unless-stopped
|
||||
networks: [infra-shared]
|
||||
command: ["--config=/etc/otelcol-contrib/config.yaml"]
|
||||
volumes:
|
||||
- ./otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml:ro
|
||||
ports:
|
||||
- "4317:4317" # gRPC OTLP 入口(跨机信号源推送)
|
||||
- "4318:4318" # HTTP OTLP 入口(跨机信号源推送)
|
||||
- "13133:13133" # health_check extension(供 health-check.sh 探活)
|
||||
depends_on:
|
||||
- tempo
|
||||
- loki
|
||||
mem_limit: 512m
|
||||
cpus: 0.50
|
||||
cpu_shares: 512 # 低于生产件默认 1024,CPU 争用时让路
|
||||
logging:
|
||||
driver: json-file
|
||||
options: { max-size: "10m", max-file: "3" }
|
||||
|
||||
# ── Prometheus(指标存储)──────────────────────────────────────────────
|
||||
# 本地卷、保留 15 天。scrape 自身 + Collector 出口;跨机抓 game-cloud/nacos/rmq
|
||||
# 的目标在 prometheus.yml 里注释占位,后续波启用。
|
||||
prometheus:
|
||||
image: prom/prometheus:v3.1.0
|
||||
container_name: infra-prometheus
|
||||
restart: unless-stopped
|
||||
networks: [infra-shared]
|
||||
command:
|
||||
- "--config.file=/etc/prometheus/prometheus.yml"
|
||||
- "--storage.tsdb.path=/prometheus"
|
||||
- "--storage.tsdb.retention.time=15d" # 保留期 15 天(设计 §7,7-15d 上限)
|
||||
- "--web.enable-lifecycle" # 允许热加载配置(POST /-/reload)
|
||||
volumes:
|
||||
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
||||
- prometheus-data:/prometheus
|
||||
ports:
|
||||
- "9090:9090"
|
||||
mem_limit: 1g
|
||||
cpus: 0.75
|
||||
cpu_shares: 512
|
||||
logging:
|
||||
driver: json-file
|
||||
options: { max-size: "10m", max-file: "3" }
|
||||
|
||||
# ── Tempo(追踪存储,后端 = MinIO/obs-tempo)──────────────────────────────
|
||||
# 单进程 monolithic。收 Collector 转发的 OTLP(容器内 4317,不对外映射),blocks
|
||||
# 落 MinIO、WAL 落本地卷。-config.expand-env 让配置里的 ${MINIO_*} 从环境变量展开。
|
||||
tempo:
|
||||
image: grafana/tempo:2.7.1
|
||||
container_name: infra-tempo
|
||||
restart: unless-stopped
|
||||
networks: [infra-shared]
|
||||
command: ["-config.file=/etc/tempo.yaml", "-config.expand-env=true"]
|
||||
environment:
|
||||
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
|
||||
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
|
||||
volumes:
|
||||
- ./tempo.yaml:/etc/tempo.yaml:ro
|
||||
- tempo-data:/var/tempo
|
||||
ports:
|
||||
- "3200:3200" # query API(Grafana 内网走 tempo:3200,对外便于调试/探活)
|
||||
depends_on:
|
||||
minio-init:
|
||||
condition: service_completed_successfully
|
||||
mem_limit: 768m
|
||||
cpus: 0.50
|
||||
cpu_shares: 512
|
||||
logging:
|
||||
driver: json-file
|
||||
options: { max-size: "10m", max-file: "3" }
|
||||
|
||||
# ── Loki(日志存储,后端 = MinIO/obs-loki)────────────────────────────────
|
||||
# 单进程 monolithic。只收 WARN/ERROR(在源头控),chunks 落 MinIO、index 落本地卷。
|
||||
# OTLP 摄入端点 = :3100/otlp,Collector 用 otlphttp 发到这里。
|
||||
loki:
|
||||
image: grafana/loki:3.3.2
|
||||
container_name: infra-loki
|
||||
restart: unless-stopped
|
||||
networks: [infra-shared]
|
||||
command: ["-config.file=/etc/loki/loki-config.yaml", "-config.expand-env=true"]
|
||||
environment:
|
||||
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
|
||||
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
|
||||
volumes:
|
||||
- ./loki-config.yaml:/etc/loki/loki-config.yaml:ro
|
||||
- loki-data:/loki
|
||||
ports:
|
||||
- "3100:3100"
|
||||
depends_on:
|
||||
minio-init:
|
||||
condition: service_completed_successfully
|
||||
mem_limit: 768m
|
||||
cpus: 0.50
|
||||
cpu_shares: 512
|
||||
logging:
|
||||
driver: json-file
|
||||
options: { max-size: "10m", max-file: "3" }
|
||||
|
||||
# ── Grafana(统一看板 + 告警 + admin 一键进盘)──────────────────────────
|
||||
# 预配三数据源(Prometheus/Tempo/Loki)+ 三联下钻 + 概览盘。容器内 3000、对外 3002。
|
||||
# admin 口令经 .env 注入;首次进盘即见数据源与看板(设计 §10.3 本期做)。
|
||||
grafana:
|
||||
image: grafana/grafana:11.4.0
|
||||
container_name: infra-grafana
|
||||
restart: unless-stopped
|
||||
networks: [infra-shared]
|
||||
environment:
|
||||
GF_SECURITY_ADMIN_USER: ${GF_ADMIN_USER:-admin}
|
||||
GF_SECURITY_ADMIN_PASSWORD: ${GF_ADMIN_PASSWORD}
|
||||
GF_USERS_ALLOW_SIGN_UP: "false"
|
||||
GF_ANALYTICS_REPORTING_ENABLED: "false"
|
||||
GF_ANALYTICS_CHECK_FOR_UPDATES: "false"
|
||||
# 三联下钻(trace↔log↔metric)在 Grafana 11 已 GA,靠数据源 provisioning 的 jsonData
|
||||
# 配跳转即可,无需 feature toggle。
|
||||
volumes:
|
||||
- ./grafana/provisioning:/etc/grafana/provisioning:ro
|
||||
- ./grafana/dashboards:/var/lib/grafana/dashboards:ro
|
||||
- grafana-data:/var/lib/grafana
|
||||
ports:
|
||||
- "3002:3000"
|
||||
depends_on:
|
||||
- prometheus
|
||||
- tempo
|
||||
- loki
|
||||
mem_limit: 384m
|
||||
cpus: 0.50
|
||||
cpu_shares: 512
|
||||
logging:
|
||||
driver: json-file
|
||||
options: { max-size: "10m", max-file: "3" }
|
||||
|
||||
# ── 既有共享网(external,不新建)──────────────────────────────────────────
|
||||
networks:
|
||||
infra-shared:
|
||||
external: true
|
||||
|
||||
# ── 本地持久卷(docker 托管,避 bind-mount 的 uid 权限坑)────────────────────
|
||||
# Prometheus TSDB / Grafana 状态需持久;Tempo WAL / Loki index 是本地热态,块数据在 MinIO。
|
||||
volumes:
|
||||
prometheus-data:
|
||||
grafana-data:
|
||||
tempo-data:
|
||||
loki-data:
|
||||
@ -0,0 +1,108 @@
|
||||
{
|
||||
"annotations": { "list": [] },
|
||||
"editable": true,
|
||||
"graphTooltip": 1,
|
||||
"time": { "from": "now-6h", "to": "now" },
|
||||
"refresh": "30s",
|
||||
"schemaVersion": 39,
|
||||
"tags": ["huijing", "observability"],
|
||||
"title": "绘境AI · 可观测总览",
|
||||
"uid": "huijing-obs-overview",
|
||||
"templating": { "list": [] },
|
||||
"panels": [
|
||||
{
|
||||
"type": "row",
|
||||
"title": "观测栈自监控(Collector · 起栈即有数据)",
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 },
|
||||
"collapsed": false,
|
||||
"panels": []
|
||||
},
|
||||
{
|
||||
"type": "timeseries",
|
||||
"title": "Collector 接收信号速率(spans/logs/metrics per s)",
|
||||
"description": "OTLP 入口吞吐。三条生成/服务路推来的信号量。",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 1 },
|
||||
"fieldConfig": { "defaults": { "unit": "reqps" }, "overrides": [] },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "sum(rate(otelcol_receiver_accepted_spans_total[5m]))", "legendFormat": "spans" },
|
||||
{ "refId": "B", "expr": "sum(rate(otelcol_receiver_accepted_log_records_total[5m]))", "legendFormat": "logs" },
|
||||
{ "refId": "C", "expr": "sum(rate(otelcol_receiver_accepted_metric_points_total[5m]))", "legendFormat": "metrics" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "timeseries",
|
||||
"title": "Collector 导出成功/失败 + 队列(丢弃即后端不可达)",
|
||||
"description": "验收第 6 条要看的 queue/drop 指标。send_failed 持续 > 0 说明后端抖动或不可达。",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 1 },
|
||||
"fieldConfig": { "defaults": {}, "overrides": [] },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "sum(rate(otelcol_exporter_sent_spans_total[5m]))", "legendFormat": "sent spans/s" },
|
||||
{ "refId": "B", "expr": "sum(rate(otelcol_exporter_send_failed_spans_total[5m]))", "legendFormat": "failed spans/s" },
|
||||
{ "refId": "C", "expr": "sum(otelcol_exporter_queue_size)", "legendFormat": "queue size" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "stat",
|
||||
"title": "被监控目标存活(Prometheus up)",
|
||||
"description": "每个 scrape target 的 up/down。后续波接入 game-cloud/nacos/rmq 后这里会长出更多目标。",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 6, "w": 12, "x": 0, "y": 9 },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{ "type": "value", "options": { "0": { "text": "DOWN", "color": "red" }, "1": { "text": "UP", "color": "green" } } }
|
||||
]
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"options": { "colorMode": "background", "textMode": "value_and_name" },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "up", "legendFormat": "{{job}}", "instant": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "row",
|
||||
"title": "业务指标(占位 · 后续波埋点落地后生效)",
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 15 },
|
||||
"collapsed": false,
|
||||
"panels": []
|
||||
},
|
||||
{
|
||||
"type": "timeseries",
|
||||
"title": "生成成功率(按状态)",
|
||||
"description": "占位:待 game-cloud 在任务终态回填处埋 huijing_gen_task_total{status}(设计 §6)。埋点前无数据。",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 8, "w": 8, "x": 0, "y": 16 },
|
||||
"fieldConfig": { "defaults": { "unit": "percentunit" }, "overrides": [] },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "sum(rate(huijing_gen_task_total{status=\"success\"}[30m])) / clamp_min(sum(rate(huijing_gen_task_total[30m])), 1)", "legendFormat": "成功率" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "timeseries",
|
||||
"title": "生成耗时 P50/P95",
|
||||
"description": "占位:待 worker 导出 huijing_gen_duration_seconds histogram(设计 §6)。埋点前无数据。",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 8, "w": 8, "x": 8, "y": 16 },
|
||||
"fieldConfig": { "defaults": { "unit": "s" }, "overrides": [] },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "histogram_quantile(0.50, sum(rate(huijing_gen_duration_seconds_bucket[5m])) by (le))", "legendFormat": "P50" },
|
||||
{ "refId": "B", "expr": "histogram_quantile(0.95, sum(rate(huijing_gen_duration_seconds_bucket[5m])) by (le))", "legendFormat": "P95" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "timeseries",
|
||||
"title": "队列深度 / 九门失败",
|
||||
"description": "占位:待埋 huijing_gen_queue_depth(gauge)与 huijing_gen_gate_fail_total{gate}(设计 §6)。埋点前无数据。",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 8, "w": 8, "x": 16, "y": 16 },
|
||||
"fieldConfig": { "defaults": {}, "overrides": [] },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "max(huijing_gen_queue_depth)", "legendFormat": "队列深度" },
|
||||
{ "refId": "B", "expr": "sum(rate(huijing_gen_gate_fail_total[30m])) by (gate)", "legendFormat": "门失败 {{gate}}" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
# =============================================================================
|
||||
# Grafana 看板 provisioning —— 从文件加载看板(/var/lib/grafana/dashboards)
|
||||
# 第一波先放一块概览盘;后续波随业务埋点落地补更多盘,放同目录即自动加载。
|
||||
# =============================================================================
|
||||
apiVersion: 1
|
||||
|
||||
providers:
|
||||
- name: huijing-observability
|
||||
orgId: 1
|
||||
folder: "绘境AI 可观测"
|
||||
type: file
|
||||
disableDeletion: false
|
||||
updateIntervalSeconds: 30
|
||||
allowUiUpdates: true
|
||||
options:
|
||||
path: /var/lib/grafana/dashboards
|
||||
foldersFromFilesStructure: false
|
||||
@ -0,0 +1,67 @@
|
||||
# =============================================================================
|
||||
# Grafana 数据源 provisioning —— 三数据源 + 指标↔追踪↔日志三联下钻
|
||||
# 设计 §5 面三/§10.3:预配 Prometheus/Tempo/Loki,开箱三联下钻,admin 一键进盘。
|
||||
# URL 用 compose 服务名(同 infra-shared 网内解析),内网无鉴权。
|
||||
# 注:provisioning 里 Grafana 会展开 ${...} 环境变量,故 Grafana 内部变量(如
|
||||
# ${__value.raw} / ${__trace.traceId})一律写成 $${...} 转义,避免被当环境变量吞掉。
|
||||
# =============================================================================
|
||||
apiVersion: 1
|
||||
|
||||
datasources:
|
||||
# ── Prometheus:默认数据源 ──────────────────────────────────────────────
|
||||
- name: Prometheus
|
||||
uid: prometheus
|
||||
type: prometheus
|
||||
access: proxy
|
||||
url: http://prometheus:9090
|
||||
isDefault: true
|
||||
jsonData:
|
||||
httpMethod: POST
|
||||
# exemplar 上的 trace_id 直接跳 Tempo(指标 → 追踪 下钻)
|
||||
exemplarTraceIdDestinations:
|
||||
- name: trace_id
|
||||
datasourceUid: tempo
|
||||
|
||||
# ── Tempo:追踪。配 追踪→日志 / 追踪→指标 / 服务图 三向下钻 ──────────────────
|
||||
- name: Tempo
|
||||
uid: tempo
|
||||
type: tempo
|
||||
access: proxy
|
||||
url: http://tempo:3200
|
||||
jsonData:
|
||||
# 追踪 → 日志:带 traceID 跳到 Loki 查同一条链路的日志
|
||||
tracesToLogsV2:
|
||||
datasourceUid: loki
|
||||
spanStartTimeShift: "-1h"
|
||||
spanEndTimeShift: "1h"
|
||||
filterByTraceID: true
|
||||
filterBySpanID: false
|
||||
# 追踪 → 指标:跳到 Prometheus 看相关指标
|
||||
tracesToMetrics:
|
||||
datasourceUid: prometheus
|
||||
spanStartTimeShift: "-1h"
|
||||
spanEndTimeShift: "1h"
|
||||
# 服务拓扑图与节点图(基于 span 关系)
|
||||
serviceMap:
|
||||
datasourceUid: prometheus
|
||||
nodeGraph:
|
||||
enabled: true
|
||||
traceQuery:
|
||||
timeShiftEnabled: true
|
||||
spanStartTimeShift: "-1h"
|
||||
spanEndTimeShift: "1h"
|
||||
|
||||
# ── Loki:日志。配 日志→追踪 下钻(从日志里的 trace_id 跳 Tempo)──────────────
|
||||
- name: Loki
|
||||
uid: loki
|
||||
type: loki
|
||||
access: proxy
|
||||
url: http://loki:3100
|
||||
jsonData:
|
||||
# derivedFields:从日志行/结构化元数据里提取 trace_id,一键跳到 Tempo 对应 trace。
|
||||
# 后续波真接入日志后,按实际 trace_id 落地形态(structured metadata / 正文 JSON)微调正则。
|
||||
derivedFields:
|
||||
- name: trace_id
|
||||
matcherRegex: '"trace_id":"(\w+)"'
|
||||
url: "$${__value.raw}"
|
||||
datasourceUid: tempo
|
||||
57
deploy/infra/observability/health-check.sh
Executable file
57
deploy/infra/observability/health-check.sh
Executable file
@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# 观测栈健康探针 —— 五件就绪判定(配置控制面阶段四 · 第一波)
|
||||
# -----------------------------------------------------------------------------
|
||||
# 一次探完 Collector / Prometheus / Tempo / Loki / Grafana 五个对外端点,
|
||||
# 全绿(全部 HTTP 200)整体 PASS 退 0;任一非 200 / 超时则 FAIL 退 1。
|
||||
#
|
||||
# 两处内网纪律(与 nacos/rocketmq 探针一致):
|
||||
# - `--noproxy '*'`:本机系统代理是 fake-ip(198.18.x);内网直连(Tailscale 100.64.x)
|
||||
# 必须绕过它,否则连接被代理拦下返 000。这是内网外呼铁律。
|
||||
# - curl -w 恒输出 http_code(失败为 000);仅在 curl 二进制本身返空时兜底 000,
|
||||
# 不用 `|| echo 000`(会与 -w 的 000 叠成 "000000")。
|
||||
#
|
||||
# 各件探的就绪端点:
|
||||
# Collector :13133 / health_check extension(就绪返 200)
|
||||
# Prometheus :9090 /-/healthy 自身健康
|
||||
# Tempo :3200 /ready 就绪(未就绪期返 503,就绪后 200)
|
||||
# Loki :3100 /ready 就绪(未就绪期返 503,就绪后 200)
|
||||
# Grafana :3002 /api/health 自身健康(DB/插件就绪返 200)
|
||||
#
|
||||
# 用法:HOST=100.64.0.8 bash deploy/infra/observability/health-check.sh
|
||||
# =============================================================================
|
||||
set -uo pipefail
|
||||
|
||||
HOST="${HOST:-100.64.0.8}"
|
||||
MAX_TIME="${MAX_TIME:-8}"
|
||||
|
||||
# 探针清单:名称|URL。逐个探,记录结果。
|
||||
CHECKS=(
|
||||
"Collector|http://${HOST}:13133/"
|
||||
"Prometheus|http://${HOST}:9090/-/healthy"
|
||||
"Tempo|http://${HOST}:3200/ready"
|
||||
"Loki|http://${HOST}:3100/ready"
|
||||
"Grafana|http://${HOST}:3002/api/health"
|
||||
)
|
||||
|
||||
fail=0
|
||||
for item in "${CHECKS[@]}"; do
|
||||
name="${item%%|*}"
|
||||
url="${item#*|}"
|
||||
code="$(curl -s -o /dev/null -w '%{http_code}' --noproxy '*' --max-time "${MAX_TIME}" "${url}" 2>/dev/null)"
|
||||
code="${code:-000}"
|
||||
if [[ "$code" == "200" ]]; then
|
||||
echo "PASS ${name} 200 @ ${url}"
|
||||
else
|
||||
echo "FAIL ${name}=${code} @ ${url}"
|
||||
fail=1
|
||||
fi
|
||||
done
|
||||
|
||||
echo "---"
|
||||
if [[ "$fail" == "0" ]]; then
|
||||
echo "PASS 观测栈五件全绿 @ ${HOST}"
|
||||
exit 0
|
||||
fi
|
||||
echo "FAIL 观测栈存在未就绪组件 @ ${HOST}(见上)"
|
||||
exit 1
|
||||
75
deploy/infra/observability/loki-config.yaml
Normal file
75
deploy/infra/observability/loki-config.yaml
Normal file
@ -0,0 +1,75 @@
|
||||
# =============================================================================
|
||||
# Loki 配置 —— 日志存储 · 单进程 monolithic · 后端 = MinIO(obs-loki 桶)
|
||||
# 设计 §4/§6:只收 WARN/ERROR(在源头控级别),chunks 落 MinIO、index 落本地卷。
|
||||
# Collector 用 otlphttp 发到 :3100/otlp(Loki 3.x 原生 OTLP 摄入端点)。
|
||||
# ${MINIO_*} 由启动参数 -config.expand-env=true 从容器环境变量展开(compose 注入)。
|
||||
# =============================================================================
|
||||
|
||||
# 内网单机、不启多租户鉴权(鉴权由所在网络与 nginx 边界兜)。
|
||||
auth_enabled: false
|
||||
|
||||
server:
|
||||
http_listen_port: 3100
|
||||
grpc_listen_port: 9096 # 与 Tempo 的 9095 错开(虽不同容器不冲突,显式区分省心)
|
||||
log_level: info
|
||||
|
||||
common:
|
||||
instance_addr: 127.0.0.1
|
||||
path_prefix: /loki # 本地态根目录(落 named volume loki-data)
|
||||
replication_factor: 1
|
||||
ring:
|
||||
kvstore:
|
||||
store: inmemory # 单实例,环状态放内存即可
|
||||
|
||||
schema_config:
|
||||
configs:
|
||||
- from: 2024-01-01
|
||||
store: tsdb
|
||||
object_store: s3
|
||||
schema: v13 # 当前稳定 schema
|
||||
index:
|
||||
prefix: index_
|
||||
period: 24h
|
||||
|
||||
storage_config:
|
||||
tsdb_shipper:
|
||||
active_index_directory: /loki/index
|
||||
cache_location: /loki/index_cache
|
||||
# S3(MinIO)分字段配置:endpoint 不带 scheme,insecure=true 走 HTTP,
|
||||
# s3forcepathstyle=true 是 MinIO 必需(AWS SDK 默认 virtual-host 风格,MinIO 用 path 风格)。
|
||||
aws:
|
||||
endpoint: infra-minio:9000
|
||||
bucketnames: obs-loki # 观测专用桶,绝不碰 ragflow 现有桶
|
||||
access_key_id: ${MINIO_ACCESS_KEY}
|
||||
secret_access_key: ${MINIO_SECRET_KEY}
|
||||
s3forcepathstyle: true
|
||||
insecure: true
|
||||
|
||||
compactor:
|
||||
working_directory: /loki/retention
|
||||
compaction_interval: 10m
|
||||
retention_enabled: true # 开启保留期回收(否则日志只增不删)
|
||||
retention_delete_delay: 2h
|
||||
retention_delete_worker_count: 100
|
||||
delete_request_store: s3 # 删除请求也落 S3(retention_enabled 时必配)
|
||||
|
||||
limits_config:
|
||||
retention_period: 360h # 日志保留 15 天(与 Prometheus 保留期看齐)
|
||||
reject_old_samples: true
|
||||
reject_old_samples_max_age: 168h
|
||||
allow_structured_metadata: true # OTLP 摄入把 trace_id 等作为 structured metadata 存
|
||||
volume_enabled: true
|
||||
ingestion_rate_mb: 8 # 只收 WARN/ERROR,8MB/s 足够、且给失控日志封顶
|
||||
ingestion_burst_size_mb: 16
|
||||
|
||||
ruler:
|
||||
storage:
|
||||
type: local
|
||||
local:
|
||||
directory: /loki/rules
|
||||
rule_path: /loki/rules-temp
|
||||
enable_api: true
|
||||
|
||||
# 关掉匿名用量上报(内网、不外呼)。
|
||||
analytics:
|
||||
reporting_enabled: false
|
||||
148
deploy/infra/observability/otel-collector-config.yaml
Normal file
148
deploy/infra/observability/otel-collector-config.yaml
Normal file
@ -0,0 +1,148 @@
|
||||
# =============================================================================
|
||||
# OTel Collector 配置 —— 统一入口:收 OTLP → 脱敏 + 尾采样 + 批量 → 分发三库
|
||||
# 设计 §4/§5 面三/§8:脱敏是进 Tempo/Loki 前的最后一道安全红线;尾采样错误+慢全采、
|
||||
# 正常抽样;后端不可达时本地缓冲丢弃而非阻塞主链。
|
||||
#
|
||||
# 组件全部取自 opentelemetry-collector-contrib(redaction / tail_sampling 是 contrib 件,
|
||||
# core 镜像没有,故 compose 用 -contrib 镜像)。
|
||||
# =============================================================================
|
||||
|
||||
extensions:
|
||||
# 健康探针:health-check.sh 探 :13133 判就绪。
|
||||
health_check:
|
||||
endpoint: 0.0.0.0:13133
|
||||
|
||||
receivers:
|
||||
# OTLP 唯一入口。跨机信号源(game-cloud / 两条生成线,都在别处)经 Tailscale 推到
|
||||
# mini-infra 的 4317(gRPC)/4318(HTTP)。监听 0.0.0.0 才能收到容器外/跨机流量。
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
endpoint: 0.0.0.0:4317
|
||||
http:
|
||||
endpoint: 0.0.0.0:4318
|
||||
|
||||
processors:
|
||||
# ── 内存护栏:软红线,超阈值即拒收/丢弃,防 Collector 自身 OOM 拖累同箱 new-api ──
|
||||
# 达 limit 时开始拒绝新数据(back-pressure 上游 best-effort 上报会丢而非把 Collector 撑爆)。
|
||||
memory_limiter:
|
||||
check_interval: 1s
|
||||
limit_percentage: 75
|
||||
spike_limit_percentage: 15
|
||||
|
||||
# ── 尾部采样:一条 trace 的所有 span 齐了再决策(设计 §7)──────────────────
|
||||
# 多策略取"或":错误全采 + 慢(>2s)全采 + 其余按 10% 概率采。既盯住所有异常/慢链路,
|
||||
# 又把正常链路的存储量压到一成。decision_wait 是等齐 span 的窗口。
|
||||
tail_sampling:
|
||||
decision_wait: 10s
|
||||
num_traces: 20000 # 决策期内最多缓存的 trace 数(内存换准确)
|
||||
expected_new_traces_per_sec: 200
|
||||
policies:
|
||||
- name: errors-always # 错误链路:全采
|
||||
type: status_code
|
||||
status_code:
|
||||
status_codes: [ERROR]
|
||||
- name: slow-always # 慢链路(>2000ms):全采
|
||||
type: latency
|
||||
latency:
|
||||
threshold_ms: 2000
|
||||
- name: sample-normal # 其余正常链路:10% 抽样
|
||||
type: probabilistic
|
||||
probabilistic:
|
||||
sampling_percentage: 10
|
||||
|
||||
# ── 脱敏:进库前最后一道安全红线(设计 §4/§8 第 7 条)────────────────────────
|
||||
# 手机号 / token / 密钥 在写入 Tempo(span 属性)与 Loki(日志正文)前打码。
|
||||
# allow_all_keys=true:不删属性(保留可观测性),只把命中键名或命中值的内容 mask。
|
||||
# - blocked_key_patterns:键名像密钥的,整值打码(token/secret/password/api_key/…)。
|
||||
# - blocked_values:值本身匹配敏感格式的打码(中国大陆手机号 / 常见密钥前缀 / JWT)。
|
||||
# redact_all_types=true:非字符串(如 int 型手机号)也按字符串形态检查。
|
||||
# summary=info:只记打码计数、不记键名,避免摘要本身泄信息。
|
||||
redaction:
|
||||
allow_all_keys: true
|
||||
redact_all_types: true
|
||||
blocked_key_patterns:
|
||||
- "(?i).*(token|secret|password|passwd|api[_-]?key|access[_-]?key|authorization|cookie|credential).*"
|
||||
blocked_values:
|
||||
- "1[3-9]\\d{9}" # 中国大陆手机号
|
||||
- "(?i)(sk|pk|api|key|token|bearer|ghp|xox)[-_][A-Za-z0-9]{16,}" # 常见密钥/令牌前缀
|
||||
- "eyJ[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{4,}" # JWT
|
||||
summary: info
|
||||
|
||||
# ── 批量:降导出频次、提吞吐。放在 pipeline 末端、导出前。──
|
||||
batch:
|
||||
timeout: 5s
|
||||
send_batch_size: 512
|
||||
send_batch_max_size: 1024
|
||||
|
||||
exporters:
|
||||
# ── 追踪 → Tempo(容器内 OTLP gRPC,同网明文 insecure)──────────────────────
|
||||
# sending_queue = 本地内存缓冲;retry_on_failure = 后端抖动时重试。队列满即丢弃
|
||||
# (不阻塞接收)——对应设计 §8"Collector 不可达/后端不可达时本地丢弃而非阻塞"。
|
||||
otlp/tempo:
|
||||
endpoint: tempo:4317
|
||||
tls:
|
||||
insecure: true
|
||||
sending_queue:
|
||||
enabled: true
|
||||
queue_size: 5000
|
||||
retry_on_failure:
|
||||
enabled: true
|
||||
initial_interval: 5s
|
||||
max_interval: 30s
|
||||
max_elapsed_time: 300s
|
||||
|
||||
# ── 指标 → Prometheus 出口(暴露 /metrics 在 8889,由 Prometheus 主动 scrape)──
|
||||
# namespace=huijing:业务指标统一前缀 huijing_*(如 huijing_gen_task_total)。
|
||||
# resource_to_telemetry_conversion:把 resource 属性(service.name 等)落成指标标签。
|
||||
prometheus:
|
||||
endpoint: 0.0.0.0:8889
|
||||
namespace: huijing
|
||||
resource_to_telemetry_conversion:
|
||||
enabled: true
|
||||
enable_open_metrics: true
|
||||
|
||||
# ── 日志 → Loki 的 OTLP 摄入端点(:3100/otlp,exporter 自动补 /v1/logs)──────
|
||||
otlphttp/loki:
|
||||
endpoint: http://loki:3100/otlp
|
||||
sending_queue:
|
||||
enabled: true
|
||||
queue_size: 5000
|
||||
retry_on_failure:
|
||||
enabled: true
|
||||
initial_interval: 5s
|
||||
max_interval: 30s
|
||||
max_elapsed_time: 300s
|
||||
|
||||
service:
|
||||
extensions: [health_check]
|
||||
telemetry:
|
||||
# Collector 自身遥测暴露在 0.0.0.0:8888,供 Prometheus scrape(队列深度/丢弃数等,
|
||||
# 用于验收第 6 条"agent 的 queue/drop 指标可见")。默认只在 localhost,须显式放开。
|
||||
# 下面是 0.116 的 readers 写法;若该版本起容器时报 telemetry 配置错,退回老式(仍受支持):
|
||||
# metrics:
|
||||
# level: detailed
|
||||
# address: 0.0.0.0:8888
|
||||
metrics:
|
||||
readers:
|
||||
- pull:
|
||||
exporter:
|
||||
prometheus:
|
||||
host: 0.0.0.0
|
||||
port: 8888
|
||||
pipelines:
|
||||
# 追踪:限流 → 尾采样 → 脱敏 → 批量 → Tempo。脱敏在导出前、不可绕过。
|
||||
traces:
|
||||
receivers: [otlp]
|
||||
processors: [memory_limiter, tail_sampling, redaction, batch]
|
||||
exporters: [otlp/tempo]
|
||||
# 指标:限流 → 脱敏(指标标签也可能带敏感值)→ 批量 → Prometheus 出口。
|
||||
metrics:
|
||||
receivers: [otlp]
|
||||
processors: [memory_limiter, redaction, batch]
|
||||
exporters: [prometheus]
|
||||
# 日志:限流 → 脱敏(日志正文里有报错原文)→ 批量 → Loki。
|
||||
logs:
|
||||
receivers: [otlp]
|
||||
processors: [memory_limiter, redaction, batch]
|
||||
exporters: [otlphttp/loki]
|
||||
47
deploy/infra/observability/prometheus.yml
Normal file
47
deploy/infra/observability/prometheus.yml
Normal file
@ -0,0 +1,47 @@
|
||||
# =============================================================================
|
||||
# Prometheus 配置 —— 指标存储 · 自监控 + Collector 出口抓取
|
||||
# 设计 §5 面三:本波先自监控(scrape 自身 + Collector),跨机抓 game-cloud/nacos/rmq
|
||||
# 的目标注释占位、后续波启用。保留期由 compose 的 --storage.tsdb.retention.time=15d 定。
|
||||
# =============================================================================
|
||||
global:
|
||||
scrape_interval: 30s # 30s 一轮,低负载够用、省资源
|
||||
evaluation_interval: 30s
|
||||
external_labels:
|
||||
cluster: huijing-mvp
|
||||
site: mini-infra
|
||||
|
||||
scrape_configs:
|
||||
# ── 自监控:Prometheus 自身 ──
|
||||
- job_name: prometheus
|
||||
static_configs:
|
||||
- targets: ["localhost:9090"]
|
||||
|
||||
# ── Collector 导出的业务指标(namespace=huijing,如 huijing_gen_task_total)──
|
||||
# Collector 的 prometheus exporter 暴露在 8889;同网用服务名解析,不走对外端口。
|
||||
- job_name: otel-collector
|
||||
static_configs:
|
||||
- targets: ["otel-collector:8889"]
|
||||
|
||||
# ── Collector 自身遥测(队列深度/丢弃数等,otelcol_* 指标,验收第 6 条要看)──
|
||||
- job_name: otel-collector-internal
|
||||
static_configs:
|
||||
- targets: ["otel-collector:8888"]
|
||||
|
||||
# =========================================================================
|
||||
# 预留 · 后续波启用(跨机经 Tailscale 100.64.0.x)。启用前置条件见设计 §5 面一:
|
||||
# game-cloud 要先挂 actuator/micrometer 让 /actuator/prometheus 端点成立;
|
||||
# nacos/rocketmq 的 micrometer 端点同样待各自 exporter 就位。端口按各服务实际暴露核对。
|
||||
# =========================================================================
|
||||
# - job_name: game-cloud
|
||||
# metrics_path: /actuator/prometheus
|
||||
# static_configs:
|
||||
# - targets: ["100.64.0.X:PORT"] # game-cloud 单体 actuator 端口(待定)
|
||||
#
|
||||
# - job_name: nacos
|
||||
# metrics_path: /nacos/actuator/prometheus
|
||||
# static_configs:
|
||||
# - targets: ["100.64.0.8:8848"]
|
||||
#
|
||||
# - job_name: rocketmq
|
||||
# static_configs:
|
||||
# - targets: ["100.64.0.8:PORT"] # rocketmq-exporter 端口(待部署)
|
||||
55
deploy/infra/observability/tempo.yaml
Normal file
55
deploy/infra/observability/tempo.yaml
Normal file
@ -0,0 +1,55 @@
|
||||
# =============================================================================
|
||||
# Tempo 配置 —— 追踪存储 · 单进程 monolithic · 后端 = MinIO(obs-tempo 桶)
|
||||
# 设计 §7:选 Tempo(同 Grafana 体系、三联下钻、对象存储内存友好)。
|
||||
# 收 Collector 转发的 OTLP;blocks 落 MinIO、WAL 落本地卷 /var/tempo。
|
||||
# ${MINIO_*} 由启动参数 -config.expand-env=true 从容器环境变量展开(compose 注入)。
|
||||
# =============================================================================
|
||||
|
||||
# 允许 Grafana 经 HTTP 流式拉取查询结果(TraceQL 搜索用)。
|
||||
stream_over_http_enabled: true
|
||||
|
||||
server:
|
||||
http_listen_port: 3200 # 对外 query API(compose 映射 3200,Grafana 内网走 tempo:3200)
|
||||
grpc_listen_port: 9095
|
||||
|
||||
distributor:
|
||||
receivers:
|
||||
# Collector 用 otlp/tempo exporter 发到这里(容器内 4317,不对外映射,不与
|
||||
# Collector 对外的 4317 冲突 —— 不同容器各自独立监听)。
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
endpoint: "0.0.0.0:4317"
|
||||
http:
|
||||
endpoint: "0.0.0.0:4318"
|
||||
|
||||
ingester:
|
||||
# 尽快切块落对象存储,降低内存里活跃 trace 的驻留(mini-infra 资源纪律)。
|
||||
max_block_duration: 5m
|
||||
|
||||
compactor:
|
||||
compaction:
|
||||
block_retention: 168h # 追踪保留 7 天(设计 §4:Tempo 追踪 · MinIO bucket)
|
||||
|
||||
storage:
|
||||
trace:
|
||||
backend: s3
|
||||
wal:
|
||||
path: /var/tempo/wal # 本地 WAL(落 named volume tempo-data)
|
||||
s3:
|
||||
endpoint: infra-minio:9000 # 同网 DNS 名,复用既有 MinIO
|
||||
bucket: obs-tempo # 观测专用桶,绝不碰 ragflow 现有桶
|
||||
access_key: ${MINIO_ACCESS_KEY}
|
||||
secret_key: ${MINIO_SECRET_KEY}
|
||||
insecure: true # MinIO 同网走 HTTP、非 TLS(endpoint 为 IP:port,
|
||||
# minio-go 自动用 path-style,无需额外 forcepathstyle 字段)
|
||||
|
||||
# 关掉匿名用量上报(内网、不外呼)。
|
||||
usage_report:
|
||||
reporting_enabled: false
|
||||
|
||||
# 单租户默认摄入上限:MVP 单机、留足头。
|
||||
overrides:
|
||||
defaults:
|
||||
ingestion:
|
||||
max_traces_per_user: 50000
|
||||
Loading…
x
Reference in New Issue
Block a user