feat: add agent run heartbeat to slo reports
This commit is contained in:
@@ -224,6 +224,7 @@ async function readRedisSummary(namespace, redisUrl) {
|
||||
|
||||
function summarizeRuntime(runtimeJson) {
|
||||
const workers = runtimeJson?.router?.workers ?? [];
|
||||
const toolQueue = runtimeJson?.toolRuntime?.queue ?? null;
|
||||
const staleMetricMs = 2 * 60 * 1000;
|
||||
const staleHeartbeatMs = Number(process.env.MEMIND_RUNTIME_HEARTBEAT_STALE_MS || 60 * 1000);
|
||||
const now = Date.now();
|
||||
@@ -231,7 +232,20 @@ function summarizeRuntime(runtimeJson) {
|
||||
routerEnabled: Boolean(runtimeJson?.router?.enabled),
|
||||
publicBaseUrl: runtimeJson?.publicBaseUrl ?? null,
|
||||
toolRuntime: runtimeJson?.toolRuntime ?? null,
|
||||
toolQueue: runtimeJson?.toolRuntime?.queue ?? null,
|
||||
toolQueue,
|
||||
toolQueueSlo: toolQueue
|
||||
? {
|
||||
heartbeatMs: Number(toolQueue.heartbeatMs ?? 0),
|
||||
maxConcurrentRuns: Number(toolQueue.maxConcurrentRuns ?? 0),
|
||||
statusCounts: toolQueue.statusCounts ?? {},
|
||||
oldestRunningStartedAt: toolQueue.oldestRunningStartedAt ?? null,
|
||||
oldestRunningAgeMs: Number(toolQueue.oldestRunningAgeMs ?? 0),
|
||||
oldestRunningHeartbeatAt: toolQueue.oldestRunningHeartbeatAt ?? null,
|
||||
oldestRunningHeartbeatAgeMs: Number(toolQueue.oldestRunningHeartbeatAgeMs ?? 0),
|
||||
runningWithoutHeartbeatCount: Number(toolQueue.runningWithoutHeartbeatCount ?? 0),
|
||||
latestRunningRun: toolQueue.latestRunningRun ?? null,
|
||||
}
|
||||
: null,
|
||||
workers: workers.map((worker) => ({
|
||||
id: worker.id,
|
||||
healthy: runtimeJson?.targets?.find((target) => target.target === worker.target)?.healthy ?? null,
|
||||
@@ -325,6 +339,21 @@ if (runtimeSummary?.toolQueue?.error) failures.push('tool_queue_status_error');
|
||||
if (runtimeSummary?.toolQueue?.inFlight > runtimeSummary?.toolQueue?.maxConcurrentRuns) {
|
||||
failures.push('tool_queue_concurrency_exceeded');
|
||||
}
|
||||
const agentRunHeartbeatStaleMs = Number(
|
||||
process.env.MEMIND_AGENT_RUN_HEARTBEAT_STALE_MS ||
|
||||
Math.max(90 * 1000, Number(runtimeSummary?.toolQueueSlo?.heartbeatMs ?? 0) * 3),
|
||||
);
|
||||
if (
|
||||
runtimeSummary?.toolQueueSlo?.oldestRunningHeartbeatAgeMs > agentRunHeartbeatStaleMs
|
||||
) {
|
||||
failures.push(`agent_run_heartbeat_stale_${runtimeSummary.toolQueueSlo.oldestRunningHeartbeatAgeMs}`);
|
||||
}
|
||||
if (
|
||||
Number(runtimeSummary?.toolQueueSlo?.runningWithoutHeartbeatCount ?? 0) > 0 &&
|
||||
Number(runtimeSummary?.toolQueueSlo?.oldestRunningAgeMs ?? 0) > agentRunHeartbeatStaleMs
|
||||
) {
|
||||
failures.push(`agent_run_missing_heartbeat_${runtimeSummary.toolQueueSlo.runningWithoutHeartbeatCount}`);
|
||||
}
|
||||
|
||||
const reportDir = path.resolve(args.reportDir || path.join(appRoot, 'reports', 'runtime-slo'));
|
||||
if (args.writeReport || args.prune) {
|
||||
@@ -392,6 +421,10 @@ function markdownReport(payload) {
|
||||
'',
|
||||
'## Tool Queue',
|
||||
'',
|
||||
`- heartbeatMs: ${payload.runtime?.toolQueueSlo?.heartbeatMs ?? 0}`,
|
||||
`- oldestRunningHeartbeatAgeMs: ${payload.runtime?.toolQueueSlo?.oldestRunningHeartbeatAgeMs ?? 0}`,
|
||||
`- runningWithoutHeartbeatCount: ${payload.runtime?.toolQueueSlo?.runningWithoutHeartbeatCount ?? 0}`,
|
||||
'',
|
||||
'```json',
|
||||
JSON.stringify(payload.runtime?.toolQueue ?? null, null, 2),
|
||||
'```',
|
||||
|
||||
Reference in New Issue
Block a user