十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

DeepSeek API监控实战:Prometheus+Grafana全链路可观测性指南

DeepSeek API监控实战:Prometheus+Grafana全链路可观测性指南 简介面向需要保障 DeepSeek API 稳定性的开发者与运维人员这份监控体系构建指南聚焦如何用 Prometheus 与 Grafana 实现全链路可观测性覆盖 API 调用性能、错误率、延迟及链路追踪等核心关注点。包体为单个 PDF 文档共 29 页约 2.06MB内容结构完整包含从环境搭建、指标定义、Exporter 编写、Prometheus 采集配置到 Grafana 仪表盘可视化、Jaeger 链路追踪、Loki 日志集成以及 Alertmanager 告警与性能优化等实践章节适合希望系统构建监控栈的读者按目录逐步操作。已有 107 人学习下载文档文字、图表、目录显示正常可直接查阅使用。读者可据此完成自定义 Exporter 编写、监控面板搭建与告警规则配置形成从指标采集到异常通知的完整闭环提升线上服务的可观测能力。1. 给 DeepSeekAPI 做监控时我放弃了“抓日志”第一次把 DeepSeekAPI 接进生产环境最怕的不是模型返回错误而是它一直卡在超时边缘看日志能定位某一次调用慢却回答不了“整体成功率是多少”“P95 延迟涨了多少”“今天的 Token 消耗跑到哪了”。于是我把 Prometheus Grafana 拉进了项目。这两个工具组合起来并不神秘Prometheus 定时抓取暴露出来的指标Grafana 负责把指标变成面板和告警。所谓“全链路可观测性”第一步就是让每一次 DeepSeekAPI 调用变成可查询的指标再让指标带上模型、接口、状态这些标签。下文按“指标设计 → 埋点 → 抓取 → 展示 → 告警 → 链路关联”的顺序展开中间包含可复制的 Python 埋点代码和 Prometheus/Grafana 配置。2. DeepSeekAPI 指标埋点用 Prometheus 客户端先定义可观测边界2.1 一张最小可用的 DeepSeekAPI 监控指标清单不管用不用 Prometheus监控 DeepSeekAPI 前都要先想清楚要回答什么问题。我的清单是四组指标请求总量、延迟分布、错误码分布、Token 消耗量。它们分别对应“有没有人调”“调得慢不慢”“挂没挂”“钱烧了多少”。下面这份指标约定可以直接抄进设计文档metric name 和 label 都按 Prometheus 官方规范对齐Counter 用_total结尾Histogram 单位用_seconds。指标名类型标签说明deepseek_api_requests_totalCountermodel, endpoint, status请求总数status 为 HTTP 状态码deepseek_api_request_duration_secondsHistogrammodel, endpoint从发起调用到拿到完整响应的时间deepseek_api_tokens_totalCountermodel, typetype 区分 prompt_tokens / completion_tokensdeepseek_api_inflight_requestsGaugemodel当前未返回的请求数用于观察并发占满的情况注意单位统一成秒如果埋点代码用毫秒后续 PromQL 看到的会是 0.001 级别图表可读性很差。2.2 为什么延迟指标用 Histogram 而不是 Summary这是监控 DeepSeekAPI 最容易抄错的地方。Summary 在客户端计算分位数Prometheus 没法把多个实例的分位数合并Histogram 记录的是累计桶计数查询时用histogram_quantile算 p95多副本部署下只有 Histogram 能回答“所有实例整体 p95 延迟”这种问题。顺便区分另外两种指标类型Counter 只增不减适合累计错误数和 Token 数Gauge 可增可减适合记录“当前正在处理的 DeepSeekAPI 请求数”比如判断负载均衡后端的连接是不是全部打满。2.3 在调用 SDK 的地方埋点而不是 HTTP 中间件一个常见的错误是把计时器放在 FastAPI 中间件里测出来的只是网关自己的返回时间完全没有包含 DeepSeekAPI 上游的耗时。更准确的位置是调用 OpenAI SDK 这一层。下面这段 Python 代码可以直接放进项目import os import time from openai import OpenAI from prometheus_client import Counter, Histogram, Gauge client OpenAI( base_urlhttps://api.deepseek.com, api_keyos.getenv(DEEPSEEK_API_KEY), ) REQUESTS Counter( deepseek_api_requests_total, DeepSeek API 请求总数, [model, endpoint, status], ) LATENCY Histogram( deepseek_api_request_duration_seconds, DeepSeek API 请求延迟秒, [model, endpoint], buckets(0.25, 0.5, 1, 2.5, 5, 10, 30), ) TOKENS Counter( deepseek_api_tokens_total, DeepSeek API Token 用量, [model, type], ) INFLIGHT Gauge( deepseek_api_inflight_requests, 当前正在处理的 DeepSeek API 请求数, [model], ) def call_deepseek(model: str, messages: list): labels {model: model, endpoint: /chat/completions} INFLIGHT.labels(model).inc() start time.perf_counter() try: resp client.chat.completions.create(modelmodel, messagesmessages) REQUESTS.labels(status200, **labels).inc() TOKENS.labels(typeprompt_tokens, **labels).inc(resp.usage.prompt_tokens or 0) TOKENS.labels(typecompletion_tokens, **labels).inc(resp.usage.completion_tokens or 0) return resp except Exception as e: REQUESTS.labels(statusgetattr(e, status_code, 500), **labels).inc() raise finally: LATENCY.labels(**labels).observe(time.perf_counter() - start) INFLIGHT.labels(model).dec()代码逻辑说明INFLIGHT.inc/dec放在 try-finally 外层保证异常时并发数也能归位resp.usage是 DeepSeekAPI 返回的 Token 统计用or 0兜底避免某个字段为 None 时埋点抛异常status取不到错误码时按 500 记录埋点代码不能反过来影响业务。如果服务用 gunicorn 多 worker 跑Prometheus client 需要额外处理多进程下每个 worker 有独立内存同一条指标会被互相覆盖。常见做法是设置环境变量PROMETHEUS_MULTIPROC_DIR让所有 worker 共享同一个目录。注意不要放/tmp系统清理会丢指标。最后暴露指标端口常用做法是独立线程跑一个 HTTP 服务from prometheus_client import start_http_server start_http_server(8001)也可以把make_wsgi_app挂到 FastAPI 的/metrics路由但调试阶段start_http_server更直接。默认监听 0.0.0.0生产环境要在安全组限制来源 IP避免内部指标被其他服务随意拉取。3. Prometheus 抓取与存储让 DeepSeekAPI 指标 15 秒落一次时序库3.1 最小可用的 prometheus.yml 与容器启动命令metrics 端点有了接下来让 Prometheus 固定频率拉取。先准备一份配置global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: deepseek-api metrics_path: /metrics static_configs: - targets: [host.docker.internal:8001] labels: service: deepseek-api env: prod参数说明scrape_interval是抓取间隔15 秒对 API 网关级别的指标够用evaluation_interval是告警规则评估间隔默认和抓取间隔一致。targets 里如果 Prometheus 跑在 Docker 容器内访问宿主机服务要用host.docker.internal纯 Linux 环境没有这个域名直接填宿主机局域网 IP。启动命令docker run -d --name prometheus \ -p 9090:9090 \ -v $PWD/prometheus.yml:/etc/prometheus/prometheus.yml:ro \ -v $PWD/prometheus_data:/prometheus \ prom/prometheus:latest注意容器内 Prometheus 进程默认用户是 nobody经常遇到挂载目录权限不足导致启动失败报mkdir /prometheus: permission denied。把数据目录权限放开chmod 777 prometheus_data或者换到有权限的路径。3.2 /metrics 拉取失败的三个高频原因先看 Prometheus 的 Targets 页面打开http://localhost:9090/targets如果状态是 DOWN说明网络或端口有问题。第二步在容器内直接 curl 目标地址docker exec prometheus wget -qO- http://host.docker.internal:8001/metrics | head如果返回的指标列表里没有deepseek_api_前缀说明 Python 端的新指标没有注册检查变量是否在服务启动时就完成 import。第三步确认 Python 监听地址。如果代码里监听的是localhost:8001容器内的 Prometheus 会连不上要改成0.0.0.0:8001。还有一个隐蔽问题当用 uvicorn 多 worker 启动时每个 worker 进程重复注册同一组 metricPrometheus 抓到的值会互相覆盖表现为/metrics明明有数据查询却断断续续。解决办法就是前面说的PROMETHEUS_MULTIPROC_DIR。3.3 用 PromQL 验证 DeepSeekAPI 指标是否进库在 Prometheus 的 Graph 页面输入rate(deepseek_api_requests_total[5m])如果图表有曲线证明数据进库。刚启动时会有约 15 秒空窗属于正常。要按模型维度看调用量分布可以执行topk(10, sum(rate(deepseek_api_requests_total[5m])) by (model))rate[5m]计算每秒增量sum by (model)把 endpoint 和 status 汇总到模型维度适合回答“哪个模型调得最多”。这一步建议在 Prometheus 界面先验证通过再回 Grafana尽量减少变量因素。3.4 先理解 Prometheus 抓取机制再看 OTel Collector 接入很多人问“Prometheus 是如何从 OTel Collector 收取数据的”这里先立一个结论Prometheus 默认只会主动 scrape不会反向订阅。Collector 要接进来有两种方式第一种是让 Collector 暴露一个/metrics端口Prometheus 把它当成普通 exporter 抓取第二种是 Collector 使用 Remote Write 协议推给 Prometheus后者需要启动参数加--enable-featureremote-write-receiver。第 5 章会给出具体配置先记住默认路径是抓取。4. Grafana 面板与告警把 DeepSeekAPI 指标变成能盯的图4.1 配置 Prometheus 数据源容器环境别写 localhostGrafana 如果也用 Docker 跑和 Prometheus 之间不是 localhost 关系。用 docker-compose 把两个服务放进同一网络数据源 URL 填http://prometheus:9090如果仅用docker run且没加自定义网络可以填http://host.docker.internal:9090。填完点 Save Test出现 “Datasource is working” 再继续。如果你打开别人导出的面板报grafana failed to upgrade legacy queries datasource im7_otuvz was not found多半是数据源 UID 对不上。到 Dashboard Settings 的 JSON Model 里把旧的uid替换成当前数据源的真实 UID再重新加载面板即可。4.2 三个 PromQL 查询覆盖 DeepSeekAPI 核心监控面板Grafana 面板的本质是 PromQL。新建一个空面板把下面三条查询依次加进去。请求成功率按 endpoint 展开sum(rate(deepseek_api_requests_total{status!~5..}[5m])) by (endpoint) / sum(rate(deepseek_api_requests_total[5m])) by (endpoint)P95 延迟histogram_quantile(0.95, sum(rate(deepseek_api_request_duration_seconds_bucket[5m])) by (le, endpoint) )错误数分布sum by (status) (rate(deepseek_api_requests_total{status~5..}[5m]))前两个查询返回的单位分别是“每秒请求数”和“秒”面板的 Y 轴标题最好写清楚避免运维同学误读。_bucket是 Histogram 自动生成的系列buckets 范围决定 p95 精度如果把最大 bucket 设置在 10s超过 10s 的请求会全落进Infp95 永远算不出更精确的值。4.3 用模板变量按模型维度筛选当同一个网关代理多个模型时Dashboard 上最好留一个模型下拉框。在 Dashboard Settings → Variables 里新增变量model查询语句填label_values(deepseek_api_requests_total, model)Prometheus 会从抓到的数据里把model标签值取出来。之后在面板 PromQL 里加上{model$model}切换模型时整个面板都会联动过滤。想拷贝整个面板到其他环境时用 Dashboard Settings 的 JSON Model 导出再在目标实例 Import不要手动重建。4.4 Prometheus 告警规则与 Alertmanager 的关系Prometheus 自己就能计算告警Alertmanager 负责接收和分发。规则文件 alarm.yml 示例groups: - name: deepseek-api rules: - alert: DeepSeekAPIHighErrorRate expr: | sum(rate(deepseek_api_requests_total{status~5..}[5m])) / sum(rate(deepseek_api_requests_total[5m])) 0.05 for: 2m labels: severity: critical annotations: summary: DeepSeek API 5xx 错误率超过 5% description: 当前错误率 {{ $value | humanizePercentage }}持续 2 分钟for: 2m表示条件持续 2 分钟才触发避免偶发抖动造成告警风暴。需要把 alarm.yml 挂载进 Prometheus 容器并在 prometheus.yml 的rule_files里引用。告警最终要接到钉钉、企业微信或邮件否则只是在自己电脑上响。这部分属于典型的“Prometheus 告警规则配置”可以在接入 Alertmanager 时再细化。5. 全链路可观测性落地Prometheus 与 OTel Collector 的指标闭环5.1 Prometheus 是如何从 OTel Collector 收取数据的“全链路可观测性”不只是把 DeepSeekAPI 指标画出来还要能在一次慢请求里关联日志和调用链。Prometheus 存储指标不负责 trace 和 log常见做法是保留 Prometheus 作为指标端同时用 OpenTelemetry 把 trace 送到 Grafana Tempo日志送到 Loki三种数据用trace_id关联。回到 Prometheus 和 OTel Collector 的衔接最贴合现有架构的是把 Collector 当作中间 exporter让 Prometheus 来抓receivers: otlp: protocols: http: endpoint: 0.0.0.0:4318 exporters: prometheus: endpoint: 0.0.0.0:9091 namespace: deepseek_api service: pipelines: metrics: receivers: [otlp] exporters: [prometheus]这里prometheusexporter 会在 9091 端口暴露一个类似/metrics的抓取端点。Prometheus 侧新增一个 scrape_configtargets 指向collector:9091就完成了“应用 → OTLP → Collector → Prometheus”的链路。如果不想保留抓取关系也可以让 Collector 用prometheusremotewriteexporter 直接推给 Prometheus 的 remote write 接收器后者需要 Prometheus 启动参数加上--enable-featureremote-write-receiver。5.2 上线前用 promtool 校验告警规则重载不重启写好的告警规则不要等 Prometheus 启动失败才发现 YAML 格式有问题。用官方自带的 promtool 校验比手动翻日志快得多promtool check rules alarms.yml如果文件语法正确输出SUCCESS出现解析错误时它会指出具体行号。之后使用 HTTP 接口热重载配置curl -X POST http://localhost:9090/-/reload重载前顺手执行promtool check config prometheus.yml把主配置和告警规则一起检查能减少“规则没生效”的排障时间。要验证规则是否真会触发可以临时把阈值改低到 0.001再用一个故意返回 500 的端点观察 Alertmanager 是否收到消息。测试完记得把阈值改回来并在 Alertmanager 中清理静默避免测试告警污染值班记录。本文还有配套的精品资源点击获取
返回列表