เมื่อวันที่ 14 มีนาคม 2024 ระบบของเราล่มไป 3 ชั่วโมงเพราะ API endpoint ที่เราเรียกใช้เงียบไปโดยไม่มีการแจ้งเตือน ผมเห็นแต่ log ข้อผิดพลาด ConnectionError: timeout after 30000ms ใน terminal ตอนเช้า หลังจากนั้นผมตัดสินใจสร้างระบบ monitoring ที่เชื่อถือได้ด้วย Prometheus และ Alertmanager เพื่อไม่ให้ incident แบบนี้เกิดขึ้นอีก

ทำไมต้องใช้ Prometheus + Alertmanager

Prometheus เป็น open-source monitoring system ที่ได้รับความนิยมสูงสุดในวงการ DevOps สามารถเก็บ time-series data ได้หลายล้าน metrics ต่อวินาที ส่วน Alertmanager จัดการ deduplicate, group, route และส่ง alert ไปยังช่องทางต่างๆ เช่น Email, Slack, PagerDuty หรือ webhook

สำหรับทีมที่ใช้ LLM API อย่าง HolySheep AI การมี monitoring ที่ดีจะช่วยลดต้นทุนได้ถึง 40% เพราะตรวจจับปัญหาได้เร็วก่อนที่จะเกิดค่าใช้จ่ายฟุ่มเฟือยจาก retry หรือ timeout ที่ไม่จำเป็น

การติดตั้ง Prometheus

เริ่มต้นด้วยการสร้างไฟล์ configuration สำหรับ Prometheus โดยเราจะ monitor endpoint ของ API ที่เรียกใช้งาน

# prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - alertmanager:9093

rule_files:
  - "alert_rules.yml"

scrape_configs:
  - job_name: 'api-monitor'
    static_configs:
      - targets: ['localhost:9090']
    metrics_path: /metrics
    scrape_interval: 10s

สร้าง Prometheus Metrics Exporter

ต่อไปเราจะสร้าง Python script ที่ทำหน้าที่ export metrics ไปยัง Prometheus โดยจะ track latency, success rate, และ error count ของ API calls

# api_monitor.py
from prometheus_client import Counter, Histogram, Gauge, start_http_server
import requests
import time

Define metrics

REQUEST_COUNT = Counter( 'api_requests_total', 'Total API requests', ['endpoint', 'status'] ) REQUEST_LATENCY = Histogram( 'api_request_latency_seconds', 'API request latency', ['endpoint'] ) ACTIVE_CONNECTIONS = Gauge( 'api_active_connections', 'Number of active connections' ) BASE_URL = "https://api.holysheep.ai/v1" HEADERS = { "Authorization": f"Bearer YOUR_HOLYSHEEP_API_KEY", "Content-Type": "application/json" } def check_api_health(): """Monitor API endpoint and export metrics""" endpoints = [ "/chat/completions", "/embeddings", "/models" ] for endpoint in endpoints: start_time = time.time() ACTIVE_CONNECTIONS.inc() try: response = requests.get( f"{BASE_URL}{endpoint}", headers=HEADERS, timeout=5 ) latency = time.time() - start_time REQUEST_LATENCY.labels(endpoint=endpoint).observe(latency) REQUEST_COUNT.labels( endpoint=endpoint, status=response.status_code ).inc() except requests.exceptions.Timeout: REQUEST_COUNT.labels(endpoint=endpoint, status="timeout").inc() print(f"Timeout error on {endpoint}") except requests.exceptions.ConnectionError as e: REQUEST_COUNT.labels(endpoint=endpoint, status="connection_error").inc() print(f"ConnectionError: {e}") except requests.exceptions.HTTPError as e: REQUEST_COUNT.labels(endpoint=endpoint, status=f"http_{e.response.status_code}").inc() print(f"HTTPError: {e}") finally: ACTIVE_CONNECTIONS.dec() time.sleep(1) if __name__ == "__main__": start_http_server(9090) print("Metrics server started on :9090") while True: check_api_health() time.sleep(10)

กำหนด Alert Rules

ไฟล์นี้กำหนดเงื่อนไขการ trigger alert เมื่อเกิดปัญหาตามที่เราต้องการ เช่น latency สูงผิดปกติ หรือ success rate ต่ำกว่าเกณฑ์

# alert_rules.yml
groups:
  - name: api_alerts
    rules:
      - alert: HighLatency
        expr: histogram_quantile(0.95, api_request_latency_seconds) > 2
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "High API latency detected"
          description: "95th percentile latency is {{ $value }}s"

      - alert: HighErrorRate
        expr: |
          sum(rate(api_requests_total{status!="200"}[5m])) 
          / sum(rate(api_requests_total[5m])) > 0.05
        for: 3m
        labels:
          severity: critical
        annotations:
          summary: "API error rate exceeds 5%"
          description: "Error rate is {{ $value | humanizePercentage }}"

      - alert: APIConnectionError
        expr: increase(api_requests_total{status="connection_error"}[5m]) > 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "API connection errors detected"
          description: "{{ $value }} connection errors in the last 5 minutes"

      - alert: APITimeout
        expr: increase(api_requests_total{status="timeout"}[5m]) > 3
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "Multiple API timeouts"
          description: "{{ $value }} timeouts detected - check network connectivity"

      - alert: NoDataAvailable
        expr: absent(api_requests_total)
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "No API metrics available"
          description: "Prometheus is not receiving data from API monitor"

ตั้งค่า Alertmanager

Alertmanager จะรับ alert จาก Prometheus และส่งต่อไปยังช่องทางที่เรากำหนด เช่น Slack webhook หรือ email

# alertmanager.yml
global:
  resolve_timeout: 5m

route:
  group_by: ['alertname', 'severity']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 12h
  receiver: 'slack-notifications'
  routes:
    - match:
        severity: critical
      receiver: 'pagerduty-notifications'
      continue: true
    - match:
        severity: warning
      receiver: 'slack-notifications'

receivers:
  - name: 'slack-notifications'
    slack_configs:
      - api_url: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK'
        channel: '#api-alerts'
        title: '{{ if eq .Status "firing" }}🔥{{ else }}✅{{ end }} {{ .GroupLabels.alertname }}'
        text: |
          {{ range .Alerts }}
          *Alert:* {{ .Annotations.summary }}
          *Description:* {{ .Annotations.description }}
          *Severity:* {{ .Labels.severity }}
          *Time:* {{ .StartsAt }}
          {{ end }}

  - name: 'pagerduty-notifications'
    pagerduty_configs:
      - service_key: 'YOUR_PAGERDUTY_SERVICE_KEY'
        severity: '{{ if eq .Labels.severity "critical" }}critical{{ else }}warning{{ end }}'
        custom_details:
          alertname: '{{ .Labels.alertname }}'
          description: '{{ .Annotations.description }}'

inhibit_rules:
  - source_match:
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['alertname', 'endpoint']

เริ่มต้น Services ด้วย Docker Compose

เพื่อความสะดวกในการ deploy เราจะใช้ Docker Compose รวม Prometheus, Alertmanager และ Grafana (สำหรับ visualize metrics) ไว้ในคำสั่งเดียว

# docker-compose.yml
version: '3.8'

services:
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - ./alert_rules.yml:/etc/prometheus/alert_rules.yml
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/usr/share/prometheus/console_libraries'
      - '--web.console.templates=/usr/share/prometheus/consoles'
    restart: unless-stopped

  alertmanager:
    image: prom/alertmanager:latest
    container_name: alertmanager
    ports:
      - "9093:9093"
    volumes:
      - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
      - alertmanager_data:/alertmanager
    command:
      - '--config.file=/etc/alertmanager/alertmanager.yml'
      - '--storage.path=/alertmanager'
    restart: unless-stopped

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana_data:/var/lib/grafana
    restart: unless-stopped

  api-monitor:
    build: .
    container_name: api-monitor
    environment:
      - HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY
    restart: unless-stopped

volumes:
  prometheus_data:
  alertmanager_data:
  grafana_data:
# Dockerfile for api-monitor
FROM python:3.11-slim

WORKDIR /app

RUN pip install prometheus-client requests

COPY api_monitor.py .

CMD ["python", "api_monitor.py"]
# Start all services
docker-compose up -d

Check logs

docker-compose logs -f prometheus

Verify Alertmanager is running

curl http://localhost:9093/api/v1/status

ตั้งค่า Grafana Dashboard

หลังจากทุกอย่างทำงานแล้ว เราสามารถสร้าง Dashboard ใน Grafana เพื่อดู metrics แบบ real-time ได้ง่ายๆ ผ่าน UI

# Grafana Dashboard JSON (import this in Grafana)
{
  "dashboard": {
    "title": "API Monitoring Dashboard",
    "panels": [
      {
        "title": "Request Rate",
        "type": "graph",
        "targets": [
          {
            "expr": "rate(api_requests_total[5m])",
            "legendFormat": "{{endpoint}} - {{status}}"
          }
        ]
      },
      {
        "title": "Latency (P95)",
        "type": "gauge",
        "targets": [
          {
            "expr": "histogram_quantile(0.95, api_request_latency_seconds)",
            "legendFormat": "P95 Latency"
          }
        ]
      },
      {
        "title": "Error Rate",
        "type": "stat",
        "targets": [
          {
            "expr": "sum(rate(api_requests_total{status!='200'}[5m])) / sum(rate(api_requests_total[5m])) * 100"
          }
        ],
        "options": {"colorMode": "value", "thresholds": [
          {"value": 0, "color": "green"},
          {"value": 5, "color": "yellow"},
          {"value": 10, "color": "red"}
        ]}
      },
      {
        "title": "Active Connections",
        "type": "stat",
        "targets": [
          {
            "expr": "api_active_connections"
          }
        ]
      }
    ]
  }
}

ข้อผิดพลาดที่พบบ่อยและวิธีแก้ไข

1. Alert ไม่ถูก trigger แม้ว่าเงื่อนไขจะครบ

สาเหตุ: ค่า for ใน alert rule ยังไม่ครบเวลาที่กำหนด หรือ Prometheus ไม่สามารถ evaluate rules ได้

# วิธีแก้ไข:

1. ตรวจสอบว่า rule_files path ถูกต้องใน prometheus.yml

2. Reload Prometheus config ด้วยคำสั่ง:

curl -X POST http://localhost:9090/-/reload

3. ตรวจสอบ rule evaluation ใน Prometheus UI

ไปที่ Status > Rules

4. หรือลดค่า evaluation_interval ชั่วคราว

ใน prometheus.yml:

evaluation_interval: 5s # แทนที่จะเป็น 15s

2. Alertmanager ไม่รับ alerts จาก Prometheus

สาเหตุ: Prometheus ไม่สามารถ reach Alertmanager หรือ config ผิดพลาด

# วิธีแก้ไข:

1. ตรวจสอบว่า Alertmanager ทำงานอยู่

docker ps | grep alertmanager

2. ตรวจสอบ Alertmanager logs

docker-compose logs alertmanager

3. ทดสอบ Alertmanager API

curl -X POST http://localhost:9093/api/v1/alerts \ -H "Content-Type: application/json" \ -d '[{"labels":{"alertname":"TestAlert"}}]'

4. ตรวจสอบ Prometheus alerting config

ต้องระบุ target ให้ถูกต้อง:

alerting: alertmanagers: - static_configs: - targets: - alertmanager:9093 # ใช้ชื่อ container ไม่ใช่ localhost

3. ได้รับ HTTP 401 Unauthorized จาก API

สาเหตุ: API key ไม่ถูกต้องหรือหมดอายุ

# วิธีแก้ไข:

1. ตรวจสอบว่า API key ถูกต้อง

สำหรับ HolySheep AI ไปที่ https://www.holysheep.ai/register เพื่อสร้าง key ใหม่

2. ตรวจสอบ environment variable

echo $HOLYSHEEP_API_KEY

3. ทดสอบ API ด้วย curl

curl -X GET https://api.holysheep.ai/v1/models \ -H "Authorization: Bearer YOUR_HOLYSHEEP_API_KEY"

4. ถ้าได้ 401 แสดงว่า key หมดอายุ สร้างใหม่ที่ dashboard

4. Metrics ไม่ถูกส่งไปยัง Prometheus

สาเหตุ: Port conflict หรือ firewall บล็อก connection

# วิธีแก้ไข:

1. ตรวจสอบว่า metrics server ทำงานอยู่

curl http://localhost:9090/metrics | head -20

2. ถ้าใช้ Docker ให้แชร์ network กัน

ใน docker-compose.yml ให้ api-monitor อยู่ใน network เดียวกับ prometheus

3. หรือใช้ bridge network

networks: - monitoring

4. ตรวจสอบ port ไม่ซ้ำกัน

netstat -tulpn | grep 9090

สรุป

การตรวจสอบ API ด้วย Prometheus และ Alertmanager เป็นวิธีที่มีประสิทธิภาพและไม่มีค่าใช้จ่าย ช่วยให้เราตรวจจับปัญหาได้เร็วก่อนที่จะส่งผลกระทบต่อผู้ใช้งาน จากประสบการณ์จริงของผม ระบบนี้ช่วยลด MTTR (Mean Time To Recovery) ได้ถึง 70% และป้องกัน incident ใหญ่ไปได้หลายครั้ง

สำหรับทีมที่ใช้งาน LLM API อย่าง HolySheep AI ซึ่งมี latency เฉลี่ยต่ำกว่า 50ms และราคาประหยัดถึง 85% เมื่อเทียบกับบริการอื่น (DeepSeek V3.2 ราคาเพียง $0.42/MTok) การมี monitoring ที่ดีจะยิ่งเพิ่มความคุ้มค่าในการใช้งาน

👉 สมัคร HolySheep AI — รับเครดิตฟรีเมื่อลงทะเบียน