Observability Lgtm

为 FastAPI 应用搭建本地日志、指标、链路追踪一体化监控系统。

已扫描
适合谁
FastAPI 开发者、本地调试与性能分析人员
不适合谁
生产环境部署用户、非 Python 或非 FastAPI 项目开发者
国内可用性
需网络配置。可能需要网络配置或第三方服务可访问。
安装难度
中等(★★☆)。基于终端操作、依赖、API Key 和本地环境要求的初步判断。

安装与下载

openclaw skills install @nissan/observability-lgtm

Skill 说明

命令、参数、文件名以原文为准

最后使用时间: 2026-03-24

内存引用次数: 7

状态: 激活中

observability-lgtm

在 macOS(Apple Silicon)或 Linux 上为 FastAPI 应用快速搭建完整的本地可观测性栈(Loki + Grafana + Tempo + Prometheus + Alloy)。一条命令启动服务,一个导入即可为任意应用添加观测能力。日志 → Loki,指标 → Prometheus,链路追踪 → Tempo,全部统一在 Grafana 中展示。

适用场景

  • 正在开发 FastAPI Web 应用,需要日志、指标和链路追踪功能
  • 希望在本地通过 Grafana 查看仪表盘,而无需部署复杂的 ELK 栈(过于沉重)
  • 需要在同一界面中关联日志 ↔ 链路追踪 ↔ 指标数据
  • 有多个本地运行的应用,希望使用统一的可观测性方案

不适用场景

  • 生产环境的云部署(建议使用托管的 Grafana Cloud 或 Datadog)
  • 非 Python 应用(该 Python 工具仅支持 FastAPI;但可观测性栈本身语言无关)
  • Docker 不可用的情况

前置条件

  • 已安装 Docker 和 Docker Compose v2
  • Python 3.10+(用于仪器化库)
  • 一个待接入的 FastAPI 应用

安装的服务

服务端口用途
Grafana3000仪表盘展示 — 开发模式下无登录要求
Prometheus9091指标采集(若 MinIO 运行则避开 9090)
Loki3300日志存储(若 Langfuse 运行则避开 3100)
Tempo gRPC4317OTLP 链路追踪接收端
Tempo HTTP4318OTLP HTTP 可选接收端
Alloy UI12345Agent 状态查看界面

操作步骤

步骤 1 — 检查端口冲突

lsof -iTCP -sTCP:LISTEN -n -P 2>/dev/null | grep -E ":(3000|3300|9091|4317|4318|12345)" | awk '{print $9, $1}'

如果上述任一端口被占用,请修改 docker-compose.yml 中对应端口,并同步更新 config/grafana/provisioning/datasources/datasources.yml 中的 url: 字段。常见冲突:Langfuse 占用 3100,MinIO 占用 9090。

步骤 2 — 复制可观测性栈文件

将技能目录中的以下文件复制到工作区的 projects/observability/ 目录中:

  • assets/docker-compose.yml
  • assets/config/(整个目录树)
  • assets/lib/observability.py
  • assets/scripts/register_app.sh
mkdir -p projects/observability
cp -r SKILL_DIR/assets/* projects/observability/
mkdir -p projects/observability/logs
touch projects/observability/logs/.gitkeep
chmod +x projects/observability/scripts/register_app.sh

步骤 3 — 启动可观测性栈

cd projects/observability
docker compose up -d

等待约 15 秒,所有服务启动完成后,执行验证:

curl -s -o /dev/null -w "Grafana: %{http_code}\n"    http://localhost:3000/api/health
curl -s -o /dev/null -w "Prometheus: %{http_code}\n" http://localhost:9091/-/healthy
curl -s -o /dev/null -w "Loki: %{http_code}\n"       http://localhost:3300/ready
curl -s -o /dev/null -w "Tempo: %{http_code}\n"      http://localhost:4318/ready

所有请求应返回 200。若 Loki 或 Tempo 返回 503,请再等待 10 秒后重试(它们的启动速度慢于 Grafana 和 Prometheus)。

步骤 4 — 安装应用所需的 Python 依赖

pip install \
  "prometheus-fastapi-instrumentator>=7.0.0" \
  "opentelemetry-sdk>=1.25.0" \
  "opentelemetry-exporter-otlp-proto-grpc>=1.25.0" \
  "opentelemetry-instrumentation-fastapi>=0.46b0" \
  "python-json-logger>=2.0.7"

步骤 5 — 为 FastAPI 应用添加观测能力

在应用的 app.py(或 main.py)中,在 app = FastAPI(...) 之后添加如下代码:

import sys
sys.path.insert(0, "path/to/projects/observability/lib")
from observability import setup_observability
logger = setup_observability(app, service_name="my-service-name")

完成配置后,应用将具备以下能力:

  • 提供 /metrics 接口以供 Prometheus 采集
  • 将 JSON 格式日志写入 projects/observability/logs/my-service-name/app.log
  • 将链路追踪数据发送至本地的 Tempo(端口 4317)

步骤 6 — 注册应用至 Prometheus

cd projects/observability
./scripts/register_app.sh my-service-name <port>
# 例如:./scripts/register_app.sh image-gen-studio 7860

Prometheus 将在 30 秒内热加载新目标。可通过以下命令验证:

curl -s "http://localhost:9091/api/v1/targets" | python3 -c "
import json, sys
data = json.load(sys.stdin)
for t in data['data']['activeTargets']:
    svc = t['labels'].get('service', '')
    print(svc, '->', t['health'])
"

步骤 7 — 打开 Grafana

访问 http://localhost:3000

系统已预载 FastAPI — App Overview 仪表盘。顶部下拉菜单中选择你的服务名称,即可查看:

  • 请求速率(req/s)
  • 错误率(%)
  • 延迟(p50/p95/p99)
  • 各接口的请求分布
  • HTTP 状态码统计
  • 实时日志面板(Loki)

如需从日志跳转到链路追踪:点击日志详情面板中的 trace_id 链接,将自动打开 Tempo 中对应的完整链路追踪记录(数据源已预先配置)。

步骤 8 — 导入额外仪表盘(可选)

在 Grafana → 仪表盘 → 导入 中添加以下 ID:

  • 16110 — FastAPI 观测(比内置仪表盘更丰富)
  • 13407 — Loki 日志概览
  • 16112 — Tempo 服务图(服务依赖关系图)

常用命令

# 注册新应用后重新加载 Prometheus 配置:
curl -s -X POST http://localhost:9091/-/reload

# 重启单个服务而不丢失数据:
docker compose -f projects/observability/docker-compose.yml restart grafana

# 停止所有服务(保留数据卷):
docker compose -f projects/observability/docker-compose.yml down

# 彻底重置(清除所有存储数据):
docker compose -f projects/observability/docker-compose.yml down -v

# 查看 Alloy 日志传输状态:
open http://localhost:12345

手动链路追踪(可选)

from observability import get_tracer
tracer = get_tracer(__name__)

@app.get("/expensive-endpoint")
async def handler():
    with tracer.start_as_current_span("db-query") as span:
        span.set_attribute("db.table", "users")
        result = await db.query(...)
    return result

日志与链路追踪关联

OTel 仪器化会在每条日志中注入 trace_id。Grafana Loki 已预先配置派生字段,可将 "trace_id":"abc123" 转换为可点击的链接,直接跳转至 Tempo 中对应的链路追踪记录。

在自己的日志调用中手动包含追踪上下文:

from opentelemetry import trace

def trace_ctx() -> dict:
    ctx = trace.get_current_span().get_span_context()
    return {"trace_id": format(ctx.trace_id, "032x")} if ctx.is_valid else {}

logger.info("Processing request", extra=trace_ctx())

注意事项

  • 日志以 JSON 格式写入 projects/observability/logs/<service>/app.log

Alloy 会实时跟踪这些文件并发送到 Loki —— 除了调用 setup_observability() 外,无需额外代码变更。

  • 所有可观测性数据均本地存储 —— 数据不会离开本地机器。
  • 所有追踪和日志的默认数据分类为 data_classification: LOCAL_ONLY
  • Alloy 配置默认丢弃 DEBUG 级别日志。如需保留调试日志,请编辑 config/alloy/config.alloy

文件,移除 stage.drop 块。

N
@nissan

已收录 1 个 Skill

相关推荐