เมื่อวันที่ 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 ที่ดีจะยิ่งเพิ่มความคุ้มค่าในการใช้งาน