v0.2.8 operator dashboard with per-call audit log + cost tracking
This commit is contained in:
@@ -12,6 +12,8 @@ import { getConfigSnapshot } from "../config.js";
|
||||
import { snapshotAll } from "../credits.js";
|
||||
import { snapshotCache } from "../keysat-client.js";
|
||||
import { snapshotJobs } from "../job-credits.js";
|
||||
import { readEntries, aggregate } from "../audit-log.js";
|
||||
import { GEMINI_PRICING } from "../pricing.js";
|
||||
import fs from "fs/promises";
|
||||
import path from "path";
|
||||
|
||||
@@ -48,6 +50,49 @@ export function adminRouter({ dataDir }) {
|
||||
res.json({ entries: snapshotJobs() });
|
||||
});
|
||||
|
||||
// ── Dashboard ─────────────────────────────────────────────────────────
|
||||
// Time-range aggregations over the per-call audit log. Default range
|
||||
// is the last 30 days; override with ?days=N or ?since=<ms-epoch>.
|
||||
// Returns { range, summary, by_tier, by_model, by_pipeline,
|
||||
// by_backend, by_install, by_hour_utc, cost_vs_speed, pricing }.
|
||||
router.get("/dashboard", async (req, res) => {
|
||||
const days =
|
||||
typeof req.query.days === "string"
|
||||
? parseInt(req.query.days, 10)
|
||||
: null;
|
||||
const explicitSince =
|
||||
typeof req.query.since === "string"
|
||||
? parseInt(req.query.since, 10)
|
||||
: null;
|
||||
const sinceMs =
|
||||
explicitSince && Number.isFinite(explicitSince)
|
||||
? explicitSince
|
||||
: Date.now() -
|
||||
(Number.isFinite(days) && days > 0 ? days : 30) *
|
||||
24 *
|
||||
3600 *
|
||||
1000;
|
||||
try {
|
||||
const entries = await readEntries({ sinceMs });
|
||||
const agg = aggregate(entries);
|
||||
res.json({
|
||||
range: {
|
||||
since_ms: sinceMs,
|
||||
until_ms: Date.now(),
|
||||
days: Number.isFinite(days) && days > 0 ? days : null,
|
||||
total_entries: entries.length,
|
||||
},
|
||||
...agg,
|
||||
pricing: GEMINI_PRICING,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(`[admin/dashboard] failed: ${err?.message || err}`);
|
||||
res
|
||||
.status(500)
|
||||
.json({ error: "dashboard_failed", message: err?.message || String(err) });
|
||||
}
|
||||
});
|
||||
|
||||
// Adjust the live quotas blob. Same shape the StartOS action writes
|
||||
// to relay_tier_quotas_json — kept here so the dashboard can tune
|
||||
// quotas without round-tripping the StartOS UI.
|
||||
|
||||
Reference in New Issue
Block a user