Skip to content

Meter

Meter는 모든 MCP 호출을 7개 계층으로 자동 분류하고 호출량, 지연시간, 성공률을 추적합니다. @airmcp-dev/core에 포함되어 있으며 별도 설치가 필요 없습니다.

Meter 활성화

typescript
defineServer({
  meter: { classify: true, trackCalls: true },
});

Meter는 기본 활성입니다 (meter.enabled의 기본값은 true). defineServer 호출 시 자동으로 meter 미들웨어가 체인에 등록됩니다.

7계층 자동 분류

Meter는 도구 이름 패턴을 기반으로 호출을 자동 분류합니다:

계층매칭 패턴설명
L1ping, health, version, echo정적 응답, 비용 거의 없음
L2get, read, find, lookup, list, show단순 조회
L3convert, transform, format, parse, encode, decode데이터 변환
L4compute, calculate, aggregate, analyze, summarize집계/계산 (기본값)
L5fetch, request, call_api, webhook, http, post, put, delete외부 API 호출
L6generate, complete, chat, embed, infer, predictLLM 호출
L7agent, think, plan, execute, reason, chain, orchestrate에이전트 체인

L5는 도구 이름 외에도 파라미터 값에 http:// 또는 https://가 포함되면 자동 매칭됩니다.

매칭되지 않는 도구는 L4(기본값)로 분류됩니다.

수동 분류

defineToollayer 속성으로 자동 분류를 오버라이드합니다:

typescript
defineTool('my-cache', {
  layer: 1,   // L1로 강제 분류 (이름이 cache라서 자동 분류 안 됨)
  handler: async ({ key }) => cache.get(key),
});

defineTool('custom-llm-call', {
  layer: 6,   // L6으로 강제
  handler: async ({ prompt }) => callMyLLM(prompt),
});

MeterConfig

typescript
interface MeterConfig {
  enabled?: boolean;        // 기본: true
  classify?: boolean;       // 7계층 분류 활성화 (기본: true)
  trackCalls?: boolean;     // 호출 추적 (기본: true)
  trackTokens?: boolean;    // 토큰 사용 추적 (기본: false)
  budget?: {
    dailyLimit?: number;
    monthlyLimit?: number;
    maxTokensPerCall?: number;
    onExceed?: 'warn' | 'block';
  };
}

메트릭 조회

typescript
import { getMetricsSnapshot, resetMetricsHistory } from '@airmcp-dev/core';

const snapshot = getMetricsSnapshot();
// {
//   totalCalls: 1500,
//   successRate: 0.98,              // 성공률 (0~1)
//   avgLatencyMs: 45.2,             // 평균 지연시간
//   layerDistribution: {
//     L1: 200, L2: 400, L3: 100, L4: 300,
//     L5: 250, L6: 200, L7: 50,
//   },
//   toolCounts: {
//     search: 500,
//     greet: 300,
//     fetch: 250,
//     // ...
//   },
// }

resetMetricsHistory();  // 모든 메트릭 초기화

반환값 상세

필드타입설명
totalCallsnumber총 호출 수
successRatenumber성공률 (0~1, 에러 미포함)
avgLatencyMsnumber전체 평균 지연시간 (ms)
layerDistributionRecord<Layer, number>계층별 호출 수
toolCountsRecord<string, number>도구별 호출 수

내부 저장소

Meter는 Ring Buffer (최대 10,000건)로 호출 기록을 저장합니다. O(1) push, 가장 오래된 기록이 자동 삭제됩니다. 메모리 사용량이 일정합니다.

typescript
// 각 호출 기록
interface CallRecord {
  tool: string;        // 도구 이름
  layer: Layer;        // 분류된 계층
  latencyMs: number;   // 지연시간
  success: boolean;    // 성공 여부
  timestamp: number;   // 타임스탬프
}

에러 시 동작

도구 호출이 실패해도 Meter는 기록합니다 (success: false). Meter 자체는 에러를 처리하지 않고 다음 미들웨어로 전달합니다.

실전 활용

계층별 모니터링

typescript
const snapshot = getMetricsSnapshot();

// L6/L7 비율이 높으면 토큰 비용 주의
const heavyRatio = (snapshot.layerDistribution.L6 + snapshot.layerDistribution.L7) / snapshot.totalCalls;
if (heavyRatio > 0.3) {
  console.warn(`Heavy call ratio: ${(heavyRatio * 100).toFixed(1)}%`);
}

주기적 리포트

typescript
setInterval(() => {
  const s = getMetricsSnapshot();
  console.log(JSON.stringify({
    totalCalls: s.totalCalls,
    successRate: s.successRate,
    avgLatencyMs: s.avgLatencyMs,
    layers: s.layerDistribution,
  }));
}, 60_000);  // 1분마다

Released under the Apache-2.0 License.