콘텐츠로 이동

메트릭 및 모니터링

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

목차

개요

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

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

메트릭은 얼마나 많이, 얼마나 자주를 답합니다. 요청 하나의 인과관계, 즉 어떤 백엔드가 선택됐고 몇 번 시도했으며 각 시도가 왜 그렇게 끝났는지를 보려면 분산 트레이스 내보내기를 참고하세요. 라우터의 스팬을 OTLP로 OpenTelemetry 컬렉터에 보내는 기능입니다.

빠른 시작

1. 메트릭 활성화

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

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

2. Prometheus 설정

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

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

3. Grafana 대시보드 가져오기

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

설정

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

metrics:
  enabled: true
  port: 9090
  path: /metrics
  max_model_labels: 1000
  max_backend_labels: 100
  cardinality_limits:
    max_models: 1000
    max_endpoints: 100
    max_error_types: 100
    enable_sampling: false
    sampling_rate: 1.0
  # 이 프로필에서는 외부 Prometheus가 영속 저장소입니다.
  persistence:
    enabled: false

환경 변수

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

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

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

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

사용 가능한 메트릭

HTTP 메트릭

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

백엔드 선택은 핸들러 내부에서 수행되고 모든 라우트가 백엔드를 선택하는 것은 아니므로 HTTP 미들웨어는 backend="unknown"으로 보고합니다. 백엔드별 트래픽과 부하는 백엔드 및 prefix-routing 메트릭 패밀리에서 확인할 수 있으며, 클라이언트가 제공한 헤더는 메트릭 귀속에 신뢰하지 않습니다.

오류 및 재시도 메트릭

메트릭 유형 설명 레이블
errors_total Counter 요청 미들웨어가 관찰한 HTTP 클라이언트/서버 오류 error_type, backend
retry_attempts_total Counter 최초 시도 이후의 백엔드 재시도 backend, attempt_number
retry_success_total Counter 재시도에서 성공한 요청 backend
retry_exhausted_total Counter 한 번 이상 백엔드를 재시도한 뒤 실패한 요청 backend
timeout_errors_total Counter 최종 백엔드 또는 요청 타임아웃 응답 operation, backend

서킷 브레이커 메트릭

metrics 기능과 circuit_breaker가 모두 활성화되면 일반 프록시 트래픽이 채웁니다.

메트릭 유형 설명 레이블
circuit_breaker_state Gauge 현재 백엔드별 서킷 상태(0 Closed, 1 Open, 2 HalfOpen) backend
circuit_breaker_failures_total Counter 백엔드 서킷에 기록된 실패 backend, error_type
circuit_breaker_successes_total Counter 백엔드 서킷에 기록된 성공 backend
circuit_breaker_transitions_total Counter 서킷 상태 전환 backend, from_state, to_state

요청 파라미터 정책 메트릭

메트릭 유형 설명 레이블
request_param_policy_total Counter 적용된 파라미터 동작과 거부된 정책 결정 protocol, parameter, action, outcome
request_param_policy_composition_total Counter 로컬 정책과 Hub 정책의 조합 protocol, source, outcome

두 메트릭 패밀리는 닫혀 있고 상한이 정해진 레이블만 사용합니다. sourcenone, local, hub, intersection 중 하나이며 요청 값, 모델 id, 티어 id, 키 id, 정책 cursor는 어느 쪽에도 내보내지 않습니다.

백엔드 메트릭

메트릭 유형 설명 레이블
backend_healthy Gauge 백엔드 헬스(1=정상, 0=정상 아님), URL 레이블은 마스킹됨 backend, url
backend_health_check_duration_seconds Histogram 능동 헬스 체크 지속 시간 backend
backend_health_check_failures_total Counter 실패한 능동 헬스 체크 backend
backend_current_load Gauge 백엔드에 디스패치된 실시간 진행 중 요청 backend
backend_weight Gauge 설정된 부하 분산 가중치 backend

엔진 통계 메트릭

engine_stats.enabled: true일 때만, 그리고 엔진 통계를 지원하는 백엔드 유형(vllm, sglang, llamacpp, mlxcel, ollama, lmstudio)에 대해서만 노출된다. 폴러는 각 엔진 자체의 부하 또는 메트릭 엔드포인트(vLLM GET /metrics, SGLang GET /v1/loads/get_load·/metrics 폴백, llama.cpp는 /props의 기능 불리언으로 GET /slots·GET /metrics 선택, Ollama GET /api/ps, LM Studio GET /api/v0/models)를 읽어 백엔드당 하나의 스냅샷으로 정규화한다.

메트릭 유형 설명 레이블
backend_engine_requests_running Gauge 엔진이 실행 중이라고 보고한 요청 수 backend
backend_engine_requests_waiting Gauge 엔진이 대기 중이라고 보고한 요청 수 backend
backend_engine_kv_cache_usage_ratio Gauge 엔진 KV 캐시 사용률(0..1) backend
backend_engine_kv_tokens_capacity Gauge 엔진 KV 캐시 토큰 용량 backend
backend_engine_generation_tokens_per_second Gauge 엔진이 보고한 생성 처리량 backend
backend_engine_prefix_cache_hit_ratio Gauge 엔진 프리픽스 캐시 적중률(0..1) backend
backend_engine_context_length Gauge 단일 요청이 쓸 수 있는 최대 컨텍스트(llama.cpp는 슬롯당 값) backend
backend_engine_slots_total Gauge 엔진이 알리는 병렬 처리 슬롯 수 backend
backend_engine_stats_scrape_success Gauge 최근 엔진 스크레이프 성공(1)/실패(0) backend
backend_engine_stats_scrape_duration_seconds Gauge 최근 엔진 스크레이프 소요 시간 backend
backend_engine_stats_age_seconds Gauge 라우터 스크레이프 시점의 스냅샷 나이 backend
backend_engine_prompt_tokens_total Counter 엔진이 처리한 프롬프트 토큰(리셋 감지로 미러링) backend
backend_engine_generation_tokens_total Counter 엔진이 생성한 토큰(리셋 감지로 미러링) backend

시리즈의 정직성은 세 가지 표현 규칙이 지킨다.

  • 0이 아니라 부재. 엔진에 해당 개념이 없는 값의 시리즈는 아예 노출하지 않으며, 이는 어댑터별로 정적으로 결정한다. 유일한 예외는 SGLang /v1/loads다. 이 와이어 포맷은 0 값 필드를 생략하므로(msgspec omit_defaults), 어댑터는 누락된 숫자를 진실한 0으로 읽는다. 덕분에 유휴 SGLang 백엔드도 backend_engine_requests_running 0을 계속 보고한다.
  • 실패한 스크레이프는 한 가지만 말한다. 스크레이프 오류가 나면 해당 백엔드는 backend_engine_stats_scrape_success 0만 노출하고, 성공할 때까지 나머지 시리즈는 사라진다. 고장난 스크레이프가 유휴 엔진으로 읽히는 일을 막기 위함이다. 마지막 스냅샷은 내부에 유지되며 Admin API에서 staleness_seconds가 커지는 형태로 보인다.
  • 멀티 랭크 집계. SGLang 데이터 병렬 엔진은 DP 랭크마다 항목을 하나씩 보고한다. 랭크는 개수·용량·처리량을 합산하고 사용률·적중률은 최댓값을 취해 하나의 스냅샷으로 합친다(포화된 랭크가 중요한 랭크다). Prometheus 본문에 한 시리즈의 레이블 세트가 여러 개일 때도 같은 규칙을 적용한다.

*_tokens_total 카운터는 리셋 감지를 적용한다(직전 관측값보다 낮은 엔진 값은 재시작으로 간주하고 새 값을 재시작 이후 증가분으로 반영). 리셋 감지는 엔진이 카운터로 선언한 시리즈에만 적용한다. llama.cpp의 /metrics는 카운터와 게이지를 섞어 내보내며, 게이지는 정상적으로 감소할 수 있다.

핫 리로드로 제거된 백엔드의 backend_engine_* 시리즈는 다음 스크레이프에서 사라지고, 추가된 백엔드는 한 폴링 주기 안에 보고를 시작한다. 설정 표면은 config.yaml.exampleengine_stats를, JSON 스냅샷은 GET /admin/backends/{name}/engine-stats를 참고한다.

서빙 엔진은 라우터와 무관하게 버그가 있거나 침해될 수 있으므로, 엔진의 응답은 신뢰할 수 없는 입력으로 다룬다.

  • 제한된 도달 범위. 폴러는 설정된 백엔드 URL, 또는 그와 같은 호스트로 해석되는 metrics_url만 가져오며 리다이렉트를 따르지 않는다. 동일 호스트 규칙은 설정 로드 시점과 매 요청 직전에 두 번 검사하고, 백엔드 URL이 파싱되지 않으면 거부 쪽으로 닫힌다. 메트릭 요청에는 백엔드 API 키가 함께 나가므로 metrics_urlhttps 백엔드를 평문 http로 낮출 수 없다. allow_external_metrics_url은 호스트 규칙만 완화할 뿐 이 규칙은 해제하지 않는다.
  • 본문은 로그에 남지 않는다. 파싱 실패는 구조적 분류와 위치만 보고하고 문제가 된 값은 보고하지 않는다. 따라서 스크레이프 실패를 통해 엔진 본문의 일부(특히 llama.cpp /slots 본문)가 라우터 로그로 새어 나갈 수 없다. 전송 실패는 자격 증명이 제거된 URL만 보고한다.
  • 입력량 제한. 응답은 max_body_bytes 기준으로 청크 단위로 읽고, Prometheus 파서는 본문당 샘플 수와 샘플당 레이블 수를 제한하며, 스냅샷이 보관하는 유일한 엔진 자유 텍스트(모델 이름과 엔진 버전)는 길이를 제한하고 보이지 않는 제어 문자를 제거한다. 숫자 집계는 오버플로 대신 포화한다.

모델 서비스 메트릭

메트릭 유형 설명 레이블
model_cache_size Gauge 집계 캐시의 모델 수
model_cache_hits_total Counter 모델 집계 캐시 적중
model_cache_misses_total Counter 모델 집계 캐시 미스
model_refresh_failures_total Counter 실패한 백엔드 모델 조회
model_refresh_duration_seconds Histogram 모델 목록 집계 1회 전체 소요 시간
model_backend_fetch_duration_seconds Histogram 백엔드 1개의 모델 조회 소요 시간 backend
model_last_refresh_duration_seconds Gauge 가장 최근 집계의 소요 시간
model_fetch_attempts_total Counter 재시도를 포함한 백엔드 모델 조회 시도 수
model_empty_responses_total Counter 빈 모델 목록을 만든 갱신 수
model_backends_unavailable_total Counter 어떤 백엔드도 모델을 반환하지 않은 갱신 수
model_rate_limit_exceeded_total Counter 속도 제한으로 거부된 모델 엔드포인트 요청 수
model_transient_errors_total Counter 재시도 가능한 백엔드별 조회 실패
model_permanent_errors_total Counter 재시도 불가능한 백엔드별 조회 실패
model_stale_while_revalidate_total Counter 갱신 중 스테일 캐시로 응답한 요청 수
model_coalesced_requests_total Counter 진행 중인 집계에 합쳐진 요청 수
model_background_refreshes_total Counter 백그라운드 재검증이 시작한 백엔드 팬아웃 수(집계 패스마다 1). 진행 중 대체된 패스(issue #1548)는 같은 자리에서 재시도되며 재시도마다 다시 세므로 팬아웃 수를 유지하고, model_background_refresh_successes_totalmodel_background_refresh_failures_total은 재검증마다 1씩 증가함 (issue #1552)
model_background_refresh_successes_total Counter 결과를 저장하고 끝난 백그라운드 재검증 수(패스 수와 무관하게 재검증마다 1)
model_background_refresh_failures_total Counter 실패한 백그라운드 재검증 수(재검증마다 1)
model_singleflight_lock_acquired_total Counter 싱글플라이트용 집계 잠금 획득 수
model_superseded_aggregations_total Counter 팬아웃 도중 풀 멤버십이나 캐시 무효화 epoch가 바뀌어 fresh 대신 만료 상태로 저장된 갱신 수 (issue #1548). 저장 후 재확인에서 잡힌 멤버십 변경(issue #1552)도 포함. 각 건은 즉시 재집계로 이어지되, 세 번 연속 대체된 뒤에는 다음 재검증이 2초의 재가동 간격을 기다림

느린 모델 목록 진단

model_refresh_duration_seconds는 집계가 느렸다는 사실을 알려주고, model_backend_fetch_duration_seconds는 어느 백엔드 때문에 느렸는지 알려줍니다. 모델 목록 팬아웃은 동시에 실행되므로 전체 소요 시간은 가장 느린 백엔드 하나와 같습니다.

# 5분 구간에서 갱신을 지배하는 백엔드, 95 백분위수
histogram_quantile(0.95, sum by (backend, le) (rate(model_backend_fetch_duration_seconds_bucket[5m])))

두 히스토그램 모두 버킷이 60초까지 있습니다. 시도별 request_timeout을 초과한 백엔드는 이름, 소요 시간, 시도 횟수를 담은 WARN 로그를 한 줄 남기므로, Prometheus 없이도 그리고 전역 로그 수준을 DEBUG로 올리지 않고도 같은 사실을 확인할 수 있습니다.

WARN Slow model fetch from backend backend="claude-bedrock" duration_ms=15503 attempts=3 threshold_ms=5000 outcome="error"

model_backend_fetch_duration_seconds는 백엔드 이름당 시계열 1개를 가집니다. 백엔드 이름은 운영자가 정의하고 설정으로 한정되므로 카디널리티는 보통 작습니다. 백엔드를 동적으로 등록하는 배포(AppProxy 레플리카)에서는 서로 다른 레플리카 이름마다 시계열 1개가 생긴다고 예상해야 합니다.

라우팅 텔레메트리는 아래의 실제 KV 캐시스마트 라우팅 메트릭 패밀리에서 내보냅니다. 기존 범용 라우팅 및 모델 서비스 collector 중 지원되지 않는 항목은 등록하지 않습니다.

활성 스트리밍 응답 본문은 http_active_connections에 포함됩니다. 현재 범용 스트리밍 지속 시간 또는 응답 이후 오류 메트릭은 내보내지 않으며, 미드스트림 폴백에는 아래의 전용 실제 메트릭이 있습니다.

미드스트림 폴백 메트릭

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

메트릭 유형 설명 레이블
streaming_fallback_total Counter 스트리밍 폴백 시도 총 횟수. mid-stream 경로가 SSE 응답 확정 전에 수행한 pre-stream 홉도 포함합니다 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]))

Responses 우회 메트릭

라우터가 /v1/chat/completions 요청을 업스트림 /v1/responses로 대신 보낸 횟수를 셉니다. 항상 등록되며, 우회가 없으면 카운터가 0에 머뭅니다.

메트릭 유형 설명 레이블
responses_bridge_total Counter /v1/responses로 보낸 Chat Completions 요청 수 reason

responses_bridge_total의 reason 레이블 값

설명
responses_only_model 모델 메타데이터에 responses_only가 설정되어 있거나, 백엔드가 Responses API만 제공합니다(Codex/ChatGPT 구독 백엔드). 해당 모델의 모든 요청이 우회됩니다.
tools_with_reasoning 모델은 Chat Completions로 제공되며, 비어 있지 않은 tools 배열과 업스트림이 거절하는 reasoning effort가 함께 온 이 요청 형태만 우회됩니다. Reasoning Effort 문서의 "함수 도구와 reasoning effort 조합" 절을 참고하세요.

두 값은 운영상 의미가 다릅니다. responses_only_model은 배포 구성 자체의 성질이며 해당 모델로 가는 트래픽에 비례합니다. tools_with_reasoning은 트래픽의 성질입니다. 에이전트 트래픽 중 얼마나 많은 비율이 변환 왕복 비용을 치르고 있는지 알려주며, OpenAI가 제약을 풀고 메타데이터 플래그를 끄면 저절로 0으로 떨어집니다.

# 우회된 트래픽 중 조건부 tools 우회가 차지하는 비율
sum(rate(responses_bridge_total{reason="tools_with_reasoning"}[5m])) /
sum(rate(responses_bridge_total[5m]))

모델 실험 메트릭

모델 실험의 변형별 귀속 메트릭입니다. 전용 계열이므로 기존 요청, 지연 시간, 토큰 시계열의 레이블 집합은 그대로입니다. 레이블 값은 model_experiments 설정(실험 최대 32개, 실험당 변형 최대 16개)이나 닫힌 집합에서 옵니다.

메트릭 유형 설명 레이블
model_experiment_requests_total Counter 실험으로 해석된 요청 수 experiment, variant, status(success, client_error, server_error), assignment(sticky, random)
model_experiment_request_duration_seconds Histogram 응답 헤더까지의 시간 experiment, variant
model_experiment_tokens_total Counter prompt 및 completion 토큰 experiment, variant, kind
model_experiment_fallbacks_total Counter 모델 간 폴백 홉이 응답한 요청 수(fallback: cross_variant) experiment, variant
model_experiment_reserved_refusals_total Counter hide_variant_models 실험이 예약한 변형 모델을 지정해 거부된 요청 수 experiment

폴백 메트릭

메트릭 유형 설명 레이블
fallback_attempts_total Counter 총 폴백 시도 original_model, fallback_model, backend
fallback_success_total Counter 성공한 폴백 original_model, fallback_model, backend
fallback_exhausted_total Counter 소진된 폴백 체인 original_model
cross_provider_fallback_total Counter 크로스 프로바이더 폴백 original_model, fallback_model, original_provider, fallback_provider
fallback_duration_seconds Histogram 폴백 작업 지속 시간 original_model, success
fallback_dial_bound_saturated_total Counter 백엔드별 다이얼 상한 (fallback.fallback_policy.max_concurrent_dials_per_backend)에서 대기 상한이 만료될 때까지 기다리다 해당 백엔드에 대한 홉이 실패한 폴백 홉 다이얼 수 backend

응답 캐시 메트릭

메트릭 유형 설명 레이블
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)

퇴거 카운터는 인메모리 LRU 저장소에서 정확합니다. Redis와 S3는 만료 또는 퇴거를 서버 측에서 수행하고 라우터에 퇴거 이벤트를 제공하지 않으므로, 해당 백엔드에서는 값을 임의로 만들지 않습니다.

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 이벤트 컨슈머 메트릭

이 메트릭은 KV 이벤트 컨슈머가 활성화된 경우(src/infrastructure/kv_index/) 수집됩니다. vLLM, SGLang, TensorRT-LLM 리스너는 router salt echo를 사용해 모든 블록 이벤트를 detokenize하지 않고도 같은 접두사 identity를 유지할 수 있습니다. 모든 백엔드 레이블 값은 카디널리티 폭발을 방지하기 위해 정규화됩니다.

메트릭 유형 설명 레이블
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 확인된 고유 접두사 키의 대략적인 수 --

continuum_prefix_routing_requests_total은 백엔드 선택마다 한 번, PrefixAwareHash 전략 분기가 실행됐을 때만 기록됩니다. 다른 selection_strategy에서는 0으로 남습니다. 세 레이블은 ring 탐색과 그대로 대응합니다.

  • prefix_hash: 접두사 해시가 지목한 소유 백엔드가 요청을 받았습니다. CHWBL 부하 상한 아래였던 경우와, 모든 백엔드가 상한에 걸려 ring을 한 바퀴 돈 뒤 접두사 지역성을 지키려고 소유 백엔드를 그대로 쓴 경우를 함께 포함합니다.
  • overflow: 소유 백엔드가 부하 상한에 도달했거나 넘어서, ring에서 시계 방향 뒤쪽 노드가 요청을 받았습니다.
  • fallback: 요청에 접두사 키가 없어 모델 이름을 해싱했고 부하 상한 없이 ring을 걸었습니다. fallback 비율이 계속 100%라면 거의 언제나 prefix_routing.enabled가 false입니다.

unknown은 라우팅 경로가 아니라 정제 결과입니다. 허용 목록에 없는 레이블이 기록 함수에 도달했을 때만 나타납니다.

주요 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
routing_engine_load_decisions_total Counter 엔진 부하 인식 라우팅 결정 (이슈 #1447) backend, reason (engine_load, stale_fallback, hysteresis_hold, admission_reject)

routing_engine_load_decisions_totalrouting.engine_load.enabled가 켜져 있는 동안 스코어링 패스마다 한 번(어드미션 힌트가 거부한 선택마다 추가로 한 번) 기록됩니다. engine_load는 엔진 부하 항이 실제로 순위를 매긴 경우로 backend가 엔진이 선호한 후보를 가리키고, stale_fallback은 신선한 엔진 스냅샷이 하나도 없어 패스가 기본 스코어링과 같게 동작한 경우(backend="none"), hysteresis_hold는 데이터는 있으나 waiting_requests 편차가 balance 임계값 안에 머문 경우, admission_reject는 모든 정상 후보의 kv_cache_usage가 임계값을 넘어 어드미션 힌트가 선택을 거부한 경우(backend="none")입니다. backend 레이블 값은 다른 백엔드 레이블 시리즈와 같은 정제기를 거칩니다. 게이트 판정, 부하 정규화, 캐시된 결과, backend 레이블은 요청의 정확한 라이브 후보 집합으로 한정되므로 모델 가시성, 상태, 재시도 상태, 키별 권한으로 제외된 엔진은 해당 스코어링 결정에 영향을 주거나 레이블에 나타날 수 없습니다.

라우팅 레이블 두 개는 같은 지점에서 선택마다 한 번 기록됩니다. kv_aware는 KV 오버랩 스코어러가 이겨서 그 백엔드로 전달한 경우이고, fallback은 스코어러가 접두사 키를 가지고 실행됐지만 풀에 컴파일된 복합 점수 임계값 0.3을 넘은 백엔드가 없어 설정된 selection_strategy가 대신 결정한 경우입니다. 스코어러가 시도조차 하지 않은 선택(스코어러 미등록, 접두사 키 없음)은 둘 다 기록하지 않으므로, 두 카운터의 합은 전체 트래픽이 아니라 스코어링을 거친 선택의 수입니다. 히스토그램은 kv_aware 결정의 최고 복합 점수를 관측하며, 이 값은 오버랩 항목만이 아니라 오버랩, 부하, 헬스를 모두 반영한 가중 합입니다.

주요 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
model_tokens_processed Counter 성공한 모델 응답이 보고한 토큰 수 model, type (input, output)

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_degraded_total Counter 선택적 외부 PII 분석기를 사용할 수 없어 내장 탐지만 적용한 경우처럼 정밀도가 낮아진 상태로 완료된 프로바이더 검사 provider, kind
guardrail_verdicts_total Counter 모드 의미를 적용한 후 요청당 집계 판정 stage, mode, result
guardrail_stream_buffer_cap_trips_total Counter 스트리밍 출력 게이트의 4 MiB 유지 바이트 상한에 도달한 스트림 수(스트림당 1회) strategy, outcome

레이블 값:

  • stageinput, output, streaming.
  • resultallow, block, transform, flag.
  • kindtimeout 또는 error.
  • modemonitor 또는 enforce. guardrail_verdicts_totalmode를 담으므로, 게이팅하지 않는 monitor 모드 판정도 보입니다. 이 점이 monitor 후 enforce 롤아웃을 관찰 가능하게 만듭니다.
  • provider는 설정된 프로바이더 이름이거나, 예약된 매치 리스트 라벨 두 개 중 하나입니다. guardrails.deny 규칙이 검사를 결정했으면 match_list_deny, allow 규칙이 결정했으면 match_list_allow입니다. 차단 리스트 차단은 guardrail_blocks_totalcategory="deny_list"도 함께 기록합니다. 허용/차단 리스트를 참고하세요.
  • strategy는 상한에 도달한 시점의 전략(buffer_full / chunked / monitor), outcome은 상한 이후 출력 검사가 이어진 방식(degraded_chunked / compacted / truncated). 각 outcome이 안전 보장에 어떤 의미인지는 버퍼 상한 절을 참고하세요. strategy="monitor"는 안전 관련 이벤트가 아니라, monitor 모드 스트림이 길어서 앞쪽 4 MiB만 관찰되었다는 뜻입니다.

주요 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 토큰을 얼마나 썼나'와 같은 질문에 바로 답할 수 있습니다. model_tokens_processed 집계 카운터와 독립적인 별도 메트릭이고, 용량 산정과 공정 사용 정책, 외부 비용 귀속 산정에 쓰입니다.

메트릭 정의

메트릭 유형 설명 레이블
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:9090', 'router2:9090']
    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.kubernetes.io/name: continuum-router
  endpoints:
    - port: metrics
      interval: 15s
      path: /metrics

Prometheus Operator CRD가 설치된 경우 Helm 차트에서 serviceMonitor.enabled=true로 이 객체를 렌더링할 수 있습니다. Operator가 없는 클러스터를 위해 저장소는 Kubernetes endpoint 검색과 체크인된 알림 규칙을 포함한 독립형 Prometheus Kustomize 번들도 제공합니다.

kubectl apply -k monitoring/prometheus
kubectl -n monitoring rollout status deployment/continuum-router-prometheus
kubectl -n monitoring port-forward service/continuum-router-prometheus 9090:9090

독립형 프로필은 15일 보존 기간과 10 GiB ReadWriteOnce PersistentVolumeClaim을 요청합니다. 기본 StorageClass를 확인하고 예상 series 양에 맞게 claim 크기를 조정하거나 고가용성 모니터링에는 관리형 Prometheus 서비스를 사용하십시오. 적용 전에 클러스터 전체 검색 RBAC와 NetworkPolicy를 검토해야 합니다.

Grafana 대시보드

monitoring/grafana/dashboards/router-overview.json에는 다음 패널이 있습니다.

  • 요청 속도
  • 오류율
  • P95 지연 시간
  • 백엔드 상태
  • 엔드포인트별 요청 속도
  • 응답 시간 백분위
  • 모델 사용 분포
  • 백엔드별 현재 처리 중 부하
  • 엔진 요청 수(running / waiting), engine_stats 기반 (이슈 #1446)
  • 엔진 KV 캐시 사용률, engine_stats 기반 (이슈 #1446)
  • 이유별 엔진 부하 라우팅 결정, routing.engine_load 기반 (이슈 #1447)

가져오는 방법:

  1. Grafana를 엽니다.
  2. 대시보드 → 가져오기를 선택합니다.
  3. monitoring/grafana/dashboards/router-overview.json을 업로드합니다.
  4. Prometheus 데이터 소스를 선택하고 가져옵니다.

알림

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

중요 알림

{% raw %}

- alert: HighErrorRate
  expr: sum(rate(http_requests_total{status_code=~"5.."}[5m])) / sum(rate(http_requests_total[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: TimeoutErrors
  expr: sum(rate(timeout_errors_total[5m])) > 0.1
  for: 10m
  annotations:
    summary: "빈번한 타임아웃 오류: 초당 {{ $value }}건"

예제

쿼리 예제

상태별 요청 속도

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

엔드포인트별 P95 지연 시간

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

백엔드 부하 개요

backend_current_load

모델 사용량 순위

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

오류율 백분율

sum(rate(http_requests_total{status_code=~"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:9090/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:9090/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. 시간 범위 검증

추가 리소스