콘텐츠로 이동

메트릭 및 모니터링

이 문서는 Continuum Router의 메트릭 및 모니터링 기능을 설명합니다.

목차

개요

Continuum Router는 시스템 상태, 성능, 사용 패턴을 다룰 수 있도록 Prometheus 호환 메트릭을 제공합니다. 메트릭 시스템은 다음과 같이 설계되었습니다:

  • 가벼움: 최소한의 성능 오버헤드
  • 넓은 범위: 라우터의 모든 중요한 측면 포함
  • 프로덕션 준비: 카디널리티 제한 및 적절한 레이블링 포함
  • 쉬운 통합: 표준 Prometheus/Grafana 설정과 작동

빠른 시작

1. 메트릭 활성화

메트릭은 기본적으로 활성화되어 있습니다. 메트릭 엔드포인트는 /metrics에서 사용할 수 있습니다:

# 메트릭 보기
curl http://localhost:8000/metrics

2. Prometheus 설정

prometheus.yml에 라우터를 타겟으로 추가:

scrape_configs:
    - job_name: 'continuum-router'
    static_configs:
      - targets: ['localhost:8000']
    scrape_interval: 15s

3. Grafana 대시보드 가져오기

monitoring/grafana/dashboards/router-overview.json에서 제공된 대시보드를 가져옵니다.

설정

메트릭 설정은 메인 설정 파일을 통해 수행됩니다:

metrics:
  # 메트릭 수집 활성화/비활성화
  enabled: true

  # 메트릭 엔드포인트 경로
  endpoint: "/metrics"

  # 메트릭 폭발을 방지하기 위한 카디널리티 제한
  cardinality_limit:
    max_labels_per_metric: 100
    max_unique_label_values: 1000

  # 선택적 메트릭 (성능을 위해 기본적으로 비활성화)
  optional_metrics:
    enable_request_body_size: false
    enable_response_body_size: false
    enable_detailed_errors: true

환경 변수

환경 변수를 사용하여 메트릭을 설정할 수도 있습니다:

# 메트릭 활성화/비활성화
METRICS_ENABLED=true

# 메트릭 엔드포인트 변경
METRICS_ENDPOINT=/custom/metrics

# 선택적 메트릭 활성화
METRICS_ENABLE_BODY_SIZE=true

사용 가능한 메트릭

HTTP 메트릭

메트릭 유형 설명 레이블
http_requests_total Counter 총 HTTP 요청 수 method, endpoint, status
http_request_duration_seconds Histogram 요청 지연 시간 method, endpoint
http_active_connections Gauge 현재 활성 연결 -
http_request_size_bytes Histogram 요청 본문 크기 method, endpoint
http_response_size_bytes Histogram 응답 본문 크기 method, endpoint

백엔드 메트릭

메트릭 유형 설명 레이블
backend_health_status Gauge 백엔드 헬스 (1=정상, 0=비정상) backend_id, backend_url
backend_health_check_duration_seconds Histogram 헬스 체크 지속 시간 backend_id
backend_health_check_failures_total Counter 총 헬스 체크 실패 backend_id, error_type
backend_request_latency_seconds Histogram 백엔드 요청 지연 시간 backend_id, endpoint
backend_connection_pool_size Gauge 연결 풀 크기 backend_id
backend_connection_pool_active Gauge 풀의 활성 연결 backend_id

라우팅 메트릭

메트릭 유형 설명 레이블
routing_decisions_total Counter 총 라우팅 결정 strategy, selected_backend
routing_backend_selection_duration_seconds Histogram 백엔드 선택 시간 strategy
routing_model_availability Gauge 백엔드별 모델 가용성 model, backend_id
routing_retries_total Counter 총 재시도 횟수 backend_id, reason
routing_circuit_breaker_state Gauge 서킷 브레이커 상태 backend_id

모델 서비스 메트릭

메트릭 유형 설명 레이블
model_cache_hits_total Counter 모델 캐시 적중 operation
model_cache_misses_total Counter 모델 캐시 미스 operation
model_refresh_duration_seconds Histogram 모델 목록 새로고침 지속 시간 backend_id
model_discovery_errors_total Counter 모델 검색 오류 backend_id, error_type

캐시 스탬피드 방지 메트릭

이 메트릭은 캐시 스탬피드 방지 메커니즘을 모니터링하는 데 도움이 됩니다:

메트릭 유형 설명 레이블
model_stale_while_revalidate_total Counter 갱신이 진행 중일 때 오래된 데이터를 반환한 요청 -
model_coalesced_requests_total Counter 새로운 집계를 트리거하는 대신 진행 중인 집계를 기다린 요청 -
model_background_refreshes_total Counter 시작된 백그라운드 갱신 작업 -
model_background_refresh_successes_total Counter 성공한 백그라운드 갱신 작업 -
model_background_refresh_failures_total Counter 실패한 백그라운드 갱신 작업 -
model_singleflight_lock_acquired_total Counter 싱글플라이트를 위해 집계 잠금이 획득된 횟수 -

캐시 스탬피드 메트릭 이해하기

  • 높은 coalesced_requests: 싱글플라이트 패턴이 중복 집계를 효과적으로 방지하고 있음을 나타냄
  • 높은 stale_while_revalidate: stale-while-revalidate 패턴이 갱신 중에 캐시된 데이터를 반환하고 있음을 보여줌
  • 낮은 background_refresh_failures: 백그라운드 갱신이 올바르게 작동하고 있음을 확인
  • 캐시 미스 시 블로킹 없음: background_refreshes > 0일 때, 요청은 캐시 갱신을 거의 기다리지 않아야 함

스트리밍 메트릭

메트릭 유형 설명 레이블
streaming_active_connections Gauge 활성 스트리밍 연결 endpoint
streaming_events_sent_total Counter 전송된 총 SSE 이벤트 endpoint, event_type
streaming_connection_duration_seconds Histogram 스트리밍 연결 지속 시간 endpoint
streaming_errors_total Counter 스트리밍 오류 endpoint, error_type

미드스트림 폴백 메트릭

미드스트림 폴백 기능이 활성화된 경우(streaming.mid_stream_fallback.enabled: true)에 방출되는 메트릭입니다.

메트릭 유형 설명 레이블
streaming_fallback_total Counter 미드스트림 폴백 시도 총 횟수 reason
streaming_fallback_success_total Counter 성공한 미드스트림 폴백 복구 original_backend, fallback_backend
streaming_fallback_accumulated_tokens Histogram 폴백 전까지 누적된 추정 토큰 수 outcome (success, failure)

streaming_fallback_total의 reason 레이블 값

설명
timeout 백엔드 비활성 타임아웃 초과
connection_error TCP/TLS 연결 오류
stream_read_error 스트림에서 바이트 읽기 오류
stream_ended_unexpectedly [DONE] 마커 없이 스트림 종료
too_many_stream_errors 연속 오류 이벤트 임계값 도달
other 기타 실패 원인

주요 PromQL 쿼리

# 미드스트림 폴백 비율
rate(streaming_fallback_total[5m])

# 폴백 복구 성공률
sum(rate(streaming_fallback_success_total[5m])) /
sum(rate(streaming_fallback_total[5m]))

# 폴백 트리거 시점의 누적 토큰 중앙값
histogram_quantile(0.5, rate(streaming_fallback_accumulated_tokens_bucket[5m]))

폴백 메트릭

메트릭 유형 설명 레이블
fallback_attempts_total Counter 총 폴백 시도 original_model, fallback_model, reason
fallback_success_total Counter 성공한 폴백 original_model, fallback_model
fallback_exhausted_total Counter 소진된 폴백 체인 original_model
fallback_cross_provider_total Counter 크로스 프로바이더 폴백 from_provider, to_provider
fallback_duration_seconds Histogram 폴백 작업 지속 시간 original_model

응답 캐시 메트릭

메트릭 유형 설명 레이블
continuum_response_cache_requests_total Counter 결과별 캐시 조회 result (hit, miss, skip)
continuum_response_cache_entries Gauge 현재 캐시된 항목 수 --
continuum_response_cache_size_bytes Gauge 대략적인 캐시 메모리 사용량 --
continuum_response_cache_evictions_total Counter LRU 퇴거 --
continuum_response_cache_hit_rate Gauge 롤링 캐시 적중률 (0.0--1.0) --
continuum_cache_backend_type Gauge 활성 캐시 백엔드 (1 = 활성) backend (memory, redis)

Redis 캐시 백엔드 메트릭

이 메트릭은 Redis 캐시 백엔드가 활성화된 경우(backend: redis) 수집됩니다.

메트릭 유형 설명 레이블
continuum_cache_redis_connections_active Gauge 풀의 활성 Redis 연결 --
continuum_cache_redis_connections_idle Gauge 풀의 유휴 Redis 연결 --
continuum_cache_redis_latency_seconds Histogram Redis 작업 지연 시간 operation (get, set, delete)
continuum_cache_redis_errors_total Counter 유형별 Redis 오류 type (connection, timeout, other)
continuum_cache_fallback_active Gauge 인메모리 폴백이 활성화되었는지 여부 (0 또는 1) --

KV 이벤트 컨슈머 메트릭

이 메트릭은 vLLM KV 이벤트 컨슈머가 활성화된 경우(src/infrastructure/kv_index/) 수집됩니다. 모든 백엔드 레이블 값은 카디널리티 폭발을 방지하기 위해 정규화됩니다.

메트릭 유형 설명 레이블
continuum_kv_event_received_total Counter 각 백엔드에서 수신된 KV 캐시 이벤트 backend
continuum_kv_event_processed_total Counter 채널을 통해 성공적으로 전달된 KV 캐시 이벤트 backend
continuum_kv_event_dropped_total Counter 백프레셔로 인해 삭제된 KV 캐시 이벤트 backend
continuum_kv_consumer_connected Gauge KV 이벤트 컨슈머 연결 여부 (1 = 연결됨, 0 = 연결 끊김) backend
continuum_kv_consumer_reconnects_total Counter 각 백엔드 컨슈머의 총 재연결 시도 횟수 backend

Prefix 라우팅 메트릭

이 메트릭은 접두사 인식 스티키 라우팅 결정 및 백엔드 분포를 추적합니다.

메트릭 유형 설명 레이블
continuum_prefix_routing_requests_total Counter 전략 유형별 총 접두사 라우팅 결정 strategy (prefix_hash, overflow, fallback, unknown)
continuum_prefix_routing_backend_distribution Gauge 백엔드별 인플라이트 요청 (로드 밸런싱용) backend
continuum_prefix_routing_prefix_cardinality Gauge 확인된 고유 접두사 키의 대략적인 수 --

주요 PromQL 쿼리

# 접두사 라우팅 적중률 (접두사 해시 사용 비율 vs 폴백)
sum(rate(continuum_prefix_routing_requests_total{strategy="prefix_hash"}[5m])) /
sum(rate(continuum_prefix_routing_requests_total[5m]))

# 오버플로율 (CHWBL 로드 밸런싱 활성화)
rate(continuum_prefix_routing_requests_total{strategy="overflow"}[5m])

# 백엔드 부하 분포 (대체로 균등해야 함)
continuum_prefix_routing_backend_distribution

KV 캐시 인덱스 메트릭

이 메트릭은 인덱스 상태, 쿼리 성능, 라우팅 결정 및 오버랩 스코어링을 포함한 KV 캐시 인덱스 서브시스템을 추적합니다.

메트릭 유형 설명 레이블
continuum_kv_index_entries Gauge KV 캐시 인덱스의 현재 항목 수 --
continuum_kv_index_events_total Counter KV 캐시 인덱스 변경 이벤트 (생성/퇴거) backend, type (created, evicted)
continuum_kv_index_query_latency_seconds Histogram KV 인덱스 쿼리 작업의 지연 시간 --
continuum_kv_index_routing_decisions_total Counter 결과별 KV 인식 라우팅 결정 decision (kv_aware, fallback)
continuum_kv_index_overlap_score Histogram 라우팅된 요청의 오버랩 점수 분포 --
continuum_kv_index_event_source_status Gauge 이벤트 소스 연결 상태 (1 = 연결됨, 0 = 연결 끊김) backend, status

주요 PromQL 쿼리

# KV 인식 라우팅 비율
sum(rate(continuum_kv_index_routing_decisions_total{decision="kv_aware"}[5m])) /
sum(rate(continuum_kv_index_routing_decisions_total[5m]))

# 라우팅된 요청의 평균 오버랩 점수
histogram_quantile(0.5, rate(continuum_kv_index_overlap_score_bucket[5m]))

# KV 인덱스 쿼리 P99 지연 시간
histogram_quantile(0.99, rate(continuum_kv_index_query_latency_seconds_bucket[5m]))

# 이벤트 소스 연결 상태
continuum_kv_index_event_source_status{status="connected"}

스마트 라우팅 메트릭

분류 및 라우팅 파이프라인 전체를 추적하는 메트릭입니다.

분류 및 라우팅

메트릭 유형 설명 레이블
smart_routing_classifications_total Counter 수행된 총 분류 횟수 complexity, domain, classifier_type
smart_routing_decisions_total Counter 내려진 총 라우팅 결정 수 source_model, target_model, policy, tier
smart_routing_classifier_duration_seconds Histogram 분류기 지연 시간 classifier_type
smart_routing_policy_no_match_total Counter 매칭 정책이 없는 요청 수 -
smart_routing_tier_no_model_total Counter 정책은 매칭됐으나 해당 티어에 모델이 없는 경우 tier

부하 관리

메트릭 유형 설명 레이블
smart_routing_load_state Gauge 현재 부하 상태: 0=Normal, 1=Warning, 2=Critical -
smart_routing_tier_degradation_total Counter 부하로 인한 티어 하향 횟수 load_state
smart_routing_load_transitions_total Counter 부하 상태 전환 횟수 from_state, to_state

LLM 분류기

메트릭 유형 설명 레이블
smart_routing_llm_classifier_calls_total Counter LLM 분류기 호출 총 횟수 -
smart_routing_llm_classifier_cache_hits_total Counter 캐시에서 반환된 분류 결과 수 -
smart_routing_llm_classifier_duration_seconds Histogram LLM 분류 전체 지연 시간 (버킷: 50ms~5s) -
smart_routing_llm_classifier_fallbacks_total Counter LLM 결과를 버리고 규칙 기반 결과를 사용한 횟수 -
smart_routing_llm_classifier_parse_errors_total Counter 재시도 전 응답 파싱 실패 횟수 -
smart_routing_llm_classifier_retries_total Counter 초기 파싱 실패 후 재시도 횟수 -

집계 및 운영

메트릭 유형 설명 레이블
smart_routing_requests_total Counter 스마트 라우팅된 요청 총 수 source_model, target_model, policy, load_state
smart_routing_tier_usage_total Counter 티어 사용 분포 tier, domain
smart_routing_cost_estimate_total Counter 티어 최적화로 절감된 예상 비용 tier
smart_routing_policy_evaluations_total Counter 정책 평가 빈도 policy_name, result
smart_routing_model_availability Gauge 티어별 사용 가능한 모델 수 model, tier

주요 PromQL 쿼리

# 정책별 스마트 라우팅 요청 속도
rate(smart_routing_requests_total[5m])

# 티어 사용 분포
sum by(tier) (rate(smart_routing_tier_usage_total[5m]))

# LLM 분류기 캐시 히트율
rate(smart_routing_llm_classifier_cache_hits_total[5m]) /
rate(smart_routing_llm_classifier_calls_total[5m])

# LLM 분류기 P95 지연 시간
histogram_quantile(0.95, rate(smart_routing_llm_classifier_duration_seconds_bucket[5m]))

# LLM 분류기 폴백 비율 (안정성 지표)
rate(smart_routing_llm_classifier_fallbacks_total[5m]) /
rate(smart_routing_llm_classifier_calls_total[5m])

# LLM 기반 분류 비율
rate(smart_routing_classifications_total{classifier_type="llm_based"}[5m]) /
rate(smart_routing_classifications_total[5m])

# 정책 평가 성공률
sum by(policy_name) (rate(smart_routing_policy_evaluations_total{result="matched"}[5m]))

비즈니스 메트릭

메트릭 유형 설명 레이블
model_usage_total Counter 모델 사용 횟수 model, backend_id
tokens_consumed_total Counter 소비된 총 토큰 model, operation

Guardrail Metrics

가드레일이 설정되고 metrics 기능이 활성화되면 내보내집니다. 모든 가드레일 결정이 기록되므로, 운영자는 enforce 전후로 정책이 무엇을 하는지(monitor 모드에서는 무엇을 할지)를 관찰할 수 있습니다.

메트릭 유형 설명 레이블
guardrail_checks_total Counter 단계·판정 결과별 프로바이더 검사 stage, provider, result
guardrail_blocks_total Counter 단계·프로바이더·카테고리별 차단 판정 stage, provider, category
guardrail_check_duration_seconds Histogram 프로바이더별 검사 지연(초) stage, provider
guardrail_errors_total Counter 프로바이더 오류(타임아웃 / 하드 실패) provider, kind
guardrail_fail_open_total Counter fail-open으로 해소된 프로바이더 실패(요청 허용) provider
guardrail_fail_closed_total Counter fail-closed로 해소된 프로바이더 실패(요청 차단) provider
guardrail_verdicts_total Counter 모드 의미를 적용한 후 요청당 집계 판정 stage, mode, result

레이블 값:

  • stageinput, output, streaming.
  • resultallow, block, transform, flag.
  • kindtimeout 또는 error.
  • modemonitor 또는 enforce. guardrail_verdicts_totalmode를 담으므로, 게이팅하지 않는 monitor 모드 판정도 보입니다. 이 점이 monitor 후 enforce 롤아웃을 관찰 가능하게 만듭니다.

주요 PromQL 쿼리

# 카테고리별로 무엇이 차단될지(monitor 모드 튜닝)
sum by (category) (rate(guardrail_blocks_total[1h]))

# enforce 후 단계별 차단율
sum by (stage) (rate(guardrail_verdicts_total{result="block", mode="enforce"}[5m]))

# 프로바이더 오류율(타임아웃 대 하드 실패)
sum by (provider, kind) (rate(guardrail_errors_total[5m]))

# 프로바이더별 P95 가드레일 검사 지연
histogram_quantile(0.95, sum by (le, provider) (rate(guardrail_check_duration_seconds_bucket[5m])))

전체 가드레일 가이드(개념, 프로바이더, 설정, 임계값 튜닝 워크플로)는 가드레일을 참고하세요.

API 키별 LLM 토큰 사용량

라우터는 LLM 토큰 소비를 API 키 단위로 쪼개어 노출합니다. 운영자는 '지난 1시간 동안 어느 키가 completion 토큰을 가장 많이 썼나', '오늘 X팀이 모델 Y에서 prompt 토큰을 얼마나 썼나'와 같은 질문에 바로 답할 수 있습니다. 기존의 집계 카운터(tokens_consumed_total)와 독립적인 별도 메트릭이고, 용량 산정과 공정 사용 정책, 추후의 비용 귀속 산정에 쓰입니다.

메트릭 정의

메트릭 유형 설명 레이블
llm_tokens_total Counter 요청당 소비된 LLM 토큰 수 api_key_id, model, backend, kind
api_key_info Gauge (상수 1) 설정된 API 키 어노테이션을 레이블로 노출하는 정보 메트릭 api_key_id + 어노테이션 허용 목록

kind 값은 다음 두 가지입니다:

  • prompt — 업스트림 요청 프롬프트의 토큰 수
  • completion — 업스트림 응답 completion의 토큰 수

OpenAI 호환(prompt_tokens / completion_tokens) 응답과 Anthropic(input_tokens / output_tokens) 응답 모두 동일한 카운터로 정규화됩니다. 라우터는 OpenAI 호환 스트리밍 요청에 stream_options.include_usage=true를 자동 주입하므로, 클라이언트 동작과 무관하게 마지막 SSE 청크에서 사용량 정보를 받습니다.

api_key_id 도출 규칙

api_key_id는 원본 API 키가 노출되지 않도록, 라우터가 안정적이면서 역방향 복원이 불가능한 식별자를 다음 우선순위로 만들어 사용합니다:

  1. 요청의 bearer 토큰이 설정된 API 키 항목과 일치하면 해당 항목의 id 필드를 씁니다(예: key-production-1).
  2. 일치하지 않으면 원본 토큰의 SHA-256 해시 앞 12자에 k_ 접두어를 붙입니다(예: k_3f5a7c9b1e2d).
  3. 토큰이 아예 없으면 anonymous 리터럴이 들어갑니다.

모든 레이블 값은 기존 CardinalityManager를 거치므로, 토큰을 무작위로 갈아끼우는 공격이 들어와도 Prometheus 시리즈가 폭발하지 않습니다.

어노테이션 레이블과 api_key_info

각 API 키 항목에는 자유로운 annotations: { key: value } 맵을 달 수 있고, 운영자는 그중 어떤 키를 Prometheus 레이블로 승격할지 metrics.annotation_labels 허용 목록으로 명시합니다. 허용 목록에 없는 어노테이션은 내부 데이터로만 남습니다.

설정 스키마(기존 api_keys 블록 안):

api_keys:
  api_keys:
      - key: "${API_KEY_1}"
        id: "key-production-1"
        user_id: "user-admin"
        organization_id: "org-main"
        annotations:
            email: "ops@example.com"
            team: "platform"
            environment: "prod"
            owner: "alice"

metrics:
    enabled: true
    annotation_labels: [email, team]            # 레이블 키 허용 목록

권장 표준 어노테이션 키는 email, uuid, owner, team, environment인데, 강제는 아니고 운영자가 자체 키를 추가해도 됩니다.

metrics.annotation_labels가 비어 있지 않으면 라우터는 등록된 키마다 api_key_info{api_key_id, email, team, ...} = 1을 한 번씩 발행합니다. 이 정보 메트릭을 PromQL 조인으로 llm_tokens_total에 투영하면 카운터의 레이블 집합을 키우지 않고도 메타데이터로 필터링·그룹핑할 수 있습니다:

# 이메일별 토큰 소비량 (지난 24시간, prompt + completion 합산)
sum by (email) (
  increase(llm_tokens_total[24h])
  * on (api_key_id) group_left(email) api_key_info
)

카디널리티와 핫 리로드

  • api_key_id 카디널리티는 기본 1,000개로 제한됩니다.
  • API 키 어노테이션은 기존 설정 리로드 파이프라인을 통해 핫 리로드되고, api_key_info 정보 메트릭은 리로드마다 원자적으로 다시 발행됩니다. llm_tokens_total 카운터 값은 리셋되지 않습니다.
  • 단, api_key_info레이블 집합 (즉 annotation_labels 항목들)은 시작 시점에 고정됩니다. 허용 목록에서 키를 추가하거나 빼려면 재시작이 필요한데, Prometheus가 등록된 메트릭의 레이블 이름 변경을 허용하지 않기 때문입니다.

PromQL 예제

# 지난 1시간 동안 API 키별 prompt 토큰 합계
sum by (api_key_id) (
  increase(llm_tokens_total{kind="prompt"}[1h])
)
# 지난 24시간 동안 completion 토큰 상위 10개 키
topk(10,
  sum by (api_key_id) (
    increase(llm_tokens_total{kind="completion"}[24h])
  )
)
# 팀별 토큰 사용량 (annotation_labels에 team이 포함되어 있어야 함)
sum by (team) (
  increase(llm_tokens_total[24h])
  * on (api_key_id) group_left(team) api_key_info
)
# 모델별 prompt+completion 합산 속도 (토큰/초)
sum by (model) (rate(llm_tokens_total[5m]))
# 백엔드별·키별 소비량 (비용 귀속 산정용)
sum by (api_key_id, backend) (
  increase(llm_tokens_total[24h])
)

Grafana 패널 예제

지난 24시간 동안 completion 토큰 상위 10개 팀을 보여주는 stat 패널:

{
    "title": "Top 10 teams by completion tokens (24h)",
    "type": "stat",
    "targets": [
        {
            "expr": "topk(10, sum by (team) (increase(llm_tokens_total{kind=\"completion\"}[24h]) * on (api_key_id) group_left(team) api_key_info))",
            "legendFormat": "{{team}}"
        }
    ],
    "options": {
        "reduceOptions": {
            "values": false,
            "calcs": ["lastNotNull"]
        }
    }
}

지출 추이를 따라가려면 rate(llm_tokens_total[5m])team이나 model로 그룹화한 시계열 패널과 함께 쓰면 됩니다.

검증 절차

기능을 활성화한 뒤 다음 순서로 동작을 확인합니다:

  1. 설정된 API 키로 chat-completion 요청을 한 번 보냅니다.
  2. /metrics를 스크랩해서 llm_tokens_total{...}api_key_info{...} 시리즈가 노출되는지 확인합니다.
  3. 스트리밍의 경우에도 카운터가 증가하는지 봅니다. 사용량은 마지막 SSE 청크에서 잡고, 라우터가 OpenAI 호환 백엔드에는 stream_options.include_usage=true를 자동 주입하므로 클라이언트 동작과 무관하게 동작합니다.
  4. 일상적인 워크로드에서 /metrics의 카디널리티(예: wc -l < /metrics)를 측정해, 도입 전 베이스라인 대비 회귀가 없는지 확인합니다.

통합

Prometheus 설정

완전한 Prometheus 설정 예제:

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
    - job_name: 'continuum-router'
    static_configs:
      - targets: ['router1:8000', 'router2:8000']
    metric_relabel_configs:
      # 필요시 높은 카디널리티 메트릭 삭제
      - source_labels: [__name__]
        regex: 'http_request_duration_seconds_bucket'
        action: drop

Kubernetes 통합

Kubernetes 배포의 경우 ServiceMonitor 사용:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: continuum-router
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: continuum-router
  endpoints:
    - port: metrics
    interval: 15s
    path: /metrics

Grafana 대시보드

제공된 Grafana 대시보드는 다음을 포함합니다:

개요 패널

  • 요청 속도 및 오류율
  • P50, P95, P99 지연 시간
  • 활성 연결
  • 백엔드 헬스 상태

백엔드 성능

  • 백엔드별 지연 시간
  • 헬스 체크 성공률
  • 연결 풀 활용률
  • 서킷 브레이커 상태

모델 사용

  • 모델 요청 분포
  • 캐시 적중률
  • 토큰 소비
  • 모델 가용성 매트릭스

알림 개요

  • 활성 알림
  • 알림 기록
  • SLO 준수

대시보드 가져오기:

  1. Grafana 열기
  2. 대시보드 -> 가져오기로 이동
  3. monitoring/grafana/dashboards/router-overview.json 업로드
  4. Prometheus 데이터 소스 선택
  5. 가져오기 클릭

알림

사전 설정된 알림 규칙이 monitoring/prometheus/alerts.yml에 있습니다:

중요 알림

{% raw %}

- alert: BackendDown
  expr: backend_health_status == 0
  for: 1m
  annotations:
    summary: "백엔드 {{ $labels.backend_id }}이(가) 다운됨"

- alert: HighErrorRate
  expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05
  for: 5m
  annotations:
    summary: "높은 오류율: {{ $value | humanizePercentage }}"

경고 알림

{% raw %}

- alert: HighLatency
  expr: histogram_quantile(0.95, http_request_duration_seconds) > 1
  for: 5m
  annotations:
    summary: "P95 지연 시간 1초 초과: {{ $value | humanizeDuration }}"

- alert: LowCacheHitRate
  expr: rate(model_cache_hits_total[5m]) / rate(model_cache_total[5m]) < 0.8
  for: 10m
  annotations:
    summary: "캐시 적중률 80% 미만: {{ $value | humanizePercentage }}"

예제

쿼리 예제

상태별 요청 속도

sum(rate(http_requests_total[5m])) by (status)

엔드포인트별 P95 지연 시간

histogram_quantile(0.95,
  sum(rate(http_request_duration_seconds_bucket[5m])) by (endpoint, le)
)

백엔드 헬스 개요

sum(backend_health_status) by (backend_id)

모델 사용량 순위

topk(10, sum(rate(model_usage_total[1h])) by (model))

오류율 백분율

sum(rate(http_requests_total{status=~"5.."}[5m])) /
sum(rate(http_requests_total[5m])) * 100

프로그래밍 방식 접근

메트릭에 프로그래밍 방식으로 접근할 수도 있습니다:

import requests
from prometheus_client.parser import text_string_to_metric_families

# 메트릭 가져오기
response = requests.get('http://localhost:8000/metrics')
metrics = text_string_to_metric_families(response.text)

# 메트릭 처리
for family in metrics:
    for sample in family.samples:
        if sample.name == 'http_requests_total':
            print(f"엔드포인트: {sample.labels['endpoint']}, 카운트: {sample.value}")

사용자 정의 메트릭 수집

#!/bin/bash
# 30초마다 메트릭을 수집하고 파일에 저장

while true; do
  timestamp=$(date +%s)
  curl -s http://localhost:8000/metrics > "metrics_${timestamp}.txt"
  sleep 30
done

모범 사례

1. 레이블 카디널리티

메트릭 폭발을 방지하기 위해 레이블 카디널리티를 낮게 유지:

# 좋음: 낮은 카디널리티
labels:
  status: "200"  # ~5개 가능한 값
  method: "GET"  # ~7개 가능한 값

# 나쁨: 높은 카디널리티
labels:
  user_id: "12345"  # 무제한
  request_id: "abc-123"  # 요청당 고유

2. 메트릭 명명

Prometheus 명명 규칙 준수:

  • snake_case 사용
  • 메트릭 이름에 단위 포함 (_seconds, _bytes, _total)
  • 표준 접두사 사용 (http_, backend_, model_)

3. 대시보드 설계

  • 관련 메트릭을 함께 그룹화
  • 적절한 시각화 유형 사용 (현재 값에는 게이지, 시계열에는 그래프)
  • 절대값과 비율 모두 포함
  • 적절한 새로고침 간격 설정 (실시간에는 15-30초, 이력에는 1-5분)

4. 알림 설정

  • 플래핑을 방지하기 위해 적절한 평가 기간 사용 (for: 5m)
  • 알림 설명에 컨텍스트 포함
  • 심각도에 따른 알림 라우팅 설정
  • 프로덕션 전 스테이징에서 알림 테스트

5. 성능 고려 사항

  • 필요하지 않은 경우 선택적 메트릭 비활성화
  • 복잡한 쿼리에 레코딩 규칙 사용
  • 적절한 메트릭 보존 정책 구현
  • 장기 보존을 위해 원격 스토리지 고려

6. 보안

  • 민감한 데이터가 노출된 경우 메트릭 엔드포인트 보호
  • 프로덕션에서 Prometheus 스크래핑에 TLS 사용
  • Grafana 대시보드에 인증 구현
  • 메트릭 접근 로그 감사

문제 해결

메트릭이 나타나지 않음

  1. 설정에서 메트릭이 활성화되어 있는지 확인
  2. 메트릭 엔드포인트에 접근 가능한지 확인
  3. Prometheus 타겟 상태 확인
  4. 메트릭 초기화 오류에 대한 라우터 로그 검토

높은 메모리 사용량

  1. 카디널리티 제한 검토
  2. 무제한 레이블 확인
  3. 필요시 히스토그램 버킷 감소
  4. 메트릭 만료 활성화

잘못된 값

  1. 메트릭 유형 확인 (카운터 vs 게이지)
  2. 집계 함수 확인
  3. 레이블 선택기 검토
  4. 시간 범위 검증

추가 리소스