microservice ต้องมี observability แค่ไหน ถึงจะคุ้ม

작성자

카테고리:

← 피드로
DEV Community · Gophernment · 2026-07-09 개발(SW)

Gophernment

microservice ต้องมี observability แค่ไหน ถึงจะคุ้ม

มีเรื่องเล่าในทีมที่ผมเคยทำงานด้วย:

ระบบล่มตอนตี 2 — pager ดัง — dev ตื่นมาเปิด laptop
ใช้เวลา 45 นาทีแกะว่า error เกิดจาก service ไหน
พอรู้ว่าเป็น payment-service — ใช้เวลาอีก 20 นาทีไล่ว่า request นี้ผ่าน auth-serviceorder-servicepayment-service → แล้วพังที่ payment-service เพราะ inventory-service ตอบกลับมา 500

1 ชั่วโมง 5 นาที — เพื่อรู้ว่า “พังที่ inventory”

ถ้ามี tracing — รู้ใน 2 นาที

นี่คือเหตุผลที่ observability เกิด — แต่มันก็มีราคาที่ต้องจ่าย

observability คืออะไร

ไม่ใช่แค่ monitoring — monitoring บอกว่า “CPU 90%” — observability บอกว่า “CPU 90% เพราะเมื่อกี้มี request จาก order-service มา 10,000 requests ใน 1 นาที — และ 30% ของ requests พังที่ SELECT * FROM orders WHERE...

3 เสาหลัก:

ถามอะไร ตัวอย่าง 📊 Metrics “เกิดอะไรขึ้น?” CPU 90%, latency 2s, error rate 5% 📜 Logs “เกิดเพราะอะไร?” EROR: connection refused dial tcp 10.0.1.5:5432 🔍 Traces “ผ่านมาทางไหน?” gateway → auth → order → payment → inventory

monitoring = metrics — รู้ว่ามีปัญหา
observability = metrics + logs + traces — รู้ว่าปัญหาคืออะไร และเกิดที่ไหน

ทำไม microservice ถึงต้องการ observability มากกว่า monolith

เพราะ request เดียวผ่าน service เยอะ

Monolith:
  request → [app] → response
  log อยู่ที่เดียว — เปิดไฟล์เดียวเจอ

Microservice:
  request → gateway → auth → user → order → payment → inventory → ...
  log กระจาย 7 services — ไม่มีทางไล่เองไหว

Enter fullscreen mode Exit fullscreen mode

จำนวน service กับเวลา debug:

จำนวน service เวลาที่ใช้แกะว่า error อยู่ตรงไหน (เฉลี่ย) 1 (monolith) 5-10 นาที 5 15-30 นาที 10 30-60 นาที 20+ “ขอไปชงกาแฟก่อน”

นี่คือ exponential growth ของความซับซ้อน — ไม่ใช่ linear

เพราะไม่มีใคร “เห็นภาพรวม”

dev-A: "ผมดู log ของ payment-service แล้ว — มันพังที่ call external API"
dev-B: "แต่ external API มันรับ request จาก payment-service ปกตินะ"
dev-C: "เดี๋ยวนะ — payment-service ใช้ connection pool เก่าที่ถูก reset โดย auth-service"

Enter fullscreen mode Exit fullscreen mode

ทุกคนเห็นแค่สิ่งที่ตัวเองดูแล — ไม่มีใครเห็น flow ทั้งหมด — tracing คือเครื่องมือเดียวที่แก้ปัญหานี้ได้

ต้องแลกด้วยอะไร

เงิน

Datadog ทีม 20 services: ~$2,500/เดือน
Grafana self-host: ~$250/เดือน + engineer time

แต่เงินไม่ใช่ต้นทุนเดียว

เวลาตั้งค่า — และ maintain

สิ่งที่ต้องทำ:
1. ติดตั้ง OpenTelemetry SDK ในทุก service
2. ตั้งค่า collector — รับ data → ส่งไป backend
3. ตั้งค่า backend — Grafana/Prometheus/Datadog
4. สร้าง dashboard — อันนี้ใช้เวลาเยอะที่สุด
5. ตั้ง alert — ไม่งั้นมี dashboard แต่ไม่มีใครดู
6. onboard ทีม — สอนให้ทุกคนใช้เป็น

Enter fullscreen mode Exit fullscreen mode

ขั้นตอน 1-3 ใช้เวลาเป็นวัน ขั้นตอน 4-6 ใช้เวลาเป็นสัปดาห์ ถึงเดือน

Cognitive load

ทุก tool ที่เพิ่ม = ทุกอย่างที่ทีมต้องเรียนรู้และ maintain

ก่อน: รู้แค่ Go + Postgres + Docker
หลัง: รู้ Go + Postgres + Docker + Prometheus + Grafana + Loki + Tempo + OTel + ...

Enter fullscreen mode Exit fullscreen mode

ถ้าทีมมี 3 คน — เพิ่ม observability = เพิ่มภาระคนละ 20-30% — อาจไม่คุ้ม

Performance overhead

OTel SDK เพิ่ม latency ~1-5ms ต่อ request — และกิน memory ~10-50MB ขึ้นอยู่กับ sampling rate

Sampling 100% = เห็นทุก request แต่ performance hit สูง
Sampling 10% = เห็นแค่บางส่วน แต่แทบไม่มี overhead

Storage — ต้นทุนที่คนลืมคิด

traces กับ logs ใช้ storage มหาศาล — และ storage ไม่ได้ฟรี

ตัวอย่างจริง — 20 services, 1,000 req/s, 8 ชม/วัน:

Traces (sampling 100%, เก็บ 7 วัน):
  1,000 req/s × 3,600s × 8h = 28.8M requests/วัน
  เฉลี่ย 10 spans/request × ~2KB/span = ~576 GB/วัน
  เก็บ 7 วัน = ~4 TB

  ค่า storage (AWS S3): ~$90/เดือน
  ค่า storage (Grafana Cloud): ~$500/เดือน
  ค่า storage (Datadog): ~$2,000+/เดือน (คิดตาม ingestion + retention)

Enter fullscreen mode Exit fullscreen mode

และนี่คือ sampling 100% — ทีมส่วนใหญ่ sampling แค่ 10-20% — แต่ก็ยังเป็นตัวเลขที่มีนัยสำคัญ

Traces โตเร็วกว่าที่คิด (self-hosted storage — S3-compatible @ ~$22.50/TB):

เดือนที่ 1: 20 services, เก็บ 7 วัน → 4 TB → $90
เดือนที่ 6: เพิ่ม 10 services, เก็บ 30 วัน → 30 TB → $675
เดือนที่ 12: trace ละเอียดขึ้น, เก็บ 90 วัน → 120 TB → $2,700

Enter fullscreen mode Exit fullscreen mode

traces โตตาม services × retention × detail — ทั้งสามตัวมีแต่เพิ่ม ไม่เคยลด

วิธีคุม cost:

1. Sampling แบบหัว-ท้าย:
   - 100% เก็บเฉพาะ entry span (request เข้า)
   - 10% เก็บเต็มทุก span
   - error 100% เก็บหมด

2. Tail-based sampling:
   - ส่งทุก trace เข้า collector
   - collector ตัดสินใจเก็บเฉพาะ trace ที่ผิดปกติ (error, latency สูง)

3. ตั้ง retention policy:
   - traces: 3-7 วัน (พอ debug incident ล่าสุด)
   - metrics: 30-90 วัน (ดู trend)
   - logs: 7-14 วัน (debug)

Enter fullscreen mode Exit fullscreen mode

💡 กฏง่าย ๆ: storage cost ของ traces มักจะมากกว่า CPU cost ของ services ที่คุณ monitor — ถ้า traces cost > infra cost — คุณทำอะไรผิดซักอย่าง

แล้วเมื่อไหร่ถึงคุ้ม

คุ้ม — เมื่อ

1. ใช้เวลาดีบั๊ก production เกิน 30 นาทีต่อครั้ง

ถามตัวเอง: incident ครั้งล่าสุด — ใช้เวลาเท่าไหร่กว่าจะรู้ว่าเกิดอะไรขึ้น?

ถ้าตอบว่า “ไม่รู้” หรือ “เกิน 30 นาที” — observability คุ้มแน่

2. มี service >10 ตัว หรือทีม >5 คน

เส้นแบ่งคร่าว ๆ: monolith → observability “nice to have” — 5+ services → “ควรมี” — 10+ services → “ต้องมี”

3. downtime มีผลต่อ revenue

ถ้าทุกนาทีที่ระบบล่ม = เสียเงิน — observability คือประกัน — จ่าย $2K/เดือน ดีกว่าเสีย $50K/นาทีตอนระบบล่ม

ไม่คุ้ม — เมื่อ

1. มี service <5 ตัว — และทีม <3 คน

เปิด log ทีละ service ก็ยังไหว — observability อาจ overkill

2. ยังไม่มี incident บ่อย

ถ้า production ยังนิ่ง — เงินก้อนนั้นไปเพิ่ม feature ดีกว่า

3. กำลัง validate product-market fit

startup ระยะแรก — metrics สำคัญกว่า observability — รู้ว่า revenue เท่าไหร่สำคัญกว่ารู้ว่า request ผ่านกี่ hop

เริ่มยังไง — แบบไม่เจ็บ

อย่าเริ่มด้วย “ลง observability platform” — เริ่มด้วยการถาม:

“incident ครั้งล่าสุด — อะไรคือคำถามที่เราใช้เวลาหาคำตอบนานที่สุด?”

ระดับ 1: Structured Logging (ฟรี ใช้เวลา 1 วัน)

// แทนที่จะ log แบบนี้
log.Printf("user %s login failed", userID)

// log แบบนี้
slog.Error("login failed",
    slog.String("user_id", userID),
    slog.String("reason", "invalid_password"),
    slog.String("trace_id", traceID),
)

Enter fullscreen mode Exit fullscreen mode

trace_id คือกุญแจ — มันเชื่อม log ทุก service ที่ request นี้ผ่าน

💡 Level 1 ใช้ request-scoped ID (เช่น UUID จาก middleware) — ยังไม่ใช่ OTel trace ID จริง — Level 2 จะแทนที่ด้วย trace_id จาก span context ที่เชื่อมข้าม service ได้จริง

ระดับ 2: Tracing (ฟรี ค่อยเป็นค่อยไป)

เริ่มจากเพิ่ม span ในแต่ละ function:

import "go.opentelemetry.io/otel"

func GetUser(ctx context.Context, id string) (*User, error) {
    ctx, span := otel.Tracer("user-service").Start(ctx, "GetUser")
    defer span.End()
    // ... โค้ดเดิม
}

Enter fullscreen mode Exit fullscreen mode

แต่นั่นทำให้เห็นแค่ span ภายใน process เดียว — ยังไม่เห็น flow ข้าม service

สิ่งที่ขาด — trace context propagation:

// HTTP client — inject traceparent header ให้เรียกข้าม service
import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"

client := &http.Client{Transport: otelhttp.NewTransport(http.DefaultTransport)}
resp, _ := client.Get("http://payment-service/charge")  // trace_id ตามไปอัตโนมัติ

// HTTP server — extract traceparent จาก request ขาเข้า
handler := otelhttp.NewHandler(mux, "order-service")

Enter fullscreen mode Exit fullscreen mode

ถ้า order-service ใช้ otelhttp.NewTransport ตอนเรียก payment-service — span ของทั้งสอง service จะถูก link เป็น trace เดียวกัน — นี่คือสิ่งที่ทำให้ “รู้ใน 2 นาที” จากบทนำเป็นจริง

การเพิ่ม span ใช้ ~3 บรรทัดต่อ function — otelhttp.NewTransport/NewHandler ใช้ 1 บรรทัด — ได้ tracing ทั้งระบบ โดยไม่ต้องเขียน propagation logic เอง

💡 หลักการเดียวกับ PII ใน log — ใช้กับ span attributes ด้วย: ห้ามใส่ email, user_id, order_id เป็น span tag — ใช้ trace_id + log correlation แทน

ระดับ 3: Dashboard + Alert (เริ่มมีค่าใช้จ่าย)

เริ่มจาก Grafana Cloud Free → ดู metrics + traces → ตั้ง alert เฉพาะ critical path

สรุป — คุ้มไหม

monolith → observability = nice to have
microservice → observability = requirement ไม่ใช่ feature

Enter fullscreen mode Exit fullscreen mode

แต่ requirement ไม่ได้แปลว่าต้องทำเต็มรูปแบบ — เริ่มจาก structured logging + tracing (ฟรี, ใช้เวลาไม่นาน) — แล้วค่อยขยับไป dashboard + alert เมื่อเริ่มรู้สึกว่า “หา bug นานเกินไป”

และที่สำคัญ: อย่าตั้ง budget observability จากการ copy-paste plan ของทีม 300 คน — ทีม 5 คนต้องการ observability คนละแบบกับทีม 50 คน

📚 อ่านต่อ:

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다