@daemonitor/plugins 1.1.53 → 1.1.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -76,6 +76,7 @@ export async function collectCost(p, today = todayUtc()) {
|
|
|
76
76
|
...summarizeCost(f, today),
|
|
77
77
|
breakdown: (f.breakdown || []).filter((b) => b.amount).sort((a, b) => b.amount - a.amount).slice(0, 12)
|
|
78
78
|
.map((b) => ({ name: b.name, amount: round2(b.amount) })),
|
|
79
|
+
...(f.limits?.length ? { limits: f.limits } : {}),
|
|
79
80
|
};
|
|
80
81
|
}
|
|
81
82
|
export function createCostPlugin() {
|
|
@@ -203,15 +203,47 @@ const vultr = async (cfg, _range, timeout) => {
|
|
|
203
203
|
const cloudflare = async (cfg, { end }, timeout) => {
|
|
204
204
|
need(cfg, "token", "accountId");
|
|
205
205
|
const t = tally(end.slice(0, 7));
|
|
206
|
-
const
|
|
206
|
+
const acct = `https://api.cloudflare.com/client/v4/accounts/${cfg.accountId}`;
|
|
207
|
+
const init = { headers: { Authorization: `Bearer ${cfg.token}` } };
|
|
208
|
+
const [body, limits] = await Promise.all([
|
|
209
|
+
json(`${acct}/billable-usage`, init, timeout),
|
|
210
|
+
cloudflareLimits(acct, init, timeout),
|
|
211
|
+
]);
|
|
207
212
|
let currency = "USD";
|
|
208
213
|
for (const r of body.result || []) {
|
|
209
214
|
if (r.BillingCurrency)
|
|
210
215
|
currency = r.BillingCurrency;
|
|
211
216
|
t.add(String(r.ChargePeriodStart || "").slice(0, 10), Number(r.BilledCost) || 0, r.ServiceName || r.ChargeDescription || undefined);
|
|
212
217
|
}
|
|
213
|
-
return { currency, days: t.days(), breakdown: t.breakdown() };
|
|
218
|
+
return { currency, days: t.days(), breakdown: t.breakdown(), ...(limits.length ? { limits } : {}) };
|
|
214
219
|
};
|
|
220
|
+
// Spend policies (beta, PayGo, Workers and Durable Objects only, 2026-11-13):
|
|
221
|
+
// per-product limits that email (`notification`) or stop the product
|
|
222
|
+
// (`usage_block`). Optional: a token without Billing access or an account with
|
|
223
|
+
// no policies leaves the spend row as it was. Cents converted to dollars here.
|
|
224
|
+
async function cloudflareLimits(acct, init, timeout) {
|
|
225
|
+
try {
|
|
226
|
+
const body = await json(`${acct}/billing/spend-policies`, init, timeout);
|
|
227
|
+
return (body.result || []).filter((p) => p.enabled).map((p) => cfLimit(p));
|
|
228
|
+
}
|
|
229
|
+
catch (e) {
|
|
230
|
+
if (e instanceof HttpError && [403, 404].includes(e.status))
|
|
231
|
+
return [];
|
|
232
|
+
throw e;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
export function cfLimit(p) {
|
|
236
|
+
const st = p.current_state || {};
|
|
237
|
+
return {
|
|
238
|
+
name: p.name || p.product_id,
|
|
239
|
+
product: String(p.product_id || ""),
|
|
240
|
+
blocks: p.action === "usage_block",
|
|
241
|
+
threshold: (Number(p.threshold_cents) || 0) / 100,
|
|
242
|
+
...(st.balance_cents != null ? { spent: (Number(st.balance_cents) || 0) / 100 } : {}),
|
|
243
|
+
status: String(st.status || "unavailable"),
|
|
244
|
+
...(st.billing_period_end ? { periodEnd: st.billing_period_end } : {}),
|
|
245
|
+
};
|
|
246
|
+
}
|
|
215
247
|
// PostHog: daily spend series, personal API key with billing:read. End is INCLUSIVE.
|
|
216
248
|
const posthog = async (cfg, { start, end }, timeout) => {
|
|
217
249
|
need(cfg, "apiKey");
|