-
Notifications
You must be signed in to change notification settings - Fork 291
Expand file tree
/
Copy pathperf-metrics.ts
More file actions
88 lines (75 loc) · 2.15 KB
/
Copy pathperf-metrics.ts
File metadata and controls
88 lines (75 loc) · 2.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import type { PerfMetricsSnapshot } from "./types.js";
type TimingBucket = {
count: number;
totalMs: number;
maxMs: number;
};
const counters = new Map<string, number>();
const gauges = new Map<string, number>();
const timings = new Map<string, TimingBucket>();
function hrNow(): bigint {
return process.hrtime.bigint();
}
function durationMs(start: bigint): number {
return Number(process.hrtime.bigint() - start) / 1_000_000;
}
function roundMetric(value: number): number {
return Number(value.toFixed(3));
}
export function incrementPerfCounter(name: string, delta = 1): void {
counters.set(name, (counters.get(name) ?? 0) + delta);
}
export function setPerfGauge(name: string, value: number): void {
gauges.set(name, value);
}
export function recordPerfDuration(name: string, durationMsValue: number): void {
const next = timings.get(name) ?? {
count: 0,
totalMs: 0,
maxMs: 0,
};
next.count += 1;
next.totalMs += durationMsValue;
next.maxMs = Math.max(next.maxMs, durationMsValue);
timings.set(name, next);
}
export async function measurePerf<T>(name: string, run: () => Promise<T>): Promise<T> {
const startedAt = hrNow();
try {
return await run();
} finally {
recordPerfDuration(name, durationMs(startedAt));
}
}
export function startPerfTimer(name: string): () => number {
const startedAt = hrNow();
return () => {
const elapsedMs = durationMs(startedAt);
recordPerfDuration(name, elapsedMs);
return elapsedMs;
};
}
export function getPerfMetricsSnapshot(): PerfMetricsSnapshot {
return {
counters: Object.fromEntries(counters.entries()),
gauges: Object.fromEntries(gauges.entries()),
timings: Object.fromEntries(
[...timings.entries()].map(([name, bucket]) => [
name,
{
count: bucket.count,
totalMs: roundMetric(bucket.totalMs),
maxMs: roundMetric(bucket.maxMs),
},
]),
),
};
}
export function resetPerfMetrics(): void {
counters.clear();
gauges.clear();
timings.clear();
}
export function formatPerfMetric(name: string, durationMsValue: number): string {
return `${name}=${roundMetric(durationMsValue)}ms`;
}