Remove daily report system (page, API routes, cron scheduler) as it is no longer needed. Add /api/metrics endpoint exposing total and time- windowed counts (27h, 7d, 30d) for users, workspaces, projects, repos, rooms, and skills. Also clean up dead code: - Remove OpenRouter sync and alerts check routes - Remove syncModels/checkAlerts from adminrpc client - Remove unused adminRpcAvailable state from platform sessions page - Fix handleEdit displayName comparison bug in platform users page - Simplify pricing sync to create 0-price defaults
66 lines
2.0 KiB
TypeScript
66 lines
2.0 KiB
TypeScript
import { logError } from "@/lib/logger";
|
|
import { NextResponse } from "next/server";
|
|
import { query } from "@/lib/db";
|
|
|
|
export const runtime = "nodejs";
|
|
|
|
/**
|
|
* Platform metrics endpoint.
|
|
* Returns total / 27h / 7d / 30d new counts for all platform entities.
|
|
*/
|
|
export async function GET() {
|
|
try {
|
|
// Query all entity counts in parallel
|
|
// Tables: user, workspace, project, repo, room, project_skill
|
|
const entities = [
|
|
{ name: "users", table: '"user"' },
|
|
{ name: "workspaces", table: "workspace" },
|
|
{ name: "projects", table: "project" },
|
|
{ name: "repos", table: "repo" },
|
|
{ name: "rooms", table: "room" },
|
|
{ name: "skills", table: "project_skill" },
|
|
];
|
|
|
|
const results = await Promise.all(
|
|
entities.map(async ({ name, table }) => {
|
|
const res = await query<{
|
|
total: string;
|
|
new_27h: string;
|
|
new_7d: string;
|
|
new_30d: string;
|
|
}>(
|
|
`SELECT
|
|
COUNT(*) AS total,
|
|
COUNT(*) FILTER (WHERE created_at >= NOW() - INTERVAL '27 hours') AS new_27h,
|
|
COUNT(*) FILTER (WHERE created_at >= NOW() - INTERVAL '7 days') AS new_7d,
|
|
COUNT(*) FILTER (WHERE created_at >= NOW() - INTERVAL '30 days') AS new_30d
|
|
FROM ${table}`
|
|
);
|
|
const row = res.rows[0];
|
|
return {
|
|
name,
|
|
total: parseInt(row.total, 10),
|
|
new_27h: parseInt(row.new_27h, 10),
|
|
new_7d: parseInt(row.new_7d, 10),
|
|
new_30d: parseInt(row.new_30d, 10),
|
|
};
|
|
})
|
|
);
|
|
|
|
const metrics: Record<string, unknown> = {};
|
|
for (const r of results) {
|
|
metrics[r.name] = {
|
|
total: r.total,
|
|
last_27h: r.new_27h,
|
|
last_7d: r.new_7d,
|
|
last_30d: r.new_30d,
|
|
};
|
|
}
|
|
|
|
return NextResponse.json({ metrics, timestamp: new Date().toISOString() });
|
|
} catch (e) {
|
|
logError("Metrics error:", e);
|
|
return NextResponse.json({ error: "服务器错误" }, { status: 500 });
|
|
}
|
|
}
|