mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-03 13:52:09 +03:00
149 lines
4.7 KiB
TypeScript
149 lines
4.7 KiB
TypeScript
import { getDbInstance } from "./core";
|
|
|
|
export interface CompressionAnalyticsRow {
|
|
id?: number;
|
|
timestamp: string;
|
|
combo_id?: string | null;
|
|
provider?: string | null;
|
|
mode: string;
|
|
original_tokens: number;
|
|
compressed_tokens: number;
|
|
tokens_saved: number;
|
|
duration_ms?: number | null;
|
|
request_id?: string | null;
|
|
}
|
|
|
|
export interface CompressionAnalyticsSummary {
|
|
totalRequests: number;
|
|
totalTokensSaved: number;
|
|
avgSavingsPct: number;
|
|
avgDurationMs: number;
|
|
byMode: Record<string, { count: number; tokensSaved: number; avgSavingsPct: number }>;
|
|
byProvider: Record<string, { count: number; tokensSaved: number }>;
|
|
last24h: Array<{ hour: string; count: number; tokensSaved: number }>;
|
|
}
|
|
|
|
export function insertCompressionAnalyticsRow(row: CompressionAnalyticsRow): void {
|
|
const db = getDbInstance();
|
|
db.prepare(
|
|
`
|
|
INSERT INTO compression_analytics (timestamp, combo_id, provider, mode, original_tokens, compressed_tokens, tokens_saved, duration_ms, request_id)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
`
|
|
).run(
|
|
row.timestamp,
|
|
row.combo_id ?? null,
|
|
row.provider ?? null,
|
|
row.mode,
|
|
row.original_tokens,
|
|
row.compressed_tokens,
|
|
row.tokens_saved,
|
|
row.duration_ms ?? null,
|
|
row.request_id ?? null
|
|
);
|
|
}
|
|
|
|
export function getCompressionAnalyticsSummary(since?: string): CompressionAnalyticsSummary {
|
|
const db = getDbInstance();
|
|
|
|
let cutoff: string | null = null;
|
|
if (since === "24h") {
|
|
cutoff = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
|
|
} else if (since === "7d") {
|
|
cutoff = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
|
|
} else if (since === "30d") {
|
|
cutoff = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString();
|
|
}
|
|
|
|
const whereClause = cutoff ? "WHERE timestamp >= ?" : "";
|
|
const params = cutoff ? [cutoff] : [];
|
|
|
|
type ScalarRow = { total: number; totalSaved: number; avgPct: number; avgDur: number };
|
|
const scalar = db
|
|
.prepare(
|
|
`
|
|
SELECT
|
|
COUNT(*) as total,
|
|
COALESCE(SUM(tokens_saved), 0) as totalSaved,
|
|
COALESCE(AVG(CASE WHEN original_tokens > 0 THEN CAST(tokens_saved AS REAL) / original_tokens * 100 ELSE 0 END), 0) as avgPct,
|
|
COALESCE(AVG(duration_ms), 0) as avgDur
|
|
FROM compression_analytics ${whereClause}
|
|
`
|
|
)
|
|
.get(...params) as ScalarRow | undefined;
|
|
|
|
const modeRows = db
|
|
.prepare(
|
|
`
|
|
SELECT mode, COUNT(*) as cnt, COALESCE(SUM(tokens_saved), 0) as saved,
|
|
COALESCE(AVG(CASE WHEN original_tokens > 0 THEN CAST(tokens_saved AS REAL) / original_tokens * 100 ELSE 0 END), 0) as avgPct
|
|
FROM compression_analytics ${whereClause}
|
|
GROUP BY mode
|
|
`
|
|
)
|
|
.all(...params) as Array<{ mode: string; cnt: number; saved: number; avgPct: number }>;
|
|
|
|
const byMode: Record<string, { count: number; tokensSaved: number; avgSavingsPct: number }> = {};
|
|
for (const r of modeRows) {
|
|
byMode[r.mode] = { count: r.cnt, tokensSaved: r.saved, avgSavingsPct: Math.round(r.avgPct) };
|
|
}
|
|
|
|
const provRows = db
|
|
.prepare(
|
|
`
|
|
SELECT provider, COUNT(*) as cnt, COALESCE(SUM(tokens_saved), 0) as saved
|
|
FROM compression_analytics ${whereClause}
|
|
GROUP BY provider ORDER BY cnt DESC
|
|
`
|
|
)
|
|
.all(...params) as Array<{ provider: string | null; cnt: number; saved: number }>;
|
|
|
|
const byProvider: Record<string, { count: number; tokensSaved: number }> = {};
|
|
for (const r of provRows) {
|
|
const key = r.provider ?? "unknown";
|
|
byProvider[key] = { count: r.cnt, tokensSaved: r.saved };
|
|
}
|
|
|
|
const last24hMap = new Map<string, { hour: string; count: number; tokensSaved: number }>();
|
|
const now = new Date();
|
|
for (let i = 23; i >= 0; i--) {
|
|
const d = new Date(now.getTime() - i * 60 * 60 * 1000);
|
|
const hourStr = d.toISOString().substring(0, 14) + "00:00Z";
|
|
last24hMap.set(hourStr, { hour: hourStr, count: 0, tokensSaved: 0 });
|
|
}
|
|
|
|
const hourRows = db
|
|
.prepare(
|
|
`
|
|
SELECT strftime('%Y-%m-%dT%H:00:00Z', timestamp) as hour,
|
|
COUNT(*) as cnt, COALESCE(SUM(tokens_saved), 0) as saved
|
|
FROM compression_analytics
|
|
WHERE timestamp >= ?
|
|
GROUP BY hour ORDER BY hour ASC
|
|
`
|
|
)
|
|
.all(new Date(now.getTime() - 24 * 60 * 60 * 1000).toISOString()) as Array<{
|
|
hour: string;
|
|
cnt: number;
|
|
saved: number;
|
|
}>;
|
|
|
|
for (const r of hourRows) {
|
|
if (last24hMap.has(r.hour)) {
|
|
last24hMap.set(r.hour, { hour: r.hour, count: r.cnt, tokensSaved: r.saved });
|
|
}
|
|
}
|
|
|
|
const last24h = Array.from(last24hMap.values());
|
|
|
|
return {
|
|
totalRequests: scalar?.total ?? 0,
|
|
totalTokensSaved: scalar?.totalSaved ?? 0,
|
|
avgSavingsPct: Math.round(scalar?.avgPct ?? 0),
|
|
avgDurationMs: Math.round(scalar?.avgDur ?? 0),
|
|
byMode,
|
|
byProvider,
|
|
last24h,
|
|
};
|
|
}
|