下载工作台
Flask Web 开发

Prometheus、链路追踪与 APM

试读上半部分 · 解锁后可读全文

第 18 章 · Prometheus、链路追踪与 APM

本章目标:使用 prometheus_flask_exporterapi-demo 暴露 /metrics(请求计数、延迟直方图);理解 Grafana 仪表盘与告警规则(虚构示例);入门 OpenTelemetry,让 trace_id 贯穿 Flask → SQLAlchemy → Redis;将结构化日志metrics 通过 request_id 关联(衔接 ch09);了解 APM(Datadog / New Relic 类工具)概念;建立生产可观测性 checklist

学时建议:5~6 小时(含 2 小时 Prometheus + Grafana 跟练)

前置:本模块 ch09 请求 ID 与结构化日志;ch10 Redis;ch11 Gunicorn;ch17 ORM 慢查询。监控概念可对照 ops-deployxiaozi-cloud 告警章节。


18.1 可观测性三大支柱

         Metrics              Logs               Traces
    Prometheus/Grafana    JSON → ELK/Loki    OpenTelemetry → Jaeger
    「系统是否异常?」     「发生了什么?」      「慢在哪里?」
支柱api-demo 示例
Metrics/metrics 暴露 flask_http_request_duration_seconds
Logsrequest_id=abc123 关联访问与审计日志
Tracestrace_id 串联 ORM 查询与 Redis 调用
统一使用虚构 api-demoapi.example.com严禁写入真实监控地址、API Key 或租户 ID。

RED 方法(请求型服务):Rate 每秒请求、Errors 错误率、Duration 延迟分布。


18.2 prometheus_flask_exporter 集成

pip install prometheus-flask-exporter

api_demo/extensions.py

from prometheus_flask_exporter import PrometheusMetrics

metrics = PrometheusMetrics.for_app_factory(group_by="endpoint")

def init_extensions(app):
    metrics.init_app(app)
    # db, cache, login_manager ...

默认暴露 GET /metrics,自动采集 flask_http_request_totalflask_http_request_duration_seconds 等。

自定义业务 Counter

from prometheus_client import Counter

product_created_total = Counter(
    "api_demo_product_created_total", "商品创建次数", ["source"]
)
# 视图中:product_created_total.labels(source="api").inc()

保护 /metrics(生产必做):

# Nginx 限制内网 IP,或 Bearer Token 校验 METRICS_TOKEN

18.3 本地 Prometheus + Grafana 跟练

api-demo/deploy/prometheus.yml

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: api-demo
    metrics_path: /metrics
    static_configs:
      - targets: [host.docker.internal:5000]
        labels: {env: staging, service: api-demo}

api-demo/deploy/docker-compose.monitoring.yml

services:
  prometheus:
    image: prom/prometheus:v2.51.0
    volumes: [./prometheus.yml:/etc/prometheus/prometheus.yml:ro]
    ports: ["9090:9090"]
  grafana:
    image: grafana/grafana:10.4.0
    ports: ["3000:3000"]
    environment:
      GF_SECURITY_ADMIN_PASSWORD: changeme-local-only

常用 PromQL

Panel表达式
QPSrate(flask_http_request_total[1m])
P95histogram_quantile(0.95, rate(flask_http_request_duration_seconds_bucket[5m]))
5xx 比sum(rate(...{status=~"5.."}[5m])) / sum(rate(...[5m]))

18.4 Grafana 告警规则(虚构示例)

api-demo/deploy/alerts/api-demo.yml

groups:
  - name: api-demo-staging
    rules:
      - alert: ApiDemoHighErrorRate
        expr: |
          sum(rate(flask_http_request_total{status=~"5.."}[5m]))
          / sum(rate(flask_http_request_total[5m])) > 0.05
        for: 5m
        labels: {severity: critical, service: api-demo}
        annotations:
          summary: "api-demo 5xx 错误率超过 5%"

      - alert: ApiDemoHighLatencyP99
        expr: |
          histogram_quantile(0.99,
            sum(rate(flask_http_request_duration_seconds_bucket[5m])) by (le)
          ) > 2
        for: 10m
        labels: {severity: warning}
        annotations:
          summary: "P99 延迟超过 2 秒"

      - alert: ApiDemoMetricsTargetDown
        expr: up{job="api-demo"} == 0
        for: 2m
        labels: {severity: critical}
字段说明
exprPromQL 触发条件
for持续时长,防抖动
annotationsRunbook 链接(用占位 URL)

通知渠道用占位 Webhook,不写真实密钥。


18.5 OpenTelemetry 简介

OpenTelemetry(OTel) 统一 Traces/Metrics/Logs 的 CNCF 标准,展示单次请求完整路径:

trace_id: 7a3f9c2e...
├─ span: GET /api/v1/products     [120ms]
│   ├─ span: sqlalchemy SELECT    [85ms]
│   └─ span: redis GET cache:key  [3ms]
pip install opentelemetry-api opentelemetry-sdk \
  opentelemetry-instrumentation-flask \
  opentelemetry-instrumentation-sqlalchemy \
  opentelemetry-instrumentation-redis \
  opentelemetry-exporter-otlp

api_demo/telemetry.py

import os
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
from opentelemetry.instrumentation.redis import RedisInstrumentor

def setup_telemetry(app, db_engine=None):

以下内容需解锁后阅读

试读已结束。解锁本章 ¥5.00,或开通年度会员畅读全部教程。
年度会员 ¥199.00/年; 小紫 AI 工作台有效会员 ¥99.00/年

正文仅在服务端鉴权后下发,未付费无法获取下半部分内容。