首页/新闻资讯/正文详情

成本监控:给每个 Agent 加“水表”,用 Prometheus + Grafana 盯住 LLM Token 消耗

发布时间:2026/9/26 11:03:30 来源:云帆数科 栏目:资讯中心
成本监控:给每个 Agent 加“水表”,用 Prometheus + Grafana 盯住 LLM Token 消耗
1. 多 Agent 跑起来之后钱到底花在哪了如果你正在自建 Agent 服务大概率遇到过这个场景三个 Agent 各司其职一个负责抓取、一个负责总结、一个负责写日报跑了一周感觉挺顺月底一看账单傻眼。不是付不起而是完全说不清钱花在哪——哪个 Agent 是耗 Token 大户哪次调用重复了Pro 模型是不是被用在了本该 Flash 干的活上这就是 LLM 成本的黑盒问题。传统后端服务有 CPU、内存、QPS 指标但 LLM 调用天然是「按量计费 外部依赖」如果不主动埋点你手里只有一张月底账单没有任何中间过程。没有计量的系统就像没有水表的出租屋房东说多少就是多少。这篇要做的就是给每个 Agent 装一块「水表」每次 LLM 调用自动算成本指标汇总到 PrometheusGrafana 出图超阈值告警。同时用 TaoToken 作为统一的 Key/API 通道让所有 Agent 走同一个入口Token 计数上报是否生效一眼可验。适合已经有一个能跑的 Agent 服务、想把它从「能跑」推进到「可观测」的开发者。2. 前置准备统一通道 指标栈在埋点之前先把两件事定下来否则后面指标口径会乱。第一件是调用通道。多 Agent 各自持有不同的 Key会导致成本归属混乱——你没法判断这笔消耗属于哪个 Agent。我的做法是让所有 Agent 统一走 TaoToken 的 API 通道用同一个 Key 出口Agent 身份通过请求头或业务标签区分。这样 Prometheus 里的agentlabel 才有意义。TaoToken 的 API 地址是https://taotoken.net/api兼容 OpenAI 风格的/v1/chat/completions现有 SDK 基本不用改。第二件是指标栈。Prometheus 负责采集和存储Grafana 负责可视化Agent 服务里用prometheus/client_golang暴露/metrics。三者关系很简单Agent 进程暴露指标 → Prometheus 定时抓取 → Grafana 查询展示。注意Prometheus 是拉模型pull所以你的 Agent 服务必须有一个 HTTP 端口能被 Prometheus 访问到。本地开发用:9090生产环境记得和业务端口分开避免暴露内部指标。先把依赖装上go get github.com/prometheus/client_golang/prometheus go get github.com/prometheus/client_golang/prometheus/promhttp如果你用的是 Python Agent对应换成prometheus_client思路完全一致后面指标定义可以照搬。3. 可复制配置从成本计算到指标暴露3.1 先定义价格表别让成本算错成本监控最容易翻车的地方不是埋点是价格算错。把定价写成代码集中维护// internal/llm/cost.go package llm type ModelPricing struct { InputPrice float64 // 元/百万 Token OutputPrice float64 } var ModelPrices map[string]ModelPricing{ deepseek-v4-pro: {InputPrice: 2.0, OutputPrice: 8.0}, deepseek-v4-flash: {InputPrice: 0.5, OutputPrice: 2.0}, qwen2.5-coder:7b: {InputPrice: 0, OutputPrice: 0}, // 本地模型免费 } func CalculateCost(model string, inputTokens, outputTokens int) float64 { pricing, ok : ModelPrices[model] if !ok { // 未知模型按最贵的估宁可高估不可漏算 pricing ModelPrices[deepseek-v4-pro] } return float64(inputTokens)/1_000_000*pricing.InputPrice float64(outputTokens)/1_000_000*pricing.OutputPrice }一次典型调用1000 输入 500 输出按 Pro 算就是(1000/1M×2)(500/1M×8)¥0.006不到一分钱。单次看着小但 Agent 是高频调用量级一上来差距就出来了。3.2 指标定义四个核心指标就够不要一上来定义十几个指标先覆盖「次数、Token、成本、耗时」四类// internal/middleware/metrics.go package middleware import ( context net/http time github.com/prometheus/client_golang/prometheus github.com/prometheus/client_golang/prometheus/promhttp ) var ( callsTotal prometheus.NewCounterVec( prometheus.CounterOpts{ Name: agent_llm_calls_total, Help: LLM 调用总次数, }, []string{agent, model, status}, ) tokensConsumed prometheus.NewCounterVec( prometheus.CounterOpts{ Name: agent_llm_tokens_total, Help: LLM Token 消耗总量, }, []string{agent, model, type}, // type input / output ) callCost prometheus.NewCounterVec( prometheus.CounterOpts{ Name: agent_llm_cost_yuan_total, Help: LLM 调用总费用元, }, []string{agent, model}, ) callDuration prometheus.NewHistogramVec( prometheus.HistogramOpts{ Name: agent_llm_duration_seconds, Help: LLM 调用耗时分布, Buckets: []float64{0.1, 0.5, 1, 2, 5, 10, 30, 60}, }, []string{agent, model}, ) ) func init() { prometheus.MustRegister(callsTotal, tokensConsumed, callCost, callDuration) }关键点agent这个 label 是整篇的核心。没有它你只能看到「总消耗」看不到「哪个 Agent 消耗」。多 Agent 场景下这个 label 就是水表的户号。3.3 中间件把埋点塞进调用链用装饰器模式包一层业务代码零改动type MetricsMiddleware struct { next agent.Client agent string } func Metrics(next agent.Client, agentName string) agent.Client { return MetricsMiddleware{next: next, agent: agentName} } func (mm *MetricsMiddleware) Chat( ctx context.Context, messages []agent.Message, ) (*agent.Response, error) { start : time.Now() resp, err : mm.next.Chat(ctx, messages) elapsed : time.Since(start).Seconds() status : success if err ! nil { status error } model : unknown if resp ! nil resp.Model ! { model resp.Model } callsTotal.WithLabelValues(mm.agent, model, status).Inc() callDuration.WithLabelValues(mm.agent, model).Observe(elapsed) if err nil resp ! nil { tokensConsumed.WithLabelValues(mm.agent, model, input). Add(float64(resp.Usage.InputTokens)) tokensConsumed.WithLabelValues(mm.agent, model, output). Add(float64(resp.Usage.OutputTokens)) cost : llm.CalculateCost(model, resp.Usage.InputTokens, resp.Usage.OutputTokens) callCost.WithLabelValues(mm.agent, model).Add(cost) } return resp, err }组装的时候每个 Agent 传自己的名字// 抓取 Agent fetcherClient : middleware.Metrics(baseClient, fetcher) // 总结 Agent summarizerClient : middleware.Metrics(baseClient, summarizer) // 日报 Agent reporterClient : middleware.Metrics(baseClient, reporter) middleware.StartMetricsServer(:9090)StartMetricsServer就是标准的promhttp.Handler()挂到/metrics这里不重复贴了。3.4 Prometheus 抓取配置在prometheus.yml里加一个 jobscrape_configs: - job_name: agent-llm scrape_interval: 15s static_configs: - targets: [host.docker.internal:9090] labels: env: dev如果你用 Docker Compose 跑 Prometheushost.docker.internal指向宿主机K8s 里换成 Service 名即可。抓取间隔 15s 是成本和精度的平衡点再密意义不大因为 LLM 调用本身是秒级。4. 验证请求确认 Token 计数真的上报了配置写完不代表生效必须做一次端到端验证。分三步。第一步手动打一次请求触发指标变化curl -s http://localhost:9090/metrics | grep agent_llm_cost_yuan_total如果返回空说明指标没注册或服务没起来。正常应该看到类似agent_llm_cost_yuan_total{agentreporter,modeldeepseek-v4-flash} 0.0006第二步连续调用几次观察计数是否累加。这里有个坑Counter 类型只增不减如果你重启了 Agent 进程计数会归零。这是正常的Prometheus 用rate()处理重启导致的跳变不要手动去「修正」它。第三步在 Prometheus 的 Graph 页面执行查询确认能查到数据sum(rate(agent_llm_cost_yuan_total[5m])) by (agent)这条查询会按 Agent 分组返回每个 Agent 每分钟的成本速率。如果某个 Agent 没出现检查它的中间件是否真的被包进了调用链——我踩过的坑就是只包了主流程异步任务里的调用漏了导致那部分消耗完全没上报。Grafana 面板骨架三个最关键的图{ panels: [ { title: 每小时成本按 Agent, type: timeseries, targets: [ { expr: sum(rate(agent_llm_cost_yuan_total[1h])) by (agent) * 3600, legendFormat: {{agent}} } ] }, { title: Token 消耗趋势按模型, type: timeseries, targets: [ { expr: sum(rate(agent_llm_tokens_total[5m])) by (model, type), legendFormat: {{model}}-{{type}} } ] }, { title: 调用成功率, type: stat, targets: [ { expr: sum(rate(agent_llm_calls_total{status\success\}[5m])) / sum(rate(agent_llm_calls_total[5m])) } ] } ] }告警规则建议先加一条成本突增groups: - name: agent-cost rules: - alert: AgentCostSpike expr: sum(rate(agent_llm_cost_yuan_total[10m])) by (agent) * 3600 5 for: 5m labels: severity: warning annotations: summary: Agent {{ $labels.agent }} 每小时成本超过 5 元这条规则的意思是某个 Agent 的实时成本速率折算成小时超过 5 元持续 5 分钟就告警。阈值按你的业务量调重点是「实时发现异常」而不是等月底。5. 本篇常见错排查指标查不到/metrics返回 404。检查StartMetricsServer是否在main里被调用以及端口是否被占用。另一个常见原因是把promhttp.Handler()挂到了业务路由上被鉴权中间件拦了。成本算出来是 0。大概率是resp.Usage为空。有些兼容接口在流式模式下不返回 usage需要显式请求stream_options: {include_usage: true}或者在流结束后手动累加。走 TaoToken 通道时非流式请求默认带 usage流式需要确认一下。Grafana 里曲线是断的。检查 Prometheus 的scrape_interval和 Grafana 查询的[5m]窗口是否匹配。如果抓取间隔是 15s查询窗口至少给 1m否则rate()会因为样本不足返回空。重启后成本归零累计值不对。这是 Counter 的正常行为。要算「历史总成本」用sum(increase(agent_llm_cost_yuan_total[30d]))不要直接读 Counter 的瞬时值。多个 Agent 的 label 混在一起。检查每个 Agent 的中间件是否传了不同的agentName。如果都传了默认值Prometheus 里就只有一个时间序列分组失去意义。6. 把水表读起来再谈优化指标跑通之后你会发现很多之前靠感觉的判断都变得可验证。比如我实测下来日报 Agent 里真正贵的是总结环节而不是抓取环节因为总结用的是 Pro 模型而抓取用 Flash 就够。把总结拆成「Flash 初筛 Pro 精修」之后同样的任务成本降了大约四成。下一步可以做的给每个 Agent 设独立的成本预算超了自动降级到便宜模型把agent_llm_cost_yuan_total接到告警异常突增时第一时间收到通知再往后用 OpenTelemetry 把每次调用的 trace 串起来定位到具体是哪一步 Prompt 写胖了。如果你还没统一调用通道建议先把所有 Agent 的出口收敛到 TaoToken 的 API 通道Key 管理、用量统计、模型切换都在一个地方埋点口径也统一。接入文档在https://taotoken.net/api对应的文档页API Keys 在控制台的api-keys页面生成。指标跑起来之后模型对话和 Coding Plan 的用量也能对照着看成本这件事就从「月底惊吓」变成了「实时读数」。

相关推荐

28天,我的知识库自己长出来了:用 TaoToken 打通 Notion、Obsidian 与 AGENTS.md 的 Multi-Agent 配置骨架
28天,我的知识库自己长出来了:用 TaoToken 打通 Notion、Obsidian 与 AGENTS.md 的 Multi-Agent 配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 11:03:30

Python 下 MySQLdb 使用:TaoToken 统一 Key 接入与 settings.json 配置骨架
Python 下 MySQLdb 使用:TaoToken 统一 Key 接入与 settings.json 配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 11:03:30

指数分布:从无记忆性到泊松过程的等待时间建模
指数分布:从无记忆性到泊松过程的等待时间建模

1. 指数分布到底在解决什么问题先说个场景。你站在一家奶茶店的柜台前,观察顾客到来的间隔时间——第一位顾客来了,过了3分钟第二位才来,又过了1分钟第三位来了,接着等了7分钟第四位才慢悠悠晃过来。这些“等待时间”看起来毫无规… · 2026/9/26 11:03:17

原生JavaScript手写轮播图组件:原理、实现与避坑指南
原生JavaScript手写轮播图组件:原理、实现与避坑指南

轮播图听起来简单,写起来翻车的概率一点都不低。如果把“轮播图(JavaScript)”拿到实际开发里做一遍,你会发现它远不是把图片横向排开、再定时往左移动 100% 那么简单:自动播放和手动切换的配合、定时器的清理、边界条… · 2026/9/26 11:36:00

ACL 2025中稿10篇背后:通义实验室代码智能与对话智能的工程化落地路径
ACL 2025中稿10篇背后:通义实验室代码智能与对话智能的工程化落地路径

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 11:35:48

物联网设备安全防护链:TLS加密通信与数据安全擦除的工程方案
物联网设备安全防护链:TLS加密通信与数据安全擦除的工程方案

物联网设备的安全威胁模型 物联网设备的安全问题这两年被放大了。大量设备直接暴露在公网,用默认密码、明文HTTP传输、固件可被逆向提取。2025年某智慧水务系统被入侵,攻击者就是通过截获设备的明文MQTT通信篡改了传感器数据,导致告警系统误报… · 2026/9/26 11:35:42

VCC、VDD、VEE、VSS、VBAT供电标识全解析
VCC、VDD、VEE、VSS、VBAT供电标识全解析

1. 这些字母组合不是密码,是电路世界的“门牌号”刚入行那会儿,我蹲在实验室里调一块STM32最小系统板,焊完发现RTC不走时——明明晶振起振了,代码也烧进去了,可万用表一量,VBAT引脚电压只有0.8V。当时盯着原… · 2026/9/26 11:35:42

掌控 Rust 双向链表:从 `LinkedList<T>` 源码到高阶实践的 2000 字深度剖析
掌控 Rust 双向链表:从 `LinkedList<T>` 源码到高阶实践的 2000 字深度剖析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 11:35:36

OpenClaw AI Agent跨平台部署教程:飞书Teams接入与踩坑实录
OpenClaw AI Agent跨平台部署教程:飞书Teams接入与踩坑实录

最近AI圈子里突然流行起一句话:"你领养龙虾了吗?"乍一看以为是宠物博主在整活,点进技术群才发现,大家说的是开源的AI Agent框架OpenClaw。这个名字本身就带梗——Claw和龙虾钳子脱不开关系,社区索性把"… · 2026/9/26 11:35:30

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21

OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40

向下兼容与向上兼容:接口设计中的兼容性策略与工程实践
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践

一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码