import { describe, it, expect, beforeEach } from 'vitest'; import { Registry } from 'prom-client'; import { createWorkerMetrics } from './worker-metrics.js'; describe('metrics/worker-metrics', () => { let reg: Registry; beforeEach(() => { reg = new Registry(); }); it('registers all 6 metrics under the supplied prefix', async () => { createWorkerMetrics(reg, 'aao_worker_t'); const out = await reg.metrics(); for (const name of [ 'aao_worker_t_jobs_total', 'aao_worker_t_active_jobs', 'aao_worker_t_job_duration_seconds', 'aao_worker_t_llm_calls_total', 'aao_worker_t_llm_call_duration_seconds', 'aao_worker_t_tool_calls_total', ]) { expect(out).toContain(name); } }); it('activeJobs supports inc/dec', async () => { const m = createWorkerMetrics(reg, 'aao_worker_g'); m.activeJobs.inc({ piece: 'chat', profile: 'main' }); m.activeJobs.inc({ piece: 'chat', profile: 'main' }); m.activeJobs.dec({ piece: 'chat', profile: 'main' }); const out = await reg.metrics(); expect(out).toMatch(/aao_worker_g_active_jobs\{piece="chat",profile="main"\} 1/); }); it('tool calls split by success label', async () => { const m = createWorkerMetrics(reg, 'aao_worker_tc'); m.toolCallsTotal.inc({ tool_name: 'Read', success: 'true' }, 5); m.toolCallsTotal.inc({ tool_name: 'Read', success: 'false' }, 1); const out = await reg.metrics(); expect(out).toMatch(/aao_worker_tc_tool_calls_total\{tool_name="Read",success="true"\} 5/); expect(out).toMatch(/aao_worker_tc_tool_calls_total\{tool_name="Read",success="false"\} 1/); }); it('LLM histogram observes seconds (not ms)', async () => { const m = createWorkerMetrics(reg, 'aao_worker_llm'); m.llmCallDurationSeconds.observe( { worker_id: 'w1', backend_id: 'gpu-a', model: 'qwen3:8b' }, 2.5, ); const out = await reg.metrics(); expect(out).toMatch(/aao_worker_llm_llm_call_duration_seconds_sum\{[^}]+\} 2\.5/); }); it('job-duration buckets fit minute-to-hour range', async () => { const m = createWorkerMetrics(reg, 'aao_worker_jd'); m.jobDurationSeconds.observe( { piece: 'chat', status: 'succeeded', profile: 'main' }, 75, ); const out = await reg.metrics(); // The 120s bucket should be incremented (75 < 120) expect(out).toMatch(/aao_worker_jd_job_duration_seconds_bucket\{[^}]*le="120"[^}]*\} 1/); // The 60s bucket should NOT be incremented (75 > 60) expect(out).toMatch(/aao_worker_jd_job_duration_seconds_bucket\{[^}]*le="60"[^}]*\} 0/); }); });