# Prometheus 指标记录问题修复总结 ## 问题描述 Prometheus 中没有正常记录应用的访问数据。虽然 `/metrics` 端点可以访问,并且定义了所有指标类型,但这些指标都没有任何数据值。 ## 根本原因 1. **HTTP 请求指标未记录**:`api/routes.py` 中的路由处理函数没有使用 `@track_request` 装饰器来记录 HTTP 请求指标 2. **算法执行指标未记录**:`algorithms/base.py` 中的 `execute()` 方法没有调用 metrics 模块来记录算法执行指标 ## 解决方案 ### 1. 添加 HTTP 请求指标跟踪中间件 **文件**:`src/functional_scaffold/main.py` **修改内容**: - 导入 metrics 相关的对象:`request_counter`, `request_latency`, `in_progress_requests` - 添加 `track_metrics` 中间件,自动跟踪所有 HTTP 请求 **优点**: - 自动化:不需要在每个路由上手动添加装饰器 - 统一:所有端点的指标记录逻辑一致 - 易维护:新增端点自动获得指标跟踪能力 **实现代码**: ```python @app.middleware("http") async def track_metrics(request: Request, call_next): """记录所有HTTP请求的指标""" if not settings.metrics_enabled: return await call_next(request) # 跳过 /metrics 端点本身,避免循环记录 if request.url.path == "/metrics": return await call_next(request) in_progress_requests.inc() start_time = time.time() status = "success" try: response = await call_next(request) if response.status_code >= 400: status = "error" return response except Exception as e: status = "error" raise e finally: elapsed = time.time() - start_time request_counter.labels( method=request.method, endpoint=request.url.path, status=status ).inc() request_latency.labels( method=request.method, endpoint=request.url.path ).observe(elapsed) in_progress_requests.dec() ``` ### 2. 添加算法执行指标记录 **文件**:`src/functional_scaffold/algorithms/base.py` **修改内容**: - 在 `execute()` 方法中导入 `algorithm_counter` 和 `algorithm_latency` - 在 `finally` 块中记录算法执行指标 **实现代码**: ```python def execute(self, *args, **kwargs) -> Dict[str, Any]: from ..core.metrics import algorithm_counter, algorithm_latency start_time = time.time() status = "success" try: # ... 算法执行逻辑 ... except Exception as e: status = "error" # ... 错误处理 ... finally: elapsed_time = time.time() - start_time algorithm_counter.labels(algorithm=self.name, status=status).inc() algorithm_latency.labels(algorithm=self.name).observe(elapsed_time) ``` ## 验证结果 ### 1. 应用 /metrics 端点 修复后,`/metrics` 端点正常返回指标数据: ``` # HTTP 请求指标 http_requests_total{endpoint="/healthz",method="GET",status="success"} 3.0 http_requests_total{endpoint="/invoke",method="POST",status="success"} 2.0 http_requests_total{endpoint="/readyz",method="GET",status="success"} 1.0 # HTTP 请求延迟 http_request_duration_seconds_sum{endpoint="/invoke",method="POST"} 0.0065615177154541016 http_request_duration_seconds_count{endpoint="/invoke",method="POST"} 2.0 # 算法执行指标 algorithm_executions_total{algorithm="PrimeChecker",status="success"} 2.0 algorithm_execution_duration_seconds_sum{algorithm="PrimeChecker"} 0.00023603439331054688 algorithm_execution_duration_seconds_count{algorithm="PrimeChecker"} 2.0 # 当前进行中的请求 http_requests_in_progress 0.0 ``` ### 2. Prometheus 查询 Prometheus 成功抓取并存储了指标数据: ```bash # 查询 HTTP 请求总数 curl 'http://localhost:9090/api/v1/query?query=http_requests_total' # 查询算法执行总数 curl 'http://localhost:9090/api/v1/query?query=algorithm_executions_total' ``` ## 可用指标 修复后,以下指标可以在 Prometheus 和 Grafana 中使用: ### HTTP 请求指标 1. **http_requests_total** (Counter) - 标签:`method`, `endpoint`, `status` - 描述:HTTP 请求总数 - 用途:统计各端点的请求量、成功率 2. **http_request_duration_seconds** (Histogram) - 标签:`method`, `endpoint` - 描述:HTTP 请求延迟分布 - 用途:分析请求响应时间、P50/P95/P99 延迟 3. **http_requests_in_progress** (Gauge) - 描述:当前正在处理的请求数 - 用途:监控并发请求数、负载情况 ### 算法执行指标 1. **algorithm_executions_total** (Counter) - 标签:`algorithm`, `status` - 描述:算法执行总数 - 用途:统计算法调用量、成功率 2. **algorithm_execution_duration_seconds** (Histogram) - 标签:`algorithm` - 描述:算法执行延迟分布 - 用途:分析算法性能、优化瓶颈 ## 使用示例 ### Prometheus 查询示例 ```promql # 每秒请求数 (QPS) rate(http_requests_total[5m]) # 请求成功率 sum(rate(http_requests_total{status="success"}[5m])) / sum(rate(http_requests_total[5m])) # P95 延迟 histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) # 算法执行失败率 sum(rate(algorithm_executions_total{status="error"}[5m])) / sum(rate(algorithm_executions_total[5m])) ``` ### 生成测试流量 使用提供的脚本生成测试流量: ```bash # 启动流量生成器 ./scripts/generate_traffic.sh # 在另一个终端查看实时指标 watch -n 1 'curl -s http://localhost:8111/metrics | grep http_requests_total' ``` ## Grafana 仪表板 访问 Grafana 查看可视化指标: 1. 打开浏览器访问:http://localhost:3000 2. 登录(默认用户名/密码:admin/admin) 3. 导入仪表板:`monitoring/grafana/dashboard.json` 仪表板包含以下面板: - 请求速率(QPS) - 请求延迟(P50/P95/P99) - 错误率 - 算法执行统计 - 并发请求数 ## 注意事项 1. **中间件顺序**:指标跟踪中间件应该在日志中间件之后注册,确保所有请求都被记录 2. **/metrics 端点**:中间件会跳过 `/metrics` 端点本身,避免循环记录 3. **错误状态**:HTTP 状态码 >= 400 会被标记为 `status="error"` 4. **性能影响**:指标记录的性能开销极小(微秒级),不会影响应用性能 ## 后续优化建议 1. **添加更多维度**:可以添加 `user_id`、`region` 等标签进行更细粒度的分析 2. **自定义指标**:根据业务需求添加自定义指标(如缓存命中率、外部 API 调用次数等) 3. **告警规则**:配置 Prometheus 告警规则,在指标异常时发送通知 4. **长期存储**:考虑使用 Thanos 或 Cortex 进行长期指标存储和查询 ## 相关文件 - `src/functional_scaffold/main.py` - HTTP 请求指标跟踪中间件 - `src/functional_scaffold/algorithms/base.py` - 算法执行指标记录 - `src/functional_scaffold/core/metrics.py` - 指标定义 - `monitoring/prometheus.yml` - Prometheus 配置 - `monitoring/grafana/dashboard.json` - Grafana 仪表板 - `scripts/generate_traffic.sh` - 流量生成脚本