Files
Visigine/server/lib/activity.js
Ihor_Zhekov e344f1b7e7 Initial commit: Visigine (Vite client + Express/SQLite backend)
Container-ready via docker/ compose (frontend nginx + backend Node). Compose adjusted for Coolify on the prod server: frontend uses expose:80 (no host binding — host 8080 is taken by the Coolify proxy; Traefik routes visigine.de), backend ALLOWED_ORIGINS=https://visigine.de. Secrets stay in server/.env (git-ignored); see server/.env.example.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 10:15:06 +02:00

60 lines
1.7 KiB
JavaScript

// Rolling buffer of recent analyses, resets on restart.
// Metadata-only by design — no PII, no full response bodies, no extracted siteData.
const MAX_ENTRIES = 50
const log = []
export function recordAnalysis(entry) {
log.unshift({
ts: new Date().toISOString(),
requestId: entry.requestId,
host: entry.host || null,
score: entry.score ?? null,
issuesCount: entry.issuesCount ?? null,
failedCheckIds: entry.failedCheckIds || [],
cacheHit: Boolean(entry.cacheHit),
ms: entry.ms ?? 0,
status: entry.status === 'ok' ? 'ok' : 'err',
code: entry.code || null,
admin: Boolean(entry.admin),
})
if (log.length > MAX_ENTRIES) log.pop()
}
export function recentAnalyses() {
return [...log]
}
export function computeStats() {
const succeeded = log.filter((e) => e.status === 'ok' && typeof e.score === 'number')
if (!succeeded.length) {
return { total: log.length, succeeded: 0, avgScore: null, topFails: [], topHosts: [] }
}
const avgScore = succeeded.reduce((s, e) => s + e.score, 0) / succeeded.length
const failCounts = {}
for (const e of succeeded) {
for (const id of e.failedCheckIds) failCounts[id] = (failCounts[id] || 0) + 1
}
const topFails = Object.entries(failCounts)
.sort((a, b) => b[1] - a[1])
.slice(0, 5)
.map(([id, count]) => ({ id, count }))
const hostCounts = {}
for (const e of log) {
if (e.host) hostCounts[e.host] = (hostCounts[e.host] || 0) + 1
}
const topHosts = Object.entries(hostCounts)
.sort((a, b) => b[1] - a[1])
.slice(0, 10)
.map(([host, count]) => ({ host, count }))
return {
total: log.length,
succeeded: succeeded.length,
avgScore: Number(avgScore.toFixed(1)),
topFails,
topHosts,
}
}