Cloudflare 推出的 Billable Usage API,为账户提供了统一的可计费用量查询入口。开发者和 FinOps 团队不再需要分别处理各个自助服务产品的成本数据,而是可以通过单一端点,把 Cloudflare 的支出与其他云平台账单放进同一套采集、分析和告警流程。
这项能力的关键不只是“能查账单”,而是接口围绕 FOCUS 规范构建。对于已经在数据仓库中汇总 AWS、Azure、Google Cloud 等成本数据的团队,标准化字段意味着更少的专用转换逻辑,也更容易建立跨云口径一致的报表。
单一入口改变了什么
多产品账单分析最麻烦的部分,通常不是计算总额,而是数据入口和字段语义不一致。每增加一种产品,团队都可能需要新增抓取任务、字段映射和异常处理逻辑。
Billable Usage API 将账户下自助服务产品的成本和用量集中到一个端点,适合接入以下流程:
- 每日或每小时采集账户级成本数据;
- 按服务、时间或其他可用维度聚合支出;
- 将 Cloudflare 数据写入现有 FinOps 数据仓库;
- 对成本突增、预算超限和数据缺失触发告警;
- 在内部平台中展示接近业务语境的成本视图。
这里仍需区分“可计费用量”和最终财务账单。实际对账时,应确认接口数据的更新时间、费用调整方式、币种、税费处理以及最终账单之间的关系。来源摘要没有给出这些细节,因此生产接入前需要以当前 API 文档和账户返回结果为准。
FOCUS 的价值在于减少转换层
FOCUS 是面向云成本与用量数据的开放规范。采用统一语义后,团队可以让 Cloudflare 成本数据进入已有模型,而不必在每张报表里重复解释供应商私有字段。
例如,内部成本明细表可以围绕以下概念设计:
| 内部字段 | 用途 |
|---|---|
provider |
标识成本来源,例如 Cloudflare |
billing_account_id |
关联计费账户 |
service_name |
标识产生费用的服务 |
charge_period_start |
费用统计周期起点 |
billed_cost |
汇总或对账使用的费用金额 |
billing_currency |
防止跨币种直接求和 |
表中的字段只是可采用的仓库模型示例,并不代表 Billable Usage API 的精确响应结构。FOCUS 能缩短字段映射工作,但不能自动解决组织标签缺失、共享成本分摊或多币种换算等问题。
可以这样实践:拉取并汇总每日费用
下面的脚本演示一种最小接入方式:从环境变量读取 API 地址和令牌,请求数据,再按服务与币种汇总 BilledCost。
由于来源摘要没有提供正式端点、分页协议和完整响应结构,示例作出三个明确假设:
CLOUDFLARE_BILLABLE_USAGE_URL填写官方文档中当前的 Billable Usage API 完整地址;- 接口接受 Bearer Token;
- 响应记录位于
result、data或items数组中,并包含ServiceName、BilledCost和BillingCurrency字段。
运行前应根据真实文档调整认证方式、查询参数和字段映射。
#!/usr/bin/env python3
import json
import os
import sys
import urllib.error
import urllib.request
from collections import defaultdict
from decimal import Decimal, InvalidOperation
url = os.environ.get("CLOUDFLARE_BILLABLE_USAGE_URL")
token = os.environ.get("CLOUDFLARE_API_TOKEN")
if not url or not token:
sys.exit(
"Set CLOUDFLARE_BILLABLE_USAGE_URL and CLOUDFLARE_API_TOKEN first"
)
request = urllib.request.Request(
url,
headers={
"Authorization": f"Bearer {token}",
"Accept": "application/json",
"User-Agent": "finops-billable-usage-example/1.0",
},
)
try:
with urllib.request.urlopen(request, timeout=30) as response:
payload = json.load(response)
except urllib.error.HTTPError as exc:
detail = exc.read().decode("utf-8", errors="replace")
sys.exit(f"API returned HTTP {exc.code}: {detail}")
except urllib.error.URLError as exc:
sys.exit(f"Request failed: {exc.reason}")
if isinstance(payload, list):
records = payload
else:
records = payload.get("result") or payload.get("data") or payload.get("items") or []
if not isinstance(records, list):
sys.exit("Unexpected response: usage records are not an array")
totals = defaultdict(Decimal)
for record in records:
service = str(record.get("ServiceName") or "Unclassified")
currency = str(record.get("BillingCurrency") or "UNKNOWN")
try:
cost = Decimal(str(record.get("BilledCost", "0")))
except InvalidOperation:
sys.exit(f"Invalid BilledCost in record: {record!r}")
totals[(currency, service)] += cost
for (currency, service), cost in sorted(totals.items()):
print(f"{currency}\t{cost:.4f}\t{service}")
可以这样执行:
export CLOUDFLARE_BILLABLE_USAGE_URL='替换为官方文档中的完整端点'
export CLOUDFLARE_API_TOKEN='替换为只读 API 令牌'
python3 cloudflare_costs.py
生产任务还应保存原始响应。这样在字段映射出错或规范升级时,可以重新处理历史数据,而不必完全依赖再次调用接口。
接入数据仓库时别跳过这些边界
单端点降低了采集复杂度,但成本系统的可靠性取决于一组看起来不起眼的工程细节:
- 增量窗口:记录每次成功采集的周期,并适当回看最近窗口,以接收延迟数据或修订;
- 幂等写入:根据响应中实际可用的稳定标识构造唯一键,避免重跑任务导致重复费用;
- 分页与限流:按官方协议处理分页、超时、重试和速率限制,不能假设一次请求返回全部记录;
- 币种隔离:不同币种先分别汇总,只有在引入明确汇率与换算日期后才能合并;
- 最小权限:为采集任务创建只需读取计费数据的令牌,并通过密钥管理系统注入;
- 完整性监控:同时监控请求失败、空数据、记录数突变和费用突变。
采用建议
较稳妥的落地顺序是先运行一段时间的旁路采集,将 API 汇总结果与现有账单或控制台数据进行核对;确认时间窗口、币种和字段口径后,再接入预算告警与成本分摊。若团队已经采用 FOCUS 数据模型,可以优先复用现有事实表和报表,只为 Cloudflare 增加供应商级映射与质量检查。
Billable Usage API 解决的是“如何稳定取得统一成本数据”这一层问题。预算归属、共享服务分摊和业务单位成本仍需要组织自己的标签、账户结构与分摊规则。把接口当作可靠的数据入口,而不是完整的 FinOps 方案,通常能得到更可控的实施结果。