Monitoring Strategy: เลือก Metrics ที่ควร Monitor

ปัญหาที่ทีม DevOps เจอบ่อยที่สุดไม่ใช่ “Metrics ไม่พอ” แต่เป็น “Metrics เยอะเกินจนไม่รู้จะดูอะไร” หรือในอีกมุมคือ เก็บทุกอย่างแต่ไม่มี Metric ไหนบอกได้ว่า “ระบบกำลังมีปัญหาหรือเปล่า” การเลือก Metrics ที่ถูกต้องตั้งแต่ต้นจึงเป็นเรื่องสำคัญ เพราะทุก Metric ที่เก็บต้องเสียค่า storage, ค่า ingestion, และต้นทุน alert fatigue เมื่อ dashboard ถูกท่วมด้วยข้อมูลที่ไม่จำเป็น

บทความนี้จะพาไปทำความเข้าใจ “กลยุทธ์” ในการเลือก Metrics — เริ่มจากกรอบคิดยอดนิยมอย่าง USE Method และ RED Method ต่อด้วย Four Golden Signals ของ Google SRE ไปจนถึงวิธีจัดลำดับความสำคัญของ Metrics, การตัดสินใจว่าอะไรควรเก็บและอะไรไม่ควร รวมถึงการหลีกเลี่ยง cardinality explosion ที่ทำให้ระบบ monitoring ล่มเอง

ทำไมต้องมีกลยุทธ์ในการเลือก Metrics

ก่อนจะลงรายละเอียด มาพิจารณาปัญหาจริงที่เกิดขึ้นเมื่อไม่มีกลยุทธ์ที่ชัดเจน ทีมหนึ่งอาจ scrape ทุก default metric ของทุก exporter — บางครั้งเก็บมากกว่า 50,000 time series ต่อโฮสต์ ต้นทุน storage พุ่งเดือนละหลักแสน แต่เมื่อเกิดเหตุการณ์จริง วิศวกรกลับต้องใช้เวลา 30 นาทีในการหา Metric ที่ชี้ปัญหาได้ ในทางกลับกัน ทีมที่เก็บน้อยแต่ตรงจุด มักจะรู้ตัวก่อนและ recovery ได้เร็วกว่า

สิ่งที่ทำให้ Metrics มีคุณค่าไม่ใช่ “จำนวน” แต่คือ “ความสามารถในการตอบคำถามสำคัญ” เช่น ระบบตอนนี้สุขภาพดีหรือเปล่า, ถ้ามีปัญหา ปัญหาอยู่ตรงไหน, เรากำลังละเมิด SLO กับผู้ใช้หรือไม่ การเริ่มจาก “คำถามที่อยากตอบ” แล้วค่อย reverse-engineer ว่าต้องเก็บ Metric อะไร จะได้ชุดข้อมูลที่เล็กกว่าและมีประโยชน์มากกว่า

USE Method — กรอบคิดสำหรับ Resources

USE Method ถูกเสนอโดย Brendan Gregg สำหรับการวิเคราะห์ปัญหาด้าน performance ของระบบที่ระดับ infrastructure หลักคิดคือ ทุก resource (CPU, Memory, Disk, Network, etc.) ควรถูกวัดด้วย 3 มิติ คือ Utilization, Saturation และ Errors

มิติความหมายตัวอย่าง Metric
Utilization% เวลาที่ resource ทำงานCPU busy %, disk I/O busy %
Saturationงานที่ค้างรอ / เกินขีดความสามารถrun queue length, swap used
Errorsจำนวน error ที่ resource รายงานdisk I/O errors, network drops

USE Method เหมาะกับการวิเคราะห์ bottleneck ระดับ host หรือ container เพราะทำให้ผู้ดูแลระบบโฟกัสไปที่ resource ที่มีปัญหาแทนที่จะไล่ดู Metric ทีละตัว เช่น หากเห็น run queue ยาวขณะที่ CPU utilization แค่ 60% แสดงว่าอาจมีปัญหา context switching หรือ I/O blocking — ต่างจากการดูแต่ CPU % ที่อาจดู “ปกติ”

ตัวอย่าง USE Checklist สำหรับ Linux Server

  • CPU: node_cpu_seconds_total (utilization), node_load1 (saturation), hardware errors จาก MCE
  • Memory: node_memory_MemAvailable_bytes (utilization), node_vmstat_pswpout (saturation), OOM kill count
  • Disk: node_disk_io_time_seconds_total (utilization), node_disk_io_time_weighted_seconds_total (saturation), I/O error count
  • Network: bytes in/out (utilization), node_netstat_Tcp_RetransSegs (saturation), drops + errors

RED Method — กรอบคิดสำหรับ Services

ถ้า USE Method เน้น resource ตอน RED Method ที่เสนอโดย Tom Wilkie จะเน้นไปที่ service หรือ request-driven workload ซึ่งเป็นส่วนใหญ่ของ microservices วันนี้ ทุก service ควรมี 3 ตัวชี้วัดนี้เป็นอย่างน้อย

  • Rate: จำนวน request ต่อวินาที (throughput) — วัดด้วย Counter
  • Errors: จำนวน request ที่ล้มเหลวต่อวินาที — แยกตาม status code
  • Duration: เวลาที่ใช้ในการ process — วัดด้วย Histogram และดู p50/p95/p99

จุดเด่นของ RED Method คือเข้าใจง่าย และสามารถ apply กับทุก service ที่มี request pattern ได้ — ตั้งแต่ HTTP API, gRPC, message consumer ไปจนถึง database query layer การใช้ label เช่น method, route, status ช่วยให้ drill-down ได้ระดับ endpoint โดยไม่ต้องสร้าง dashboard แยก

ตัวอย่าง PromQL สำหรับ RED Method

# Rate: request per second แยกตาม route
sum by (route) (rate(http_requests_total[5m]))

# Errors: % ของ 5xx เทียบกับ total
sum(rate(http_requests_total{status=~"5.."}[5m]))
  / sum(rate(http_requests_total[5m]))

# Duration: p99 latency
histogram_quantile(0.99,
  sum by (le, route) (rate(http_request_duration_seconds_bucket[5m]))
)

Four Golden Signals — แนวทางของ Google SRE

ในหนังสือ Site Reliability Engineering ของ Google ได้แนะนำ “Four Golden Signals” ซึ่งคล้ายกับ RED Method แต่เพิ่ม Saturation เข้ามา เพื่อให้ครอบคลุมทั้ง request-driven และ resource-driven workload ไปพร้อมกัน

Signalคำอธิบายคำถามที่ตอบ
Latencyเวลา process request (success vs failed แยกกัน)“ผู้ใช้รอแล้วรำคาญหรือยัง?”
Trafficปริมาณงานที่เข้ามา“เราเห็นโหลดจริงเท่าไร?”
Errorsrequest ที่ล้มเหลว (explicit หรือ wrong answer)“ผู้ใช้ประสบกับ failure กี่คน?”
Saturationระบบเต็มขีดความสามารถแค่ไหน“เราใกล้ breakdown หรือยัง?”

ข้อแนะนำสำคัญของ Google คือ ให้ “แยก latency ของ success ออกจาก failed” เพราะถ้ารวมกัน error ที่ fail fast อาจทำให้ latency ดูต่ำกว่าความจริง ซ่อนปัญหา degradation ที่กำลังเกิดขึ้น

Prioritization — เลือก Metric อะไรก่อน

สำหรับทีมที่เพิ่งเริ่มตั้ง monitoring stack คำถามจริงคือ “เอาอะไรก่อน” เพราะถ้าพยายามเก็บทุกอย่างตั้งแต่วันแรก จะจมอยู่กับ infra setup ไม่ได้เริ่ม observe จริง ลำดับที่แนะนำคือ

  1. User-facing SLI ก่อน: availability + latency ของ endpoint ที่ผู้ใช้ใช้จริง (เช่น login, checkout, home page) เพราะเป็นตัวชี้วัดที่ตรงกับประสบการณ์ของลูกค้ามากที่สุด
  2. RED ของทุก service: เมื่อมี SLI แล้วให้กระจาย Rate/Errors/Duration ไปยังทุก service เพื่อ drill-down เมื่อ SLI ละเมิด
  3. USE ของ infrastructure critical: database, cache, message queue — resource ที่ถ้าล้มจะทำให้ทุก service ล้มตาม
  4. Business metrics: order per minute, signup rate, payment success ratio — ช่วยให้เชื่อม technical metric กับ business outcome
  5. Dependency health: upstream/downstream service latency, external API error rate

ลำดับนี้มาจากหลักคิดว่า “monitoring ที่ดีเริ่มจากสิ่งที่ผู้ใช้รับรู้” ไม่ใช่จาก infrastructure ขึ้นไป เพราะการที่ CPU เต็ม 100% อาจจะไม่สำคัญเลย ถ้าผู้ใช้ยังได้รับบริการปกติ แต่การที่ latency เพิ่ม 200ms อาจทำให้ conversion rate ลด 5% ทันที

การเลือก SLI — ตัวชี้วัดที่สะท้อนประสบการณ์ผู้ใช้

Service Level Indicator (SLI) คือ Metric ที่ถูกเลือกมาเป็น “ตัวแทน” ของความน่าเชื่อถือของ service การเลือก SLI ที่ดีต้องมีคุณสมบัติคือ วัดได้จากมุมของผู้ใช้, มีความสัมพันธ์เชิงเหตุผลกับความพอใจ, และสามารถ aggregate เป็นตัวเลขเดียวได้ (เช่น % success ratio)

ตัวอย่าง SLI ที่ใช้กันบ่อยในแต่ละประเภท service:

ประเภท ServiceSLI ที่แนะนำ
HTTP API% request ที่ return 2xx/3xx ภายใน 500ms
Background Job% job ที่สำเร็จภายใน SLO queue time
Storage% read ที่ return ข้อมูลถูกต้องภายใน 100ms
Streaming / Pipeline% event ที่ถึงปลายทางภายใน freshness window
Database% query ที่สำเร็จภายใน p99 threshold

ข้อผิดพลาดที่เห็นบ่อยคือ การตั้ง SLI เป็น “CPU utilization น้อยกว่า 80%” ซึ่งไม่เกี่ยวกับประสบการณ์ผู้ใช้เลย SLI ควรวัดผลลัพธ์ (outcome) ไม่ใช่สาเหตุ (cause) — CPU สูงอาจเป็นแค่ symptom ของการ process งานมาก ซึ่งเป็นเรื่องปกติ

Cardinality Budget — กันระบบ monitoring ล่มเอง

Cardinality คือจำนวน unique combination ของ label values ที่ Metric หนึ่งสร้างขึ้น ตัวอย่างเช่น http_requests_total{method, route, status, user_id} ถ้า user_id มี 1 ล้านค่า คูณกับ method 5 × route 20 × status 10 จะได้ time series 1 พันล้าน series ซึ่งเป็นจำนวนที่ Prometheus รับไม่ไหว

หลักการเลือก label มี 3 ข้อคือ: (1) label ต้องมี cardinality จำกัด — ใช้ค่าที่ enumerate ได้ (2) label ต้องช่วยตอบคำถาม operational — ถ้าไม่เคยถูกใช้ใน query/alert ก็ไม่ควรมี (3) หลีกเลี่ยง label ที่รับ input ตรงจากผู้ใช้ เช่น query string หรือ user ID — ใช้ bucket หรือ tier แทน

กฎหัวแม่โป้งสำหรับ cardinality

  • Metric หนึ่งตัวไม่ควรมี active series เกิน 10,000 (เฉพาะกรณีทั่วไป)
  • Label ที่เป็น ID ของ entity (user, session, order) ห้ามใช้กับ metric — ให้ใช้ logs หรือ traces แทน
  • ถ้าต้องการ drill-down ระดับ per-customer ให้พิจารณา top-N customer เป็น label หรือใช้ tier (enterprise/pro/free)
  • ตรวจสอบ cardinality ก่อน deploy ด้วย count by (__name__) ({__name__=~".+"}) หรือ prometheus_tsdb_symbol_table_size_bytes

Metric Naming Convention

Metric name เป็นเอกสารสำหรับตัวเอง (self-documenting) ชื่อที่ดีจะช่วยให้ทีมใหม่เข้ามาแล้วเข้าใจได้ทันทีว่าแต่ละตัวเก็บอะไร Prometheus แนะนำรูปแบบ namespace_subsystem_name_unit โดย

  • namespace: ชื่อ service หรือ domain เช่น order, payment, http
  • subsystem: ส่วนย่อยของ service เช่น server, client, cache
  • name: สิ่งที่ถูกวัด เช่น requests, duration, items
  • unit: หน่วยวัดชัดเจน เช่น seconds, bytes, total (สำหรับ counter)

ตัวอย่างที่ดี: http_request_duration_seconds, db_connection_pool_size, queue_messages_received_total — ตัวอย่างที่ควรหลีกเลี่ยง: rt, qps, a1 — ชื่อสั้นเกินไปจะไม่สื่อความหมาย และเมื่อ scale เป็น service หลายร้อยตัว จะกลายเป็นหนี้ทางเทคนิคทันที

Metrics ที่ควรหลีกเลี่ยงหรือลดเก็บ

ไม่ใช่ทุก default metric ของ exporter ที่จำเป็น บางตัวมีค่า debug ที่ใช้ครั้งเดียวหรือถูก override ด้วย signal อื่นแล้ว ทีมที่มี budget จำกัดควรพิจารณาปิด metric กลุ่มนี้

  • Per-process detail ของ node_exporter: ถ้าไม่ได้ debug ระดับ process มักจะซ้ำซ้อนกับ cadvisor
  • Histogram buckets ละเอียดเกิน: 20+ buckets ต่อ endpoint ทำให้ cardinality พุ่ง — เริ่มจาก 8-10 buckets ที่สำคัญ
  • GC metric ภาษาระดับลึก: เก็บไว้เฉพาะตอน debug memory leak ส่วนใหญ่ไม่ต้อง scrape ทุก 15s
  • Kubernetes object count ทุก namespace: ใช้ filter เอาเฉพาะ namespace production
  • Metric ที่มี id / uuid เป็น label: ย้ายไป tracing หรือ structured log แทน

การทบทวน Metrics อย่างต่อเนื่อง

Metric ไม่ใช่สิ่งที่ตั้งแล้วลืม ทุก quarter ทีมควรทบทวนว่า Metric ใดถูกใช้งานจริงใน dashboard และ alert การใช้ PromQL อย่าง topk(100, count by (__name__)({__name__=~".+"})) ช่วยหา Metric ที่มี series เยอะที่สุด ส่วน prometheus_rule_evaluation_duration_seconds ช่วยหา rule ที่ช้าเกินไป การตัด Metric ที่ไม่ถูกใช้งานภายใน 90 วันออก เป็นวิธีหนึ่งในการควบคุมต้นทุน

อีกเทคนิคคือการใช้ recording rule เพื่อ pre-compute aggregation ที่ถูก query บ่อย เช่น service-level success ratio — แทนที่จะคำนวณทุกครั้งที่เปิด dashboard ให้เก็บเป็น rule แล้ว query จาก rule output ประหยัด CPU ของ Prometheus ลงไม่น้อย

กรณีศึกษา: กลยุทธ์ Metric ของ e-commerce

สมมติเราดูแลเว็บไซต์ขายของออนไลน์ที่มี microservice ประมาณ 20 service ลำดับการเลือก Metric อาจเป็นดังนี้ เริ่มจาก user-facing SLI คือ “% ของ checkout ที่สำเร็จภายใน 3 วินาที” จาก API Gateway ตามด้วย RED ของ service หลัก 5 ตัว (catalog, cart, checkout, payment, shipping) พร้อม label method, endpoint, status_code (ไม่ใส่ user_id)

เติมด้วย USE ของ infrastructure critical คือ PostgreSQL connection pool, Redis memory, Kafka consumer lag จากนั้นเพิ่ม business metric ระดับบนสุดคือ orders_total, checkout_abandoned_total, payment_failed_total แยก label เป็น payment_method (3-5 ค่า) ไม่ใช่ per-transaction สุดท้ายเพิ่ม dependency health เช่น latency ของ payment gateway ภายนอก

ผลลัพธ์คือประมาณ 200-400 metric names กระจายตัวเป็น active series ~30,000 ซึ่งเล็กพอให้ Prometheus instance เดียวรับได้ แต่ใหญ่พอที่จะตอบคำถามสำคัญทั้งในเชิง technical และ business

ข้อผิดพลาดที่พบบ่อย

  • เก็บทุก default metric โดยไม่ filter: ส่ง metric ที่ไม่มีใครใช้ไปให้ Prometheus — เสียทั้ง storage และ CPU
  • ไม่แยก success/failure latency: รวมกันทำให้ p99 ดูต่ำกว่าความจริง ซ่อน degradation
  • ตั้ง alert บน resource ไม่ใช่ symptom ของผู้ใช้: alert CPU 90% แต่ผู้ใช้ยังดี → alert fatigue
  • ใช้ label ที่เป็น free-form string: เช่น error_message → cardinality explosion ใน 1 วัน
  • ไม่รีวิว Metric เก่า: dashboard ที่ไม่มีใครเปิดยังคง rule evaluate → ต้นทุนแฝง
  • ไม่มีการลงทะเบียน Metric ใหม่: ทุกทีมสร้าง metric เอง ไม่มีรูปแบบชื่อร่วมกัน → dashboard ซ้ำซ้อน

สรุป

การเลือก Metrics ที่ดีคือการ “ตัดสินใจสิ่งที่ไม่เก็บ” ให้ได้พอๆ กับ “เลือกสิ่งที่เก็บ” เริ่มจากกรอบคิดที่เหมาะกับ workload ของคุณ — USE สำหรับ infrastructure, RED สำหรับ service, Four Golden Signals เมื่อต้องการความครอบคลุม ให้ priority กับ user-facing SLI ก่อนเสมอ เพราะ Metric ที่สะท้อนประสบการณ์ผู้ใช้มีคุณค่ามากกว่า Metric ภายใน

อย่าลืมว่าทุก Metric มีต้นทุน ทั้ง storage, ingestion, และ cognitive load ของทีม การตั้ง cardinality budget, การเลือก label อย่างรอบคอบ, และการทบทวน Metric ทุกไตรมาสคือสิ่งที่ทำให้ monitoring stack scale ได้ในระยะยาวโดยไม่กลายเป็นภาระเอง