시작하기 전에: 왜 AI API 모니터링이 중요한가?

저는 3개월 전 이커머스 스타트업에서 AI 고객 서비스 봇을 개발했습니다. 블랙프라이데이 시즌을 앞두고 트래픽이 평소의 50배로 급증할 것으로 예상되던 시점이었죠.深夜 모니터링 대시보드를 지켜보며 불안하게 coffee를 마시던 중, API 응답 시간이 평소 200ms에서 8초까지 치솟는 현상을 발견했습니다.

문제는 단순한 지연이 아니었습니다. API 제공자의 rate limit에 도달해 요청이 실패하기 시작했고, 사용자들은 "죄송합니다, 일시적인 오류가 발생했습니다"라는 메시지만 받게 됐죠. 결국 2시간 만에 15%의 주문 전환율 손실이라는 비용을 치뤘습니다.

이 경험 이후, 저는 HolySheep AI 게이트웨이를 통해 AI API를 호출하는 모든 프로젝트에 Prometheus + Alertmanager 모니터링 시스템을 구축하고 있습니다. 이 튜토리얼에서는 그 구체적인 구현 방법을 상세히 설명드리겠습니다.

1. 전체 아키텍처 개요

┌─────────────────────────────────────────────────────────────────────┐
│                        모니터링 아키텍처                              │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────────┐  │
│  │HolySheep │    │ Prometheus│    │Grafana   │    │ Alertmanager │  │
│  │ AI API   │───▶│ Collector │───▶│Dashboard │───▶│   Slack/Pager│  │
│  │          │    │          │    │          │    │  Duty Email  │  │
│  └──────────┘    └──────────┘    └──────────┘    └──────────────┘  │
│       │                │                                              │
│       │                ▼                                              │
│       │         ┌──────────┐                                         │
│       │         │  node_   │                                         │
│       │         │ exporter │                                         │
│       │         └──────────┘                                         │
│       │                                                            │
│       ▼                                                            │
│  ┌──────────────────────────────────────┐                          │
│  │     Your AI Application Service      │                          │
│  │  - Flask/FastAPI/Django              │                          │
│  │  - prometheus_client 라이브러리       │                          │
│  └──────────────────────────────────────┘                          │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

2. HolySheep AI API 통합: 메트릭 수집 시작

먼저 HolySheep AI 게이트웨이에 연결하고, 모든 API 호출에 대한 메트릭을 자동으로 수집하는 구조를 만들겠습니다. HolySheep AI는 지금 가입하면 무료 크레딧을 제공하며, GPT-4.1 ($8/MTok), Claude Sonnet 4.5 ($15/MTok), Gemini 2.5 Flash ($2.50/MTok), DeepSeek V3.2 ($0.42/MTok) 등 모든 주요 모델을 단일 API 키로 통합 관리할 수 있습니다.

# requirements.txt

AI & 웹 프레임워크

openai==1.12.0 fastapi==0.109.2 uvicorn==0.27.1

모니터링 & 메트릭

prometheus-client==0.19.0 prometheus-fastapi-instrumentator==6.1.0

유틸리티

python-dotenv==1.0.1 httpx==0.26.0
# config.py
import os
from dotenv import load_dotenv

load_dotenv()

HolySheep AI 설정

⚠️ 실제 API 키는 환경변수로 관리하세요

HOLYSHEEP_API_KEY = os.getenv("HOLYSHEEP_API_KEY", "YOUR_HOLYSHEEP_API_KEY") HOLYSHEEP_BASE_URL = "https://api.holysheep.ai/v1" # 반드시 이 URL 사용

모델별 가격 설정 (Dollar per 1M tokens)

MODEL_PRICING = { "gpt-4.1": {"input": 8.0, "output": 32.0}, "gpt-4.1-mini": {"input": 1.5, "output": 6.0}, "claude-sonnet-4-20250514": {"input": 15.0, "output": 75.0}, "gemini-2.5-flash": {"input": 2.50, "output": 10.0}, "deepseek-v3.2": {"input": 0.42, "output": 1.68}, }

Prometheus 설정

PROMETHEUS_PORT = 9090 ALERTMANAGER_URL = "http://localhost:9093"
# holy_sheep_monitor.py
"""
HolySheep AI API 호출 모니터링 및 메트릭 수집 모듈
모든 API 호출을 감싸서 Prometheus 메트릭으로 자동 수집
"""

from prometheus_client import Counter, Histogram, Gauge, Info
from functools import wraps
import time
from typing import Callable, Any
from config import HOLYSHEEP_BASE_URL, MODEL_PRICING
from openai import OpenAI
import httpx

─────────────────────────────────────────────────────────────

Prometheus 메트릭 정의

─────────────────────────────────────────────────────────────

요청 카운터: 모델별, 상태코드별, 엔드포인트별

REQUEST_COUNTER = Counter( "ai_api_requests_total", "Total AI API requests", ["model", "status_code", "endpoint", "error_type"] )

응답 시간 히스토그램: P50, P90, P99 측정

RESPONSE_TIME = Histogram( "ai_api_response_seconds", "AI API response time in seconds", ["model", "endpoint"], buckets=[0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0, 30.0] )

토큰 사용량 게이지: 입력/출력 토큰 카운트

TOKEN_USAGE = Counter( "ai_api_tokens_total", "Total tokens used", ["model", "token_type"] # token_type: "input" or "output" )

비용 추적 카운터

API_COST = Counter( "ai_api_cost_dollars", "API cost in dollars", ["model"] )

활성 요청 수 게이지: 동시 요청 모니터링

ACTIVE_REQUESTS = Gauge( "ai_api_active_requests", "Number of active requests", ["model"] )

Rate Limit 상태 게이지

RATE_LIMIT_REMAINING = Gauge( "ai_api_rate_limit_remaining", "Remaining API calls in rate limit window", ["model"] )

─────────────────────────────────────────────────────────────

HolySheep AI 클라이언트 래퍼

─────────────────────────────────────────────────────────────

class MonitoredHolySheepClient: """ HolySheep AI API 호출을 모니터링하는 래퍼 클라이언트 모든 요청에 대해 자동 메트릭 수집 """ def __init__(self, api_key: str): self.client = OpenAI( api_key=api_key, base_url=HOLYSHEEP_BASE_URL # HolySheep 게이트웨이 사용 ) self._error_counts = {} def _extract_error_type(self, error: Exception) -> str: """오류 유형 분류""" error_str = str(error).lower() if "rate limit" in error_str or "429" in error_str: return "rate_limit" elif "timeout" in error_str or "timed out" in error_str: return "timeout" elif "401" in error_str or "unauthorized" in error_str: return "auth_error" elif "500" in error_str or "502" in error_str or "503" in error_str: return "server_error" elif "context_length" in error_str or "max_tokens" in error_str: return "context_limit" else: return "unknown" def chat_completions_create( self, model: str, messages: list, temperature: float = 0.7, max_tokens: int = 2048, **kwargs ) -> dict: """ HolySheep AI 채팅 완성 API 호출 (메트릭 자동 수집) 실제 지연 시간 예시: - Gemini 2.5 Flash: 평균 150ms (Cold start 포함 800ms) - DeepSeek V3.2: 평균 200ms - GPT-4.1: 평균 400ms """ endpoint = "/chat/completions" ACTIVE_REQUESTS.labels(model=model).inc() start_time = time.perf_counter() try: response = self.client.chat.completions.create( model=model, messages=messages, temperature=temperature, max_tokens=max_tokens, **kwargs ) # 성공 메트릭 수집 elapsed = time.perf_counter() - start_time RESPONSE_TIME.labels(model=model, endpoint=endpoint).observe(elapsed) REQUEST_COUNTER.labels( model=model, status_code="200", endpoint=endpoint, error_type="none" ).inc() # 토큰 사용량 및 비용 계산 if hasattr(response, 'usage') and response.usage: input_tokens = response.usage.prompt_tokens or 0 output_tokens = response.usage.completion_tokens or 0 TOKEN_USAGE.labels(model=model, token_type="input").inc(input_tokens) TOKEN_USAGE.labels(model=model, token_type="output").inc(output_tokens) # 비용 계산 (Dollar) if model in MODEL_PRICING: cost = ( (input_tokens / 1_000_000) * MODEL_PRICING[model]["input"] + (output_tokens / 1_000_000) * MODEL_PRICING[model]["output"] ) API_COST.labels(model=model).inc(cost) return response except Exception as e: elapsed = time.perf_counter() - start_time error_type = self._extract_error_type(e) # 실패 메트릭 수집 RESPONSE_TIME.labels(model=model, endpoint=endpoint).observe(elapsed) REQUEST_COUNTER.labels( model=model, status_code="error", endpoint=endpoint, error_type=error_type ).inc() # 오류 카운터 업데이트 (연속 실패 감지용) self._error_counts[model] = self._error_counts.get(model, 0) + 1 raise finally: ACTIVE_REQUESTS.labels(model=model).dec()

글로벌 클라이언트 인스턴스

_client_instance = None def get_monitored_client(api_key: str) -> MonitoredHolySheepClient: global _client_instance if _client_instance is None: _client_instance = MonitoredHolySheepClient(api_key) return _client_instance

3. FastAPI 애플리케이션과 Prometheus 엔드포인트

# app.py
"""
FastAPI + Prometheus 모니터링 통합 애플리케이션
HolySheep AI 기반 AI 서비스 예시
"""

from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import JSONResponse
from pydantic import BaseModel
from contextlib import asynccontextmanager
import logging
from holy_sheep_monitor import get_monitored_client
from config import HOLYSHEEP_API_KEY
from prometheus_client import make_asgi_app, REGISTRY, generate_latest

로깅 설정

logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__)

─────────────────────────────────────────────────────────────

FastAPI 앱 설정

─────────────────────────────────────────────────────────────

@asynccontextmanager async def lifespan(app: FastAPI): """애플리케이션 시작/종료 시 실행""" logger.info("🚀 AI API 모니터링 시스템 시작") logger.info(f"📊 HolySheep API 엔드포인트: {HOLYSHEEP_API_KEY[:8]}...") # HolySheep AI 클라이언트 초기화 client = get_monitored_client(HOLYSHEEP_API_KEY) app.state.client = client yield logger.info("🔴 모니터링 시스템 종료") app = FastAPI( title="AI Customer Service API", version="1.0.0", lifespan=lifespan )

Prometheus 메트릭 엔드포인트 마운트

metrics_app = make_asgi_app() app.mount("/metrics", metrics_app)

─────────────────────────────────────────────────────────────

요청/응답 모델

─────────────────────────────────────────────────────────────

class ChatRequest(BaseModel): model: str = "deepseek-v3.2" # 기본값: 가장 저렴한 모델 message: str system_prompt: str = "당신은 친절한 고객 서비스 담당자입니다." temperature: float = 0.7 max_tokens: int = 1024 class ChatResponse(BaseModel): model: str response: str input_tokens: int output_tokens: int cost_usd: float latency_ms: float

─────────────────────────────────────────────────────────────

API 엔드포인트

─────────────────────────────────────────────────────────────

@app.post("/api/chat", response_model=ChatResponse) async def chat(request: ChatRequest): """AI 고객 서비스 채팅 엔드포인트""" import time from config import MODEL_PRICING start = time.perf_counter() try: client = app.state.client messages = [ {"role": "system", "content": request.system_prompt}, {"role": "user", "content": request.message} ] response = client.chat_completions_create( model=request.model, messages=messages, temperature=request.temperature, max_tokens=request.max_tokens ) elapsed_ms = (time.perf_counter() - start) * 1000 # 토큰 및 비용 계산 usage = response.usage input_tokens = usage.prompt_tokens output_tokens = usage.completion_tokens pricing = MODEL_PRICING.get(request.model, {"input": 1.0, "output": 1.0}) cost_usd = ( (input_tokens / 1_000_000) * pricing["input"] + (output_tokens / 1_000_000) * pricing["output"] ) logger.info( f"✅ [{request.model}] 응답 완료: " f"latency={elapsed_ms:.0f}ms, tokens={input_tokens}+{output_tokens}, " f"cost=${cost_usd:.4f}" ) return ChatResponse( model=request.model, response=response.choices[0].message.content, input_tokens=input_tokens, output_tokens=output_tokens, cost_usd=cost_usd, latency_ms=round(elapsed_ms, 2) ) except Exception as e: logger.error(f"❌ 채팅 요청 실패: {str(e)}") raise HTTPException(status_code=500, detail=str(e)) @app.get("/health") async def health_check(): """헬스체크 엔드포인트""" return {"status": "healthy", "service": "ai-customer-service"} @app.get("/metrics") async def custom_metrics(): """커스텀 메트릭 엔드포인트""" return Response( content=generate_latest(REGISTRY), media_type="text/plain" ) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)

4. Prometheus 설정 및 Alertmanager 연동

# prometheus.yml

docker-compose.yml과 함께 사용하는 Prometheus 설정

global: scrape_interval: 15s evaluation_interval: 15s external_labels: cluster: 'ai-api-production' environment: 'production' alerting: alertmanagers: - static_configs: - targets: - alertmanager:9093 rule_files: - /etc/prometheus/rules/*.yml scrape_configs: # 자체 애플리케이션 메트릭 - job_name: 'ai-service' static_configs: - targets: ['ai-service:8000'] metrics_path: '/metrics' scrape_interval: 10s scrape_timeout: 5s # Prometheus 자체 메트릭 - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] # node_exporter (서버 리소스 모니터링) - job_name: 'node' static_configs: - targets: ['node-exporter:9100']
# rules/ai-alerts.yml

AI API 모니터링 알림 규칙

groups: - name: ai_api_alerts interval: 30s rules: # ───────────────────────────────────────────────────── # 1. 고가용성 알림: 서비스 장애 # ───────────────────────────────────────────────────── - alert: AIAPIServiceDown expr: up{job="ai-service"} == 0 for: 1m labels: severity: critical team: platform annotations: summary: "AI API 서비스 연결 불가" description: "{{ $labels.instance }} 서비스가 1분 이상 응답하지 않습니다." - alert: AIAPIMultiRegionFailure expr: | ( sum(rate(ai_api_requests_total{status_code="error"}[5m])) by (model) / sum(rate(ai_api_requests_total[5m])) by (model) ) > 0.1 for: 3m labels: severity: critical annotations: summary: "AI API {{ $labels.model }} 모델 10% 이상 실패" description: "{{ $labels.model }} 실패율이 10%를 초과합니다. 현재: {{ $value | humanizePercentage }}" # ───────────────────────────────────────────────────── # 2. 성능 알림: 지연 시간 이상 # ───────────────────────────────────────────────────── - alert: AIAPILatencyHigh expr: | histogram_quantile(0.95, sum(rate(ai_api_response_seconds_bucket[5m])) by (le, model) ) > 5 for: 5m labels: severity: warning annotations: summary: "AI API {{ $labels.model }} 응답 지연 증가" description: "P95 응답 시간이 5초를 초과합니다. 현재: {{ $value | humanizeDuration }}" - alert: AIAPILatencyCritical expr: | histogram_quantile(0.99, sum(rate(ai_api_response_seconds_bucket[5m])) by (le, model) ) > 10 for: 2m labels: severity: critical annotations: summary: "AI API {{ $labels.model }} 심각한 지연" description: "P99 응답 시간이 10초를 초과합니다. 즉시 조치가 필요합니다." # ───────────────────────────────────────────────────── # 3. Rate Limit 알림:Quota 소진 경고 # ───────────────────────────────────────────────────── - alert: AIAPIRateLimitWarning expr: | increase(ai_api_requests_total{error_type="rate_limit"}[5m]) > 10 for: 1m labels: severity: warning annotations: summary: "AI API Rate Limit 접근" description: "{{ $labels.model }} 모델의 Rate Limit 오류가 5분간 10회 이상 발생했습니다." - alert: AIAPIErrorRateThreshold expr: | ( sum(rate(ai_api_requests_total{error_type=~"timeout|server_error"}[10m])) by (model) / sum(rate(ai_api_requests_total[10m])) by (model) ) > 0.05 for: 5m labels: severity: warning annotations: summary: "AI API {{ $labels.model }} 오류율 5% 초과" # ───────────────────────────────────────────────────── # 4. 비용 알림: Budget 관리 # ───────────────────────────────────────────────────── - alert: AIAPICostDailyBudgetWarning expr: | sum(increase(ai_api_cost_dollars[24h])) > 100 for: 1m labels: severity: warning budget: "daily" annotations: summary: "AI API 일일 비용 경고" description: "24시간 비용이 $100을 초과했습니다. 현재: ${{ $value | humanize }}" - alert: AIAPICostBurst expr: | sum(increase(ai_api_cost_dollars[1h])) > 20 for: 5m labels: severity: warning annotations: summary: "AI API 비용 급증 감지" description: "1시간 비용이 $20를 초과했습니다. 이상 트래픽 패턴을 확인하세요." # ───────────────────────────────────────────────────── # 5. 동시성 알림: 시스템 과부하 # ───────────────────────────────────────────────────── - alert: AIAPIActiveRequestsHigh expr: | sum(ai_api_active_requests) by (model) > 50 for: 5m labels: severity: warning annotations: summary: "AI API {{ $labels.model }} 동시 요청过多" description: "활성 요청 수가 50개를 초과합니다. 스케일링을 고려하세요." # ───────────────────────────────────────────────────── # 6. 토큰 사용량 알림 # ───────────────────────────────────────────────────── - alert: AIAPITokenUsageSpike expr: | sum(rate(ai_api_tokens_total[1h])) by (model, token_type) > 1000000 # 시간당 100만 토큰 이상 for: 10m labels: severity: info annotations: summary: "AI API {{ $labels.model }} 토큰 사용량 급증" description: "{{ $labels.token_type }} 토큰 사용량이 시간당 100만개를 초과합니다."
# alertmanager.yml

Alertmanager 설정: Slack, Email, PagerDuty 연동

global: resolve_timeout: 5m smtp_smarthost: 'smtp.gmail.com:587' smtp_from: '[email protected]' smtp_auth_username: '[email protected]' smtp_auth_password: 'YOUR_APP_PASSWORD' templates: - '/etc/alertmanager/template/*.tmpl' route: group_by: ['alertname', 'severity'] group_wait: 30s group_interval: 5m repeat_interval: 4h receiver: 'default' routes: # 심각한(critical) 알림은 즉시通知 - match: severity: critical receiver: 'critical-alerts' group_wait: 10s repeat_interval: 1h # 비용 알림은 별도 채널로 - match: budget: daily receiver: 'cost-alerts' continue: true # 팀별 라우팅 - match: team: platform receiver: 'platform-team' receivers: # 기본 수신자 (Slack) - name: 'default' slack_configs: - api_url: 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL' channel: '#ai-alerts' send_resolved: true title: | {{ if eq .Status "firing" }}🚨{{ else }}✅{{ end }} {{ .GroupLabels.alertname }} text: | {{ range .Alerts }} *Severity:* {{ .Labels.severity }} *Summary:* {{ .Annotations.summary }} *Description:* {{ .Annotations.description }} *Instance:* {{ .Labels.instance }} *Value:* {{ .Value }} *Time:* {{ .StartsAt.Format "2006-01-02 15:04:05" }} {{ end }} # 심각한 알림 수신자 (SMS + Slack) - name: 'critical-alerts' slack_configs: - api_url: 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL' channel: '#ai-critical' send_resolved: true title: "🚨 CRITICAL: AI API 장애 발생" text: | *🚨 심각한 AI API 장애 감지* *알림:* {{ .CommonLabels.alertname }} *설명:* {{ .CommonAnnotations.summary }} *시간:* {{ .CommonStartsAt }} ⚡ 즉시 확인 필요! pagerduty_configs: - service_key: 'YOUR_PAGERDUTY_SERVICE_KEY' severity: critical # 비용 알림 수신자 - name: 'cost-alerts' slack_configs: - api_url: 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL' channel: '#ai-cost' send_resolved: true title: "💰 AI API 비용 알림" text: | *💰 비용 알림* *알림:* {{ .CommonLabels.alertname }} *현재 비용:* ${{ .CommonAnnotations.description }} 📊 비용 대시보드: http://grafana.example.com/d/costs # 플랫폼 팀 - name: 'platform-team' email_configs: - to: '[email protected]' send_resolved: true headers: subject: '[P1] {{ .CommonLabels.alertname }}' inhibit_rules: # 같은 인스턴스의 알림 억제 - source_match: severity: 'critical' target_match: severity: 'warning' equal: ['alertname', 'instance']

5. Docker Compose로 한 번에 실행

# docker-compose.yml
version: '3.8'

services:
  # FastAPI AI 서비스
  ai-service:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: ai-service
    ports:
      - "8000:8000"
    environment:
      - HOLYSHEEP_API_KEY=${HOLYSHEEP_API_KEY}
    volumes:
      - ./config.py:/app/config.py
      - ./holy_sheep_monitor.py:/app/holy_sheep_monitor.py
    networks:
      - monitoring
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  # Prometheus
  prometheus:
    image: prom/prometheus:v2.48.1
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - ./rules:/etc/prometheus/rules:ro
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.enable-lifecycle'
    networks:
      - monitoring
    restart: unless-stopped

  # Alertmanager
  alertmanager:
    image: prom/alertmanager:v0.27.0
    container_name: alertmanager
    ports:
      - "9093:9093"
    volumes:
      - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
      - alertmanager-data:/alertmanager
    command:
      - '--config.file=/etc/alertmanager/alertmanager.yml'
      - '--storage.path=/alertmanager'
    networks:
      - monitoring
    restart: unless-stopped

  # Grafana (시각화)
  grafana:
    image: grafana/grafana:10.2.3
    container_name: grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:-admin}
      - GF_USERS_ALLOW_SIGN_UP=false
    volumes:
      - grafana-data:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning:ro
    networks:
      - monitoring
    depends_on:
      - prometheus
    restart: unless-stopped

  # Node Exporter (서버 메트릭)
  node-exporter:
    image: prom/node-exporter:v1.7.0
    container_name: node-exporter
    ports:
      - "9100:9100"
    command:
      - '--path.procfs=/host/proc'
      - '--path.sysfs=/host/sys'
      - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    networks:
      - monitoring
    restart: unless-stopped

networks:
  monitoring:
    driver: bridge

volumes:
  prometheus-data:
  alertmanager-data:
  grafana-data:
# Grafana 대시보드 Provisioning 설정

grafana/provisioning/dashboards/dashboard.yml

apiVersion: 1 providers: - name: 'AI API Monitoring' orgId: 1 folder: 'AI Services' folderUid: 'ai-services' type: file disableDeletion: false updateIntervalSeconds: 10 options: path: /etc/grafana/provisioning/dashboards ---

grafana/provisioning/datasources/datasource.yml

apiVersion: 1 datasources: - name: Prometheus type: prometheus access: proxy url: http://prometheus:9090 isDefault: true editable: false
# grafana/provisioning/dashboards/ai-api.json (대시보드 정의)
{
  "dashboard": {
    "title": "AI API Monitoring - HolySheep",
    "uid": "ai-api-monitor",
    "timezone": "browser",
    "panels": [
      {
        "title": "Request Rate (RPM)",
        "type": "graph",
        "gridPos": {"h": 8, "w": 12, "x": 0, "y": 0},
        "targets": [
          {
            "expr": "sum(rate(ai_api_requests_total[1m])) by (model)",
            "legendFormat": "{{model}}"
          }
        ]
      },
      {
        "title": "Response Time P50/P90/P99",
        "type": "graph",
        "gridPos": {"h": 8, "w": 12, "x": 12, "y": 0},
        "targets": [
          {
            "expr": "histogram_quantile(0.50, sum(rate(ai_api_response_seconds_bucket[5m])) by (le, model))",
            "legendFormat": "P50 - {{model}}"
          },
          {
            "expr": "histogram_quantile(0.90, sum(rate(ai_api_response_seconds_bucket[5m])) by (le, model))",
            "legendFormat": "P90 - {{model}}"
          },
          {
            "expr": "histogram_quantile(0.99, sum(rate(ai_api_response_seconds_bucket[5m])) by (le, model))",
            "legendFormat": "P99 - {{model}}"
          }
        ]
      },
      {
        "title": "Error Rate by Type",
        "type": "piechart",
        "gridPos": {"h": 8, "w": 8, "x": 0, "y": 8},
        "targets": [
          {
            "expr": "sum(increase(ai_api_requests_total{status_code=\"error\"}[1h])) by (error_type)"
          }
        ]
      },
      {
        "title": "API Cost (24h)",
        "type": "stat",
        "gridPos": {"h": 8, "w": 8, "x": 8, "y": 8},
        "targets": [
          {
            "expr": "sum(increase(ai_api_cost_dollars[24h]))"
          }
        ],
        "fieldConfig": {
          "defaults": {
            "unit": "currencyUSD"
          }
        }
      },
      {
        "title": "Token Usage (Input/Output)",
        "type": "bargauge",
        "gridPos": {"h": 8, "w": 8, "x": 16, "y": 8},
        "targets": [
          {
            "expr": "sum(increase(ai_api_tokens_total[24h])) by (token_type)"
          }
        ]
      },
      {
        "title": "Active Requests",
        "type": "gauge",
        "gridPos": {"h": 8, "w": 12, "x": 0, "y": 16},
        "targets": [
          {
            "expr": "sum(ai_api_active_requests) by (model)"
          }
        ],
        "fieldConfig": {
          "defaults": {
            "thresholds": {
              "mode": "absolute",
              "steps": [
                {"value": 0, "color": "green"},
                {"value": 20, "color": "yellow"},
                {"value": 50, "color": "red"}
              ]
            }
          }
        }
      }
    ],
    "refresh": "10s",
    "schemaVersion": 30,
    "version": 1
  }
}
# 실행 명령어

전체 스택 시작

docker-compose up -d

로그 확인

docker-compose logs -f ai-service prometheus alertmanager

Prometheus Targets 확인

curl -s http://localhost:9090/api/v1/targets | jq '.data.activeTargets'

Alertmanager 상태 확인

curl -s http://localhost:9093/api/v1/status | jq '.data'

Grafana 접속 (기본 계정: admin/admin)

echo "Grafana: http://localhost:3000" echo "Prometheus: http://localhost:9090" echo "Alertmanager: http://localhost:9093" echo "API Service: http://localhost:8000" echo "Metrics: http://localhost:8000/metrics"

자주 발생하는 오류와 해결책

오류 1: "Connection refused" - Prometheus가 메트릭을 수집하지 못함

# 증상: Prometheus 로그에 아래 오류 발생

level=error ts=