47 lines
1.1 KiB
TypeScript
47 lines
1.1 KiB
TypeScript
|
|
interface PerfSample {
|
||
|
|
metric: string;
|
||
|
|
operation: string;
|
||
|
|
value: number;
|
||
|
|
}
|
||
|
|
|
||
|
|
const FLUSH_INTERVAL_MS = 30_000;
|
||
|
|
let batch: PerfSample[] = [];
|
||
|
|
let flushTimer: ReturnType<typeof setInterval> | null = null;
|
||
|
|
|
||
|
|
export function record(metric: string, operation: string, value: number): void {
|
||
|
|
batch.push({ metric, operation, value });
|
||
|
|
}
|
||
|
|
|
||
|
|
function flush(): void {
|
||
|
|
if (batch.length === 0) return;
|
||
|
|
const blob = new Blob([JSON.stringify(batch)], { type: 'application/json' });
|
||
|
|
batch = [];
|
||
|
|
|
||
|
|
if (navigator.sendBeacon) {
|
||
|
|
navigator.sendBeacon('/api/perf', blob);
|
||
|
|
} else {
|
||
|
|
fetch('/api/perf', {
|
||
|
|
method: 'POST',
|
||
|
|
headers: { 'Content-Type': 'application/json' },
|
||
|
|
body: blob,
|
||
|
|
keepalive: true,
|
||
|
|
}).catch(() => {});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export function startCollector(): void {
|
||
|
|
if (flushTimer) return;
|
||
|
|
flushTimer = setInterval(flush, FLUSH_INTERVAL_MS);
|
||
|
|
document.addEventListener('visibilitychange', () => {
|
||
|
|
if (document.visibilityState === 'hidden') flush();
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
export function stopCollector(): void {
|
||
|
|
if (flushTimer) {
|
||
|
|
clearInterval(flushTimer);
|
||
|
|
flushTimer = null;
|
||
|
|
}
|
||
|
|
flush();
|
||
|
|
}
|