Vitest Testing
提供 Vitest 单元测试与集成测试的模式与最佳实践,涵盖断言、异步测试与模拟方法。
为 FastAPI 应用搭建本地日志、指标、链路追踪一体化监控系统。
openclaw skills install @nissan/observability-lgtm命令、参数、文件名以原文为准
最后使用时间: 2026-03-24
内存引用次数: 7
状态: 激活中
在 macOS(Apple Silicon)或 Linux 上为 FastAPI 应用快速搭建完整的本地可观测性栈(Loki + Grafana + Tempo + Prometheus + Alloy)。一条命令启动服务,一个导入即可为任意应用添加观测能力。日志 → Loki,指标 → Prometheus,链路追踪 → Tempo,全部统一在 Grafana 中展示。
| 服务 | 端口 | 用途 |
|---|---|---|
| Grafana | 3000 | 仪表盘展示 — 开发模式下无登录要求 |
| Prometheus | 9091 | 指标采集(若 MinIO 运行则避开 9090) |
| Loki | 3300 | 日志存储(若 Langfuse 运行则避开 3100) |
| Tempo gRPC | 4317 | OTLP 链路追踪接收端 |
| Tempo HTTP | 4318 | OTLP HTTP 可选接收端 |
| Alloy UI | 12345 | Agent 状态查看界面 |
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。
将技能目录中的以下文件复制到工作区的 projects/observability/ 目录中:
assets/docker-compose.ymlassets/config/(整个目录树)assets/lib/observability.pyassets/scripts/register_app.shmkdir -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.shcd 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)。
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"在应用的 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 采集projects/observability/logs/my-service-name/app.logcd projects/observability
./scripts/register_app.sh my-service-name <port>
# 例如:./scripts/register_app.sh image-gen-studio 7860Prometheus 将在 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'])
"访问 http://localhost:3000
系统已预载 FastAPI — App Overview 仪表盘。顶部下拉菜单中选择你的服务名称,即可查看:
如需从日志跳转到链路追踪:点击日志详情面板中的 trace_id 链接,将自动打开 Tempo 中对应的完整链路追踪记录(数据源已预先配置)。
在 Grafana → 仪表盘 → 导入 中添加以下 ID:
# 注册新应用后重新加载 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:12345from 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 resultOTel 仪器化会在每条日志中注入 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())projects/observability/logs/<service>/app.log。 Alloy 会实时跟踪这些文件并发送到 Loki —— 除了调用 setup_observability() 外,无需额外代码变更。
data_classification: LOCAL_ONLY。config/alloy/config.alloy 文件,移除 stage.drop 块。
已收录 1 个 Skill