Skip to content

Commit baec56d

Browse files
authored
Merge pull request #590 from kalebosas2-dev/fix/issue-463-getmetrics-s-by-method-and-by-path-breakdowns
fix: populate by_method and by_path breakdowns in getMetrics
2 parents dd3d656 + d1624f5 commit baec56d

1 file changed

Lines changed: 68 additions & 6 deletions

File tree

src/lib/metrics.ts

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
interface RequestMetrics {
22
total_requests: number;
3+
34
total_errors: number;
45
total_success: number;
56
error_rate: number;
@@ -33,16 +34,60 @@ interface MetricsSnapshot {
3334
by_path: PathMetrics;
3435
}
3536

36-
const startTime = Date.now();
37-
const requestWindow: Array<{ status: number; latency: number; timestamp: number }> = [];
38-
const MAX_WINDOW_SIZE = 10000;
37+
interface RequestEntry {
38+
method: string;
39+
path: string;
40+
status: number;
41+
latency: number;
42+
timestamp: number;
43+
}
44+
45+
interface MethodCounter {
46+
count: number;
47+
errors: number;
48+
totalLatencyMs: number;
49+
}
3950

51+
interface PathCounter {
52+
count: number;
53+
errors: number;
54+
totalLatencyMs: number;
55+
}
56+
57+
const startTime = Date.now(); const requestWindow: RequestEntry[] = []; const MAX_WINDOW_SIZE = 10000; const methodCounters: { [method: string]: MethodCounter } = {}; const pathCounters: { [path: string]: PathCounter } = {};
4058
export function recordRequest(method: string, path: string, status: number, latencyMs: number): void {
4159
const timestamp = Date.now();
42-
requestWindow.push({ status, latency: latencyMs, timestamp });
60+
requestWindow.push({ method, path, status, latency: latencyMs, timestamp });
61+
62+
const methodCounter = methodCounters[method] ||= { count: 0, errors: 0, totalLatencyMs: 0 };
63+
methodCounter.count++;
64+
methodCounter.totalLatencyMs += latencyMs;
65+
if (status >= 400) methodCounter.errors++;
66+
67+
const pathCounter = pathCounters[path] ||= { count: 0, errors: 0, totalLatencyMs: 0 };
68+
pathCounter.count++;
69+
pathCounter.totalLatencyMs += latencyMs;
70+
if (status >= 400) pathCounter.errors++;
4371

4472
if (requestWindow.length > MAX_WINDOW_SIZE) {
45-
requestWindow.shift();
73+
const removed = requestWindow.shift();
74+
if (removed) {
75+
const mc = methodCounters[removed.method];
76+
if (mc) {
77+
mc.count--;
78+
mc.totalLatencyMs -= removed.latency;
79+
if (removed.status >= 400) mc.errors--;
80+
if (mc.count <= 0) delete methodCounters[removed.method];
81+
}
82+
83+
const pc = pathCounters[removed.path];
84+
if (pc) {
85+
pc.count--;
86+
pc.totalLatencyMs -= removed.latency;
87+
if (removed.status >= 400) pc.errors--;
88+
if (pc.count <= 0) delete pathCounters[removed.path];
89+
}
90+
}
4691
}
4792
}
4893

@@ -66,7 +111,24 @@ export function getMetrics(): MetricsSnapshot {
66111
const errorsPerMinute = recentRequests.filter((r) => r.status >= 400).length;
67112

68113
const byMethod: MethodMetrics = {};
114+
for (const method of Object.keys(methodCounters)) {
115+
const counter = methodCounters[method];
116+
byMethod[method] = {
117+
count: counter.count,
118+
errors: counter.errors,
119+
avg_latency_ms: counter.count > 0 ? Math.round((counter.totalLatencyMs / counter.count) * 100) / 100 : 0,
120+
};
121+
}
122+
69123
const byPath: PathMetrics = {};
124+
for (const path of Object.keys(pathCounters)) {
125+
const counter = pathCounters[path];
126+
byPath[path] = {
127+
count: counter.count,
128+
errors: counter.errors,
129+
avg_latency_ms: counter.count > 0 ? Math.round((counter.totalLatencyMs / counter.count) * 100) / 100 : 0,
130+
};
131+
}
70132

71133
return {
72134
timestamp: new Date(now).toISOString(),
@@ -84,4 +146,4 @@ export function getMetrics(): MetricsSnapshot {
84146
by_method: byMethod,
85147
by_path: byPath,
86148
};
87-
}
149+
}

0 commit comments

Comments
 (0)