Make Git slowdowns visible in daemon metrics (#2366)
* feat(server): expose daemon Git pressure metrics Separate limiter queue wait from Git execution time and report subscription ownership so accumulating work is visible in the existing runtime log. * fix(server): collect subscriptions in agent metrics Reuse the existing agent snapshot during runtime flushes so WebSocket shutdown does not require an additional AgentManager method call. * test(server): retry transient hub cleanup
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { GitCommandRuntimeMetricsWindow } from "./git-command-runtime-metrics.js";
|
||||
|
||||
function createMetricsWindow(concurrencyLimit = 2) {
|
||||
let now = 1_000;
|
||||
return {
|
||||
metrics: new GitCommandRuntimeMetricsWindow(concurrencyLimit, () => now),
|
||||
advance(ms: number) {
|
||||
now += ms;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
describe("GitCommandRuntimeMetricsWindow", () => {
|
||||
test("separates queue wait from execution time", () => {
|
||||
const { metrics, advance } = createMetricsWindow();
|
||||
const command = metrics.submit("status");
|
||||
advance(40);
|
||||
metrics.start(command);
|
||||
advance(15);
|
||||
metrics.finish(command, { success: true, timedOut: false });
|
||||
|
||||
expect(metrics.snapshotAndReset()).toMatchObject({
|
||||
submitted: 1,
|
||||
started: 1,
|
||||
completed: 1,
|
||||
failed: 0,
|
||||
timedOut: 0,
|
||||
queueWaitMs: { count: 1, p50Ms: 40, p95Ms: 40, maxMs: 40 },
|
||||
executionMs: { count: 1, p50Ms: 15, p95Ms: 15, maxMs: 15 },
|
||||
operationsTop: [["status", 1]],
|
||||
});
|
||||
});
|
||||
|
||||
test("reports live queue pressure across window resets", () => {
|
||||
const { metrics, advance } = createMetricsWindow(1);
|
||||
const active = metrics.submit("fetch");
|
||||
metrics.start(active);
|
||||
const pending = metrics.submit("rev-parse");
|
||||
metrics.observeLimiter(1, 1);
|
||||
advance(25);
|
||||
|
||||
expect(metrics.snapshotAndReset()).toMatchObject({
|
||||
concurrencyLimit: 1,
|
||||
active: 1,
|
||||
pending: 1,
|
||||
peakActive: 1,
|
||||
peakPending: 1,
|
||||
oldestPendingMs: 25,
|
||||
submitted: 2,
|
||||
started: 1,
|
||||
});
|
||||
|
||||
advance(10);
|
||||
metrics.finish(active, { success: true, timedOut: false });
|
||||
metrics.start(pending);
|
||||
metrics.observeLimiter(1, 0);
|
||||
advance(5);
|
||||
metrics.finish(pending, { success: false, timedOut: true });
|
||||
|
||||
expect(metrics.snapshotAndReset()).toMatchObject({
|
||||
active: 0,
|
||||
pending: 0,
|
||||
peakActive: 1,
|
||||
peakPending: 1,
|
||||
submitted: 0,
|
||||
started: 1,
|
||||
completed: 2,
|
||||
failed: 1,
|
||||
timedOut: 1,
|
||||
queueWaitMs: { count: 1, p50Ms: 35, p95Ms: 35, maxMs: 35 },
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user