Agent 账单装个仪表盘------LiteLLM + Grafana 成本看板
前三篇把 Token 从膨胀版一路修到全优化版,省了 50-80%。但省了多少具体数字?哪个 Agent 最烧钱?费用什么时候突然涨了?靠翻 LiteLLM 日志是查不出来的。这篇搭一个看得见的成本面板。
一句话结论
成本治理的最后一步是可见性 。用 LiteLLM 自带的 /spend/logs 做数据源,Prometheus + Grafana 做展示,再加一条 Slack/飞书告警规则。整个看板 30 分钟能搭完,代码不超过 50 行。之后每天扫一眼就知道钱花在哪。
五个关键指标
搭看板之前,先明确该盯什么。不是所有指标都值得放面板上。
| # | 指标 | 为什么重要 | 告警阈值 |
|---|---|---|---|
| 1 | 日总费用 | 最直观,老板唯一会问的 | > ¥50 |
| 2 | 按模型费用分布 | 找出哪个模型是烧钱大户 | 单一模型 > 60% |
| 3 | 按 API Key / 用户费用 | 定位是哪个 Agent 或谁在烧 | 单 Key 突增 3× |
| 4 | 请求失败率 | 失败 = 重试 = 白烧 Token | > 5% |
| 5 | 单次请求平均 Token | 异常长请求通常是 prompt 或循环 bug | > 均值 2× |
前三个盯钱 ,后两个盯异常。五个都绿,账单就不会出意外。
数据源:LiteLLM Spend Log
LiteLLM 自带 spend log,记录了每一次调用的模型、Token、费用。不需要额外埋点。
perl
curl -s "http://localhost:4000/spend/logs?start_date=$(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%S)" \
-H "Authorization: Bearer sk-litellm-master-key-change-me" | jq '.[0]'
返回结构:
json
{
"request_id": "gpt-4o-2024-05-13-abc123",
"model": "gpt-4o",
"api_key": "sk-agent-data-analyst",
"prompt_tokens": 3500,
"completion_tokens": 800,
"spend": 0.023,
"user": "data-team",
"startTime": "2026-07-23T08:15:00Z"
}
Prometheus 不认识 JSON API,需要加一层 exporter。最简方案:一个 Python 脚本把 spend log 转成 Prometheus metrics,暴露在 /metrics 端点。
搭看板
Step 1:写一个最小 Prometheus Exporter
最小可用版本只做三件事:拉 LiteLLM Spend Log、按模型累加费用、把请求/Token 计数暴露出去。这样后续 Grafana 面板和告警查询就能直接用 Prometheus 的 rate() 函数了。
ini
# spend_exporter.py --- 把 LiteLLM spend log 暴露为 Prometheus metrics
import time
from datetime import datetime, timedelta
import requests
from prometheus_client import Counter, start_http_server
API = "http://localhost:4000/spend/logs"
HEADERS = {"Authorization": "Bearer sk-litellm-master-key-change-me"}
# 累积型指标:用 rate() 做趋势分析
cost_total = Counter("agent_cost_rmb_total", "Cumulative API spend in RMB", ["model"])
request_total = Counter("agent_request_total", "Total requests", ["model"])
prompt_tokens_total = Counter("agent_prompt_tokens_total", "Total prompt tokens", ["model"])
completion_tokens_total = Counter("agent_completion_tokens_total", "Total completion tokens", ["model"])
# 只抓"自上次拉取以来新增"的日志,避免重复计数
last_fetch = datetime.utcnow() - timedelta(hours=24)
def collect():
global last_fetch
start_date = last_fetch.strftime("%Y-%m-%dT%H:%M:%SZ")
resp = requests.get(
API,
headers=HEADERS,
params={"start_date": start_date},
timeout=10,
)
resp.raise_for_status()
logs = resp.json() if isinstance(resp.json(), list) else resp.json().get("data", [])
for r in logs:
model = r.get("model", "unknown")
spend = float(r.get("spend", 0) or 0)
prompt_tokens = int(r.get("prompt_tokens", 0) or 0)
completion_tokens = int(r.get("completion_tokens", 0) or 0)
cost_total.labels(model=model).inc(spend)
request_total.labels(model=model).inc()
prompt_tokens_total.labels(model=model).inc(prompt_tokens)
completion_tokens_total.labels(model=model).inc(completion_tokens)
last_fetch = datetime.utcnow()
if __name__ == "__main__":
start_http_server(9090)
while True:
collect()
time.sleep(60)
跑起来:
bash
pip install prometheus-client requests
python spend_exporter.py &
curl localhost:9090/metrics | grep agent_
输出会类似:
ini
agent_cost_rmb_total{model="gpt-4o"} 0.82
agent_cost_rmb_total{model="gpt-4o-mini"} 0.15
agent_cost_rmb_total{model="claude-sonnet-4-20250514"} 1.23
agent_request_total{model="gpt-4o"} 13
agent_prompt_tokens_total{model="gpt-4o"} 48200
这里的关键点是:用 Counter 记录"累计值",再用
rate()计算趋势。这样再做 Grafana 面板时,语义就非常稳定。
Step 2:Prometheus 配置
yaml
# prometheus.yml
scrape_configs:
- job_name: "agent-cost"
scrape_interval: 60s
static_configs:
- targets: ["localhost:9090"]
Step 3:Grafana 面板
导入 Prometheus 数据源后,建一个 Dashboard,四个面板:
面板 1:成本趋势(折线图)
scss
sum(rate(agent_cost_rmb_total[5m])) * 60
这条查询的含义是"每分钟成本速率"。如果你希望看单位小时的费用,可把它改成 sum(rate(agent_cost_rmb_total[1h])) * 3600。
面板 2:按模型成本占比(饼图)
scss
sum by (model) (rate(agent_cost_rmb_total[5m]))
面板 3:请求失败率(单值)
如果你有失败日志或单独的失败计数器,可以这样写:
scss
sum(rate(agent_request_failures_total[5m])) / sum(rate(agent_request_total[5m])) * 100
如果你只能拿到 LiteLLM spend/logs,那失败率通常要另行接入失败日志或业务侧状态字段,不建议直接拿 Token 数做分母。
面板 4:Top 5 模型成本(表格)
scss
topk(5, sum by (model) (rate(agent_cost_rmb_total[5m])))
告警规则
看板是给人看的,告警是替人盯的。重点盯两个场景:
1. 单日费用超标
yaml
# prometheus alert rules
groups:
- name: agent_cost
rules:
- alert: DailyBudgetExceeded
expr: sum(rate(agent_cost_rmb_total[5m])) * 60 > 2
for: 5m
labels:
severity: warning
annotations:
summary: "Agent 成本速率异常"
description: "当前费用增长速率为 ¥{{ $value }} / 分钟,请检查是否有异常调用"
这里的"超标"不再看某个瞬时 gauge,而是看"增长速率"。这样更符合成本监控的真实业务场景:你需要盯的是"是不是在持续烧钱",而不是单一时刻的当前总量。
2. 单次请求 Token 突增
yaml
- alert: TokenSpike
expr: sum by (model) (rate(agent_prompt_tokens_total[5m])) > 20000
for: 1m
labels:
severity: warning
annotations:
summary: "单个模型 Prompt Token 速率异常"
description: "模型 {{ $labels.model }} 当前速率为 {{ $value }} tokens/秒"
连飞书/Slack 通知
Prometheus Alertmanager 自带飞书 webhook 支持:
yaml
# alertmanager.yml
receivers:
- name: "feishu"
webhook_configs:
- url: "https://open.feishu.cn/open-apis/bot/v2/hook/your-hook-id"
send_resolved: true
搞定。费用超标时飞书机器人直接弹消息。
没有 Prometheus 的极简方案
如果你不想搭 Prometheus + Grafana 全家桶,一个 crontab 也够用:
ini
# crontab -e 每天 18:00 跑
0 18 * * * curl -s "http://localhost:4000/spend/logs?start_date=$(date -u -d 'today 00:00' +%Y-%m-%dT%H:%M:%S)" \
-H "Authorization: Bearer sk-litellm-master-key-change-me" | \
python3 -c "
import json,sys
logs = json.load(sys.stdin) if isinstance(json.load(sys.stdin), list) else json.load(sys.stdin).get('data',[])
total = sum(r.get('spend',0) for r in logs)
print(f'今日费用: ¥{total:.2f} | 请求数: {len(logs)}')
if total > 100:
print('⚠️ 超预算!')
"
单行命令,零依赖。先跑起来,不够用了再上 Prometheus。
一步汇总
| 方案 | 时间 | 适用 |
|---|---|---|
| crontab + curl | 5 分钟 | 个人项目、日均 < ¥10 |
| Python exporter + Prometheus + Grafana | 30 分钟 | 团队、多 Agent、日均 > ¥50 |
| 加 Alertmanager | +10 分钟 | 不想每天盯着看 |
先上 crontab,费用破 ¥50/天再升到 Grafana。
下一步
诊断 → 治理(Prompt + 工具 + 模型路由 + 缓存)→ 监控,四篇覆盖了一条完整链路。你手里现在有全套工具箱了。
下篇写一个综合案例:从头到尾治理一个真实 Agent,把四篇的方法论串起来走一遍,看最终省了多少。
你现在是怎么盯 Agent 费用的? 每天翻 LiteLLM 日志、靠月底账单惊吓、还是压根没看?评论区聊聊,我看看有多少人在裸奔。
辉的技术笔记 · 知乎/掘金同步更新 · 每篇背后都是一段真实踩坑经历