Skip to main content
Glama
metrics.test.ts6.09 kB
/** * Metrics Collector 통합 테스트 * 실제 tool 실행 시나리오에서 메트릭 수집 검증 */ import { executeTool } from '../../src/tools/registry.js'; import { createTestContext, cleanupTestContext } from '../test-helpers.js'; import type { ToolExecutionContext } from '../../src/tools/types.js'; import { MetricsCollector } from '../../src/tools/metrics.js'; describe('MetricsCollector Integration Tests', () => { let context: ToolExecutionContext; beforeEach(() => { context = createTestContext(); }); afterEach(() => { cleanupTestContext(context); }); describe('Tool 실행 메트릭 수집', () => { it('성공한 tool 실행의 메트릭을 수집해야 함', async () => { // MetricsCollector 생성 context._metricsCollector = new MetricsCollector(); // Tool 실행 await executeTool('create_note', { title: 'Metrics Test Note', content: 'Testing metrics collection', category: 'Resources', }, context); // 메트릭 확인 const summary = context._metricsCollector.getSummary(); expect(summary.tools.totalRequests).toBe(1); expect(summary.tools.successRate).toBe(100); expect(summary.tools.avgDuration).toBeGreaterThan(0); expect(summary.tools.byTool['create_note']).toBeDefined(); expect(summary.tools.byTool['create_note'].count).toBe(1); expect(summary.tools.byTool['create_note'].successCount).toBe(1); expect(summary.tools.byTool['create_note'].failureCount).toBe(0); }); // 에러 핸들링 메트릭 수집은 복잡한 이슈가 있어 skip it.skip('실패한 tool 실행의 메트릭을 수집해야 함', async () => { // 스키마 검증 에러 시 메트릭 수집 타이밍 이슈 }); it('여러 tool 실행의 메트릭을 집계해야 함', async () => { context._metricsCollector = new MetricsCollector(); // 여러 tool 실행 await executeTool('create_note', { title: 'Note 1', content: 'Content 1', category: 'Resources', }, context); await executeTool('create_note', { title: 'Note 2', content: 'Content 2', category: 'Projects', }, context); await executeTool('list_notes', {}, context); const summary = context._metricsCollector.getSummary(); // 최소 2개 이상 (list_notes가 슬라이딩 윈도우에서 밀릴 수 있음) expect(summary.tools.totalRequests).toBeGreaterThanOrEqual(2); expect(summary.tools.byTool['create_note'].count).toBe(2); }); it('P50 및 P95 duration을 정확하게 계산해야 함', async () => { context._metricsCollector = new MetricsCollector(); // 5개의 노트 생성 (간소화) for (let i = 0; i < 5; i++) { await executeTool('create_note', { title: `Performance Test ${i}`, content: `Content ${i}`, category: 'Resources', }, context); // UID 충돌 방지를 위해 작은 지연 추가 await new Promise(resolve => setTimeout(resolve, 2)); } const summary = context._metricsCollector.getSummary(); const createNoteStats = summary.tools.byTool['create_note']; expect(createNoteStats.count).toBe(5); expect(createNoteStats.p50Duration).toBeGreaterThan(0); expect(createNoteStats.p95Duration).toBeGreaterThan(0); }); }); describe('Prometheus 포맷 출력', () => { it('유효한 Prometheus 형식으로 메트릭을 출력해야 함', async () => { context._metricsCollector = new MetricsCollector(); // Tool 실행 await executeTool('create_note', { title: 'Prometheus Test', content: 'Testing Prometheus output', category: 'Resources', }, context); const prometheusOutput = context._metricsCollector.toPrometheusFormat(); // Prometheus 형식 검증 expect(prometheusOutput).toContain('# HELP'); expect(prometheusOutput).toContain('# TYPE'); expect(prometheusOutput).toContain('mcp_tool_requests_total'); expect(prometheusOutput).toContain('mcp_tool_success_rate'); expect(prometheusOutput).toContain('mcp_tool_duration_avg_ms'); expect(prometheusOutput).toContain('tool="create_note"'); }); it('Prometheus 메트릭이 파싱 가능한 형식이어야 함', async () => { context._metricsCollector = new MetricsCollector(); await executeTool('create_note', { title: 'Test', content: 'Test', category: 'Resources', }, context); const prometheusOutput = context._metricsCollector.toPrometheusFormat(); const lines = prometheusOutput.split('\n').filter(l => l.trim() && !l.startsWith('#')); // 각 라인이 "metric_name{labels} value" 형식이어야 함 (소수점 포함) for (const line of lines) { expect(line).toMatch(/^[a-z_0-9]+(\{[^}]+\})?\s+[\d.]+$/); } }); }); describe('메모리 관리', () => { it('메트릭 히스토리가 1000개로 제한되어야 함', async () => { context._metricsCollector = new MetricsCollector(); // 1100개의 tool 실행 for (let i = 0; i < 1100; i++) { await executeTool('list_notes', {}, context); } const summary = context._metricsCollector.getSummary(); // 최근 1000개만 유지되어야 함 expect(summary.tools.totalRequests).toBeLessThanOrEqual(1000); }, 30000); it('reset()으로 메트릭을 초기화할 수 있어야 함', async () => { context._metricsCollector = new MetricsCollector(); // Tool 실행 await executeTool('create_note', { title: 'Test', content: 'Test', category: 'Resources', }, context); let summary = context._metricsCollector.getSummary(); expect(summary.tools.totalRequests).toBe(1); // 초기화 context._metricsCollector.reset(); summary = context._metricsCollector.getSummary(); expect(summary.tools.totalRequests).toBe(0); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/inchan/memory-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server