10/08/2026 10:11น.

Golang The Series EP.167: Monitoring AI Performance ใช้ Prometheus วัดความเร็ว Latency
#Golang
#Prometheus
#Latency
#AI Performance
#Go Backend
#Observability
#สอน Golang
#AI Infrastructure
ยินดีต้อนรับเข้าสู่ EP.167 ครับ! ผ่านมาแล้ว 166 ตอน ระบบ AI Backend ใน Go ของเรามีครบทั้ง Multi-LLM, Redis Caching, Rate Limiting, Load Balancing ไปจนถึง Circuit Breaker พร้อมลุยสเกลระดับ Enterprise เรียบร้อยแล้ว
แต่ในโลกของ Production มีประโยคคลาสสิกของนักพัฒนาระบบกล่าวไว้ว่า "If you can't measure it, you can't improve it" (ถ้าคุณวัดผลมันไม่ได้ คุณก็ปรับปรุงมันไม่ได้)
ผมจำได้เลยว่าตอนที่ปล่อยระบบ AI ขึ้น Production ครั้งแรก พอถึงช่วงที่คนใช้งานพร้อมกันเยอะๆ ระบบเกิดอืดขึ้นมาอย่างไม่ทราบสาเหตุ กว่าจะควานหาเจอว่า AI Provider เจ้าไหนกำลังคอขวดก็เสียเวลาไปหลายชั่วโมงเลยครับ
ระบบ AI มีความท้าทายเรื่อง Latency ที่ต่างจาก CRUD API ทั่วไปอย่างสิ้นเชิง API ปกติอาจตอบกลับในระดับ 50ms แต่ LLM อาจใช้เวลาตั้งแต่ 500ms ไปจนถึง 10 วินาที ขึ้นอยู่กับขนาด Prompt, ความยาว Context และจำนวน Output Tokens หากไม่มีระบบ Observability & Monitoring ที่ดี เราไม่มีทางรู้ได้เลยว่า:
LLM เจ้าไหนเริ่มตอบช้าลงในจังหวะ Peak Load?
ค่า Latency ที่กระจายตัวกัน (Percentiles: p50, p90, p99) อยู่ในระดับที่ SLA รับได้หรือไม่?
อัตราส่วน Cache Hit/Miss หรือการสับ Circuit Breaker เกิดขึ้นบ่อยแค่ไหน?
วันนี้เราจะมาติด "ตัววัดชีพจร" ให้กับแอปพลิเคชัน Go ของเราด้วย Prometheus Metrics กันครับ!
ทำความรู้จัก Metrics Types ใน Prometheus
Prometheus มีประเภทของ Metric ให้เลือกใช้งานตามวัตถุประสงค์ ในการวัดผล AI Performance เราจะเน้น 3 ตัวหลัก:
Counter: ค่าที่นับเพิ่มขึ้นเรื่อยๆ ไม่มีวันลดลง (ยกเว้น Restart Service) เหมาะสำหรับนับจำนวน Request รวม (
ai_requests_total) หรือนับจำนวน Tokens รวมที่ใช้งานไปGauge: ค่าที่ขึ้นๆ ลงๆ ได้ตลอดเวลา เหมาะสำหรับวัดจำนวน Request ที่กำลังประมวลผลอยู่ ณ ขณะนั้น (
ai_concurrent_requests)Histogram: จัดกลุ่มข้อมูลใส่ "ถัง" (Buckets) เพื่อคำนวณแจกแจงค่าทางสถิติ เหมาะที่สุดสำหรับการวัด Latency หรือ Processing Duration (
ai_request_duration_seconds)
การติดตั้ง Dependency
เราจะใช้ Official Library ของ Prometheus สำหรับภาษา Go:
Bash
go get github.com/prometheus/client_golang/prometheus
go get github.com/prometheus/client_golang/prometheus/promhttp
โครงสร้างและการเขียน Go ฝัง Prometheus Metrics
เราจะสร้าง Custom Metrics เพื่อจับเวลาการตอบสนองของ AI แต่ละ Provider (เช่น OpenAI, Anthropic, Ollama Local) พร้อมแยกตามสถานะการตอบกลับ (Success / Error)
ส่วนที่ 1: ประกาศตัวแปร Prometheus Metrics และฟังก์ชันจำลองการเรียกใช้ AI
Go
package main
import (
"fmt"
"log"
"math/rand"
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
// 1. Counter: นับจำนวน Request ทั้งหมด แยกตาม provider และ status
aiRequestsTotal = promauto.NewCounterVec(
prometheus.CounterOpts{
Name: "ai_requests_total",
Help: "จำนวนครั้งทั้งหมดที่มีการเรียกใช้งาน AI API",
},
[]string{"provider", "status"},
)
// 2. Histogram: วัดเวลาในการประมวลผล (Latency) แยกตาม provider
aiRequestDuration = promauto.NewHistogramVec(
prometheus.HistogramOpts{
Name: "ai_request_duration_seconds",
Help: "ระยะเวลาประมวลผลของ AI API ในหน่วยวินาที",
// กำหนดช่วง Buckets ทางสถิติ ตั้งแต่ 0.1s ไปจนถึง 10s
Buckets: []float64{0.1, 0.5, 1.0, 2.0, 5.0, 10.0},
},
[]string{"provider"},
)
// 3. Gauge: วัดจำนวน Request ที่กำลังรันขนานกันอยู่ในขณะนั้น
aiActiveRequests = promauto.NewGaugeVec(
prometheus.GaugeOpts{
Name: "ai_active_requests",
Help: "จำนวน Request ที่กำลังประมวลผลอยู่พร้อมกัน",
},
[]string{"provider"},
)
)
// simulateAICall จำลองการยิงหา AI Provider พร้อมจับเวลาประมวลผล
func simulateAICall(provider string) (string, error) {
// เพิ่มจำนวน Active Request ใน Gauge
aiActiveRequests.WithLabelValues(provider).Inc()
defer aiActiveRequests.WithLabelValues(provider).Dec()
// เริ่มจับเวลา
startTime := time.Now()
// จำลองเวลาประมวลผลของ AI (0.2s ถึง 3.0s)
processingTime := time.Duration(200+rand.Intn(2800)) * time.Millisecond
time.Sleep(processingTime)
duration := time.Since(startTime).Seconds()
// บันทึก Latency ลงใน Histogram Bucket
aiRequestDuration.WithLabelValues(provider).Observe(duration)
// จำลองโอกาสเกิด Error 10%
if rand.Float32() < 0.1 {
aiRequestsTotal.WithLabelValues(provider, "error").Inc()
return "", fmt.Errorf("AI Provider %s Timeout / Service Unavailable", provider)
}
aiRequestsTotal.WithLabelValues(provider, "success").Inc()
return fmt.Sprintf("คำตอบจาก %s (ใช้เวลา %.2fs)", provider, duration), nil
}
ส่วนที่ 2: ส่วนการทำ HTTP Endpoints และบริการให้ Prometheus เข้ามาดึงข้อมูล (Scraping): main.go
Go
func main() {
// 1. Endpoint สำหรับให้ Prometheus Server มา Scraping ดึงข้อมูล Metrics
http.Handle("/metrics", promhttp.Handler())
// 2. Endpoint จำลอง API สำหรับประมวลผล AI
http.HandleFunc("/api/v1/generate", func(w http.ResponseWriter, r *http.Request) {
provider := r.URL.Query().Get("provider")
if provider == "" {
provider = "openai" // Default Provider
}
resp, err := simulateAICall(provider)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
_, _ = w.Write([]byte(resp))
})
log.Println("📊 Prometheus Metrics Endpoint รันอยู่ที่ http://localhost:2112/metrics")
log.Println("🚀 AI Service API พร้อมรับ Request ที่ http://localhost:2112/api/v1/generate")
log.Fatal(http.ListenAndServe(":2112", nil))
}
การนำข้อมูลไปสร้าง Dashboard บน Grafana (PromQL)
เมื่อ Prometheus ดึง Metrics จาก /metrics Endpoint ของเราไปเก็บไว้ใน Time-Series Database แล้ว เราสามารถใช้คำสั่ง PromQL (Prometheus Query Language) บน Grafana เพื่อสร้าง Dashboard แสดงผลได้อย่างเรียบหรู:
1. คำนวณค่า Latency Percentile 95th (95% ของผู้ใช้งานได้รับตอบสนองภายในกี่วินาที)
ข้อมูลโค้ด
histogram_quantile(0.95, sum(rate(ai_request_duration_seconds_bucket[5m])) by (le, provider))
2. คำนวณอัตราความสำเร็จ (Success Rate %)
ข้อมูลโค้ด
(sum(rate(ai_requests_total{status="success"}[5m])) / sum(rate(ai_requests_total[5m]))) * 100
🎯 ท้าให้ลอง (Daily Mission)
ลองรันโค้ดด้านบน แล้วใช้ cURL ยิง Request เข้าไปหลายๆ ครั้งโดยสลับค่า Provider:
Bash
curl "http://localhost:2112/api/v1/generate?provider=openai"
curl "http://localhost:2112/api/v1/generate?provider=gemini"
จากนั้นเปิดเบราว์เซอร์เข้าไปที่ http://localhost:2112/metrics
การบ้านชวนคิด: ลองค้นหาข้อความ ai_request_duration_seconds_bucket บนหน้าเว็บ /metrics แล้วสังเกตว่าข้อมูลการนับในแต่ละ Bucket สอดคล้องกับเวลาประมวลผลจริงเพียงใด? และหากในอนาคตคุณต้องการวัด "จำนวน Token ที่ใช้ไป" (Token Usage) เพิ่มเติมเพื่อนำไปคำนวณต้นทุน (Cost) รายวัน คุณคิดว่าควรเลือกใช้ Metric Type ชนิดใดระหว่าง Counter, Gauge หรือ Histogram? ลองออกแบบโครงสร้างกันดูนะครับ!
🙋♂️ FAQ คำถามที่พบบ่อย
ทำไมถึงไม่ใช้การพิมพ์ Log ธรรมดาเพื่อจับเวลา ทำไมต้องยุ่งยากใช้ Prometheus?
การใช้ Log พิมพ์ระยะเวลา (เช่น log.Printf("ใช้เวลา %v", duration)) ทำได้ง่ายในตอนเริ่มต้นครับ แต่เมื่อระบบมีผู้ใช้งานระดับพันหรือหมื่น Request ต่อวินาที Log จะมีขนาดมหาศาลมาก การจะนำ Log เหล่านั้นมาคำนวณหาค่าเฉลี่ยหรือ P95 แบบ Real-time จะกินทรัพยากรสูงมาก Prometheus ถูกออกแบบมาเพื่อเก็บเป็น Time-Series Data ซึ่งประหยัดพื้นที่กว่า และดึงข้อมูลมาแสดงเป็นกราฟได้ไวกว่าอย่างเห็นได้ชัดครับ
ค่า Buckets ใน Histogram ควรตั้งอย่างไรสำหรับ AI ทั่วไป?
สำหรับ AI จะใช้เวลาตอบสนองนานกว่า API ปกติครับ การตั้ง Bucket ที่ระดับมิลลิวินาที (เช่น 0.01s, 0.05s) อาจจะไม่ค่อยมีประโยชน์เท่าไหร่ แนะนำให้ตั้งค่าที่ครอบคลุมช่วงการประมวลผลของ LLM จริงๆ เช่น [0.5, 1.0, 2.0, 5.0, 10.0, 30.0, 60.0] วินาที เพื่อให้รองรับไปจนถึง Prompt ขนาดใหญ่มากๆ ได้
การให้ Prometheus เข้ามาดึงข้อมูล (Scrape) บ่อยๆ จะทำให้ Server อืดไหม?
ไม่เลยครับ! ตัว /metrics endpoint ถูกออกแบบมาให้เบาและรวดเร็วมาก การตั้งให้ Prometheus เข้ามาดึงข้อมูลทุกๆ 10 หรือ 15 วินาที เป็น Best Practice พื้นฐานที่ไม่ได้ส่งผลกระทบต่อประสิทธิภาพการทำงานหลักของเซิร์ฟเวอร์เราเลยครับ
📝 สรุป
ในบทความนี้เราได้เรียนรู้วิธีการติดอาวุธให้ระบบ Go Backend ของเราด้วยการทำ Observability เพื่อตรวจสอบประสิทธิภาพการทำงานของ AI ผ่าน Prometheus Metrics เราได้รู้จักกับ Metric Types ทั้ง 3 ชนิด (Counter, Gauge, Histogram) รู้วิธีการเขียนโค้ดจับเวลา Latency อย่างถูกวิธี พร้อมทั้งการนำไปประยุกต์เขียนสูตร PromQL บน Grafana เพื่อคำนวณค่าทางสถิติระดับโปร (P95 และ Success Rate) ตอนนี้ระบบของคุณพร้อมสำหรับการสเกลบน Production และสามารถตอบคำถามทีม Business ได้อย่างมั่นใจแล้วครับว่าระบบทำงานได้ดีแค่ไหน!
ในตอนต่อไป (EP.168): เรามีระบบวัดผล Performance ที่ดีเยี่ยมแล้ว แต่ปัญหาปวดหัวที่สุดอย่างหนึ่งของนักพัฒนา AI คือ "AI ไม่ได้ตอบข้อผิดพลาดเป็น HTTP Status Code เสมอไป" บางครั้ง API ตอบกลับ 200 OK แต่ข้อความข้างในกลับเป็น "ขออภัย ฉันไม่สามารถทำตามคำสั่งนี้ได้" หรือตอบ JSON ออกมาผิด Structure จนระบบ Go ไม่สามารถ Parse (แปลง) ข้อมูลได้! ตอนหน้าเราจะมาลุยเรื่อง "Error Handling in AI — การจัดการและตั้งรับเมื่อ AI ตอบกลับสิ่งที่ไม่คาดคิด" พลาดไม่ได้เด็ดขาดครับ Gophers!
ฝากกดติดตามพวกเราได้ที่ Superdev Academy ในทุกช่องทางนะครับ!
🔵 Facebook: Superdev Academy Thailand (อัปเดตข่าวสารและบทความใหม่)
🎬 YouTube: Superdev Academy Channel (ติวเข้มแบบวิดีโอ)
📸 Instagram: @superdevacademy (เกร็ดความรู้สั้นๆ และเบื้องหลังการทำงาน)
🎬 TikTok: @superdevacademy (Tips & Tricks ฉบับย่อยง่าย)
🌐 Website: superdevacademy.com (คลังบทความและคอร์สเรียนฉบับเต็ม)