Monitoring DevOps Observability

Monitoring & Observability — รู้ทุกอย่างที่เกิดขึ้นใน SystemMonitoring & Observability — Knowing Everything That Happens Inside the System

By Anirach Mingkhwan DevOps & Vibe Coding 2026
Observability — รู้ทุกอย่างที่เกิดขึ้นในระบบ
ในบทความนี้
  1. Monitoring vs Observability — ต่างกันยังไง?
  2. 3 Pillars of Observability
  3. Pillar 1: Metrics — ตัวเลขที่ต้องจับตา
  4. Prometheus + Grafana — Metrics Stack ยอดนิยม
  5. Pillar 2: Logs — บันทึกเหตุการณ์
  6. Pillar 3: Traces — ติดตาม Request
  7. Alerting — แจ้งเตือนก่อนพัง
  8. Monitoring Stack ยอดนิยม
  9. 4 Golden Signals (Google SRE)
  10. สรุป
In this post
  1. Monitoring vs Observability — What's the Difference?
  2. 3 Pillars of Observability
  3. Pillar 1: Metrics — The Numbers to Watch
  4. Prometheus + Grafana — The Most Popular Metrics Stack
  5. Pillar 2: Logs — The Record of Events
  6. Pillar 3: Traces — Following a Request
  7. Alerting — Warning You Before It Breaks
  8. Popular Monitoring Stacks
  9. 4 Golden Signals (Google SRE)
  10. Summary

จากโพสต์ที่แล้วเราเรียนรู้ IaC — ใช้ Terraform สร้าง infrastructure และ Ansible ตั้งค่า server อัตโนมัติ

แต่หลังจาก deploy ขึ้น production แล้ว... จะรู้ได้ยังไงว่า app ทำงานปกติ? Server จะล่มตอนไหน? User กำลังเจอ error อะไร? 🔍

นี่คือที่มาของ Monitoring & Observability — ระบบที่ทำให้เรา "มองเห็น" ทุกอย่างที่เกิดขึ้นข้างใน เหมือน DevOps Engineer ที่นั่งจ้องจอ dashboard ตลอดเวลา 🐕‍🦺📊


Monitoring vs Observability — ต่างกันยังไง?

หลายคนใช้สองคำนี้แทนกัน แต่จริงๆ ต่างกัน — Monitoring คือ "ดูว่าระบบยังทำงานปกติไหม" (CPU สูงไหม? disk เต็มไหม? error rate เพิ่มไหม?) เป็นการถามคำถามที่ "รู้อยู่แล้ว" ส่วน Observability คือ "สามารถเข้าใจได้ว่าระบบเป็นยังไงจากข้อมูลที่ส่งออกมา" — ตอบคำถามที่ "ยังไม่เคยถาม" ได้ เหมาะกับ microservices ที่ complex และ failure modes คาดเดาไม่ได้:

Monitoring Observability
ตอบว่า "มีปัญหามั้ย?" ตอบว่า "ทำไมถึงมีปัญหา?"
ตรวจสิ่งที่เรา รู้ล่วงหน้า หาสิ่งที่เรา ไม่เคยคิดถึง
Dashboard + Alerts Explore + Drill-down + Correlate
CPU สูง → แจ้งเตือน ทำไม CPU สูง? → trace → พบ query ช้า
💡 จำง่ายๆ: Monitoring = ติดกล้องวงจรปิด | Observability = มีนักสืบวิเคราะห์ภาพ

3 Pillars of Observability

ระบบ Observability ที่ดีต้องมีข้อมูล 3 ประเภทที่ทำงานเสริมกัน — Metrics บอกว่า "มีปัญหาไหม" (ตัวเลข), Logs บอกว่า "เกิดอะไรขึ้น" (events), Traces บอกว่า "ช้าตรงไหน" (request flow) ขาดอันใดอันหนึ่งก็ debug ยาก:

📊
Metrics
ตัวเลขที่วัดได้ เช่น CPU %, memory, request/sec, error rate
📝
Logs
บันทึกเหตุการณ์ เช่น error messages, access logs, debug info
🔗
Traces
ติดตาม request ผ่านทุก service ว่าช้าตรงไหน

Pillar 1: Metrics — ตัวเลขที่ต้องจับตา

Metrics คือตัวเลขที่วัดได้ตามเวลา (time-series data) — CPU usage 72%, response time 230ms, error rate 0.5% เหมาะกับ alerting (แจ้งเตือนเมื่อเกินเกณฑ์) และ trending (ดู pattern ระยะยาว) Metrics แบ่งเป็น 3 ระดับ:

System Metrics

System metrics วัดสุขภาพของ infrastructure — CPU, Memory, Disk, Network ทุก server ต้องมี เป็นตัวบอกว่า "เครื่องจะล่มเมื่อไร":

  • CPU Usage — เครื่องทำงานหนักแค่ไหน
  • Memory Usage — RAM เหลือเท่าไหร่
  • Disk I/O — อ่าน/เขียน disk เร็วแค่ไหน
  • Network I/O — bandwidth ใช้ไปเท่าไหร่

Application Metrics (RED Method)

RED Method (Rate, Errors, Duration) คือ metrics ที่วัดจากมุมผู้ใช้ — request มาเท่าไร? error กี่ %? ตอบช้าแค่ไหน? สำคัญกว่า system metrics เพราะบอกได้ว่า "user experience ดีไหม":

  • Rate — จำนวน request/sec
  • Errors — เปอร์เซ็นต์ error (5xx)
  • Duration — response time (p50, p95, p99)

Business Metrics

Business metrics เชื่อม technical data กับ business impact — ยอดสั่งซื้อต่อนาที, signup rate, cart abandonment rate ช่วยตอบคำถามเช่น "ระบบช้าขึ้น 200ms ส่งผลกระทบต่อยอดขายไหม?":

  • Active Users — คนใช้งานอยู่กี่คน
  • Orders/min — คำสั่งซื้อต่อนาที
  • Revenue — รายได้ real-time
💡 RED Method: ใช้กับ services (Rate, Errors, Duration)
USE Method: ใช้กับ resources (Utilization, Saturation, Errors)

Prometheus + Grafana — Metrics Stack ยอดนิยม

Prometheus เป็น metrics database (TSDB) ที่เก็บข้อมูลแบบ time-series — ใช้ "pull model" คือ Prometheus ดึงข้อมูลจาก targets (servers, apps) ทุก 15 วินาที ส่วน Grafana เป็น dashboard tool ที่แสดง metrics เป็นกราฟสวยๆ ทั้งคู่เป็น open-source, CNCF graduated projects, และเป็น industry standard:

🎯 App
expose /metrics
→
📦 Prometheus
scrape + store
→
📊 Grafana
visualize + alert

ตั้งค่า Prometheus

ไฟล์ prometheus.yml:

global:
  scrape_interval: 15s        # ดึง metrics ทุก 15 วินาที

scrape_configs:
  # Monitor ตัว Prometheus เอง
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  # Monitor Node (เครื่อง server)
  - job_name: 'node'
    static_configs:
      - targets:
        - 'server1:9100'
        - 'server2:9100'
        - 'server3:9100'

  # Monitor App
  - job_name: 'myapp'
    metrics_path: '/metrics'
    static_configs:
      - targets: ['app:3000']

Docker Compose สำหรับ Monitoring Stack

Setup monitoring stack ได้ง่ายด้วย Docker Compose — Prometheus + Grafana + Node Exporter (system metrics) + cAdvisor (container metrics) พร้อมใช้งานในไม่กี่นาที:

version: '3.8'
services:
  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3001:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=secret
    volumes:
      - grafana_data:/var/lib/grafana

  node-exporter:
    image: prom/node-exporter:latest
    ports:
      - "9100:9100"
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro

volumes:
  prometheus_data:
  grafana_data:
# รัน monitoring stack
docker compose up -d

# เข้า Prometheus: http://localhost:9090
# เข้า Grafana:    http://localhost:3001 (admin/secret)

PromQL — Query ข้อมูลจาก Prometheus

PromQL คือ query language ของ Prometheus — ใช้คำนวณ metrics ที่ต้องการ เช่น error rate ใน 5 นาที, 95th percentile latency, CPU usage เฉลี่ย เรียนรู้ PromQL เป็นทักษะสำคัญสำหรับ DevOps:

# CPU usage เฉลี่ย 5 นาที
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# Request rate ต่อวินาที
rate(http_requests_total[5m])

# Error rate (%)
rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) * 100

# 95th percentile response time
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))

# Memory usage (%)
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100

Pillar 2: Logs — บันทึกเหตุการณ์

Logs คือบันทึกเหตุการณ์ที่เกิดขึ้นในระบบ — "user X login สำเร็จ", "payment failed: insufficient funds", "database connection timeout" Metrics บอกว่า "มีปัญหา" แต่ Logs บอกว่า "เกิดอะไรขึ้นจริงๆ" สำคัญมากตอน debug

Structured Logging — ดีกว่า plain text!

แทนที่จะ log แบบ plain text ("User john logged in") ให้ใช้ structured logging (JSON format) — ทำให้ search, filter, aggregate ได้ง่าย ถามว่า "error ทั้งหมดของ user X ใน 1 ชั่วโมงที่แล้ว" ตอบได้ทันที:

// ❌ Bad — ยากต่อการ parse
console.log("User login failed for user123");

// ✅ Good — structured JSON
logger.error({
  event: "login_failed",
  userId: "user123",
  reason: "invalid_password",
  ip: "203.0.113.50",
  timestamp: "2026-03-07T09:00:00Z"
});

Log Levels

Log levels ช่วยแยกความสำคัญ — production ควร log แค่ INFO ขึ้นไป (ไม่ต้อง DEBUG เพราะ volume สูงมาก) เมื่อมีปัญหาค่อยเปิด DEBUG ชั่วคราว:

Level ใช้เมื่อ ตัวอย่าง
ERROR เกิดข้อผิดพลาดจริง Database connection failed
WARN อาจมีปัญหาในอนาคต Disk usage > 80%
INFO เหตุการณ์ปกติที่สำคัญ Server started on port 3000
DEBUG รายละเอียดสำหรับ debug Query result: 42 rows

ELK Stack — Centralized Logging

เมื่อมีหลาย servers/containers การ SSH เข้าไปดู log ทีละเครื่องไม่ work — ต้องมี centralized logging ที่รวม logs ทั้งหมดมาที่เดียว ELK Stack (Elasticsearch + Logstash + Kibana) เป็น solution ยอดนิยม:

📱 Apps
ส่ง logs
→
🚛 Logstash
collect + transform
→
🔍 Elasticsearch
store + search
→
📊 Kibana
visualize + explore

ทางเลือกที่เบากว่า: Loki + Promtail + Grafana (ใช้ Grafana เดิมได้เลย!)

# Loki + Promtail Docker Compose
services:
  loki:
    image: grafana/loki:latest
    ports:
      - "3100:3100"

  promtail:
    image: grafana/promtail:latest
    volumes:
      - /var/log:/var/log:ro
      - ./promtail.yml:/etc/promtail/config.yml

Pillar 3: Traces — ติดตาม Request

เมื่อ 1 request ต้องผ่านหลาย services (microservices) เราจะรู้ได้ยังไงว่า ช้าตรงไหน?

🌐 API Gateway
2ms
→
👤 User Service
15ms
→
💳 Payment Service
850ms ⚠️
→
📧 Email Service
45ms

Trace ช่วยให้เห็นว่า Payment Service ใช้เวลา 850ms — นั่นคือ bottleneck!

เครื่องมือ Tracing

เครื่องมือ tracing หลักๆ — Jaeger (CNCF, open-source, ใช้กับ Kubernetes ดี), Zipkin (โดย Twitter, lightweight), OpenTelemetry (มาตรฐานใหม่ที่รวม metrics+logs+traces เป็น vendor-neutral SDK):

  • Jaeger — open-source, จาก Uber
  • Zipkin — open-source, จาก Twitter
  • OpenTelemetry — standard ใหม่ (รวม metrics + logs + traces)
  • Datadog APM / New Relic — commercial (ง่ายแต่แพง)
// OpenTelemetry ตัวอย่าง (Node.js)
const { trace } = require('@opentelemetry/api');

const tracer = trace.getTracer('my-service');

app.get('/api/checkout', async (req, res) => {
  const span = tracer.startSpan('checkout');

  try {
    // แต่ละขั้นตอนมี child span
    const userSpan = tracer.startSpan('get-user', { parent: span });
    const user = await getUser(req.userId);
    userSpan.end();

    const paySpan = tracer.startSpan('process-payment', { parent: span });
    await processPayment(user, req.amount);
    paySpan.end();

    res.json({ status: 'success' });
  } catch (err) {
    span.setStatus({ code: 2, message: err.message });
    res.status(500).json({ error: err.message });
  } finally {
    span.end();
  }
});

Alerting — แจ้งเตือนก่อนพัง

Dashboard สวยแค่ไหนก็ไม่ช่วย ถ้าไม่มีใครดู — ต้องมี Alert!

Alert Rules (Prometheus)

Alert rules กำหนดว่า "เมื่อ condition X เป็นจริงนาน Y นาที → แจ้งเตือน" สิ่งสำคัญคือ for duration ป้องกัน false alarms จาก spikes ชั่วคราว และ labels/annotations ช่วยให้ on-call team เข้าใจปัญหาเร็ว:

# alert-rules.yml
groups:
  - name: critical
    rules:
      # Server down
      - alert: InstanceDown
        expr: up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "{{ $labels.instance }} is down!"

      # CPU สูงเกิน 90% นาน 5 นาที
      - alert: HighCPU
        expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "CPU > 90% on {{ $labels.instance }}"

      # Error rate สูงเกิน 5%
      - alert: HighErrorRate
        expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) * 100 > 5
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Error rate > 5% on {{ $labels.job }}"

      # Disk เหลือน้อยกว่า 10%
      - alert: DiskSpaceLow
        expr: (node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 < 10
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Disk < 10% on {{ $labels.instance }}"

Alert ส่งไปไหน? (Alertmanager)

Alertmanager รับ alerts จาก Prometheus แล้วส่งต่อไปยัง channels ที่เหมาะสม — Slack, PagerDuty, email, webhook รองรับ grouping (รวม alerts เดียวกัน), silencing (ปิดเสียงชั่วคราว), และ routing (critical → PagerDuty, warning → Slack):

# alertmanager.yml
route:
  receiver: 'team-slack'
  routes:
    - match:
        severity: critical
      receiver: 'pagerduty'     # Critical → ปลุกคนมาแก้!
    - match:
        severity: warning
      receiver: 'team-slack'    # Warning → แจ้งใน Slack

receivers:
  - name: 'team-slack'
    slack_configs:
      - api_url: 'https://hooks.slack.com/services/xxx'
        channel: '#alerts'
        title: '🚨 {{ .GroupLabels.alertname }}'
        text: '{{ .CommonAnnotations.summary }}'

  - name: 'pagerduty'
    pagerduty_configs:
      - service_key: 'your-pagerduty-key'
🐕 Alert Fatigue: อย่าตั้ง alert ทุกอย่าง! ถ้าแจ้งเตือนเยอะเกิน คนจะเพิกเฉย → Critical = ต้อง action ทันที | Warning = ดูภายในวัน | Info = ดูเมื่อว่าง

Monitoring Stack ยอดนิยม

มี monitoring tools มากมาย — ตารางด้านล่างเปรียบเทียบ stack ยอดนิยมทั้ง open-source และ commercial ช่วยเลือกตามความต้องการ (budget, scale, complexity):

Stack ส่วนประกอบ จุดเด่น
PLG Prometheus + Loki + Grafana Open-source, K8s friendly, ครบ 3 pillars
ELK Elasticsearch + Logstash + Kibana Log search ดีมาก, enterprise
TIG Telegraf + InfluxDB + Grafana IoT/time-series ดี
Datadog All-in-one SaaS ง่ายสุด แต่แพง
New Relic All-in-one SaaS APM ดี, free tier

4 Golden Signals (Google SRE)

4 Golden Signals จาก Google SRE Book — ถ้า monitor ได้แค่ 4 อย่าง ให้เลือก 4 ตัวนี้ ครอบคลุม user experience ทั้งหมด Latency บอกประสบการณ์, Traffic บอก demand, Errors บอกคุณภาพ, Saturation บอกขีดจำกัด:

  1. Latency — ใช้เวลาตอบนานแค่ไหน? (p50, p95, p99)
  2. Traffic — มี request เข้ามากี่ครั้ง/วินาที?
  3. Errors — กี่ % ที่ error? (HTTP 5xx)
  4. Saturation — ระบบเต็มแค่ไหน? (CPU, memory, disk, queue)
💡 SLO Tip: กำหนด SLO (Service Level Objective) เช่น "99.9% uptime" หรือ "p95 latency < 200ms" แล้ว monitor ว่าทำได้จริงมั้ย — อันนี้คือ SLI (Service Level Indicator)

สรุป

Monitoring & Observability เป็นสิ่งที่ต้องมี ไม่ใช่ "มีก็ดี" — ถ้าไม่มี ก็เหมือนขับรถโดยไม่มี dashboard ไม่รู้ว่าน้ำมันจะหมดเมื่อไร เครื่องยนต์ร้อนแค่ไหน เริ่มจาก metrics + alerting ก่อน (Prometheus + Grafana) แล้วเพิ่ม logs และ traces เมื่อระบบซับซ้อนขึ้น:

  • Monitoring = "มีปัญหามั้ย?" | Observability = "ทำไมถึงมีปัญหา?"
  • 3 Pillars = Metrics (ตัวเลข) + Logs (บันทึก) + Traces (ติดตาม request)
  • Prometheus + Grafana = metrics stack ยอดนิยม ใช้ PromQL query
  • Loki / ELK = centralized logging — รวม log จากทุก server มาที่เดียว
  • Jaeger / OpenTelemetry = distributed tracing หา bottleneck ใน microservices
  • Alerting = แจ้งเตือนผ่าน Slack/PagerDuty — ระวัง alert fatigue!
  • 4 Golden Signals = Latency, Traffic, Errors, Saturation 📊🐕

In the previous post we learned IaC — using Terraform to build infrastructure and Ansible to configure servers automatically.

But once it is deployed to production... how do you know the app is behaving normally? When is the server going to fall over? What error is a user hitting right now? 🔍

This is where Monitoring & Observability comes in — the system that lets us "see" everything happening inside, like a DevOps engineer sitting and staring at a dashboard all day long 🐕‍🦺📊


Monitoring vs Observability — What's the Difference?

Many people use the two terms interchangeably, but they are genuinely different — Monitoring is "checking whether the system is still working normally" (Is CPU high? Is the disk full? Is the error rate climbing?), asking questions we already know to ask. Observability is "being able to understand the state of the system from the data it emits" — answering questions we have never thought to ask. It suits complex microservices whose failure modes are impossible to predict:

Monitoring Observability
Answers "is something wrong?" Answers "why is something wrong?"
Checks the things we anticipated Finds the things we never considered
Dashboard + Alerts Explore + Drill-down + Correlate
CPU is high → send an alert Why is CPU high? → trace → found a slow query
💡 An easy way to remember it: Monitoring = installing the security cameras | Observability = having a detective who analyses the footage

3 Pillars of Observability

A good observability setup needs three kinds of data that complement each other — Metrics tell you "is something wrong" (numbers), Logs tell you "what happened" (events), Traces tell you "where it is slow" (request flow). Missing any one of them makes debugging hard:

📊
Metrics
Measurable numbers such as CPU %, memory, requests/sec, error rate
📝
Logs
A record of events such as error messages, access logs, debug info
🔗
Traces
Following a request through every service to see where it slows down

Pillar 1: Metrics — The Numbers to Watch

Metrics are numbers measured over time (time-series data) — CPU usage 72%, response time 230ms, error rate 0.5%. They suit alerting (fire when a threshold is crossed) and trending (watching long-term patterns). Metrics come in three levels:

System Metrics

System metrics measure the health of the infrastructure — CPU, memory, disk, network. Every server needs them; they are what tells you "when the machine is going to fall over":

  • CPU Usage — how hard the machine is working
  • Memory Usage — how much RAM is left
  • Disk I/O — how fast the disk is reading and writing
  • Network I/O — how much bandwidth is being used

Application Metrics (RED Method)

The RED Method (Rate, Errors, Duration) is the set of metrics measured from the user's point of view — how many requests arrive? what percentage of them error? how slowly does it answer? It matters more than system metrics because it tells you whether the user experience is good:

  • Rate — requests per second
  • Errors — percentage of errors (5xx)
  • Duration — response time (p50, p95, p99)

Business Metrics

Business metrics connect technical data to business impact — orders per minute, signup rate, cart abandonment rate. They help answer questions like "the system got 200ms slower, did that hurt sales?":

  • Active Users — how many people are using it right now
  • Orders/min — orders per minute
  • Revenue — revenue in real time
💡 RED Method: use it for services (Rate, Errors, Duration)
USE Method: use it for resources (Utilization, Saturation, Errors)

Prometheus + Grafana — The Most Popular Metrics Stack

Prometheus is a metrics database (TSDB) that stores time-series data — it uses a "pull model", meaning Prometheus itself fetches data from its targets (servers, apps) every 15 seconds. Grafana is the dashboard tool that renders those metrics as beautiful graphs. Both are open-source, CNCF graduated projects, and the industry standard:

🎯 App
expose /metrics
→
📦 Prometheus
scrape + store
→
📊 Grafana
visualize + alert

Configuring Prometheus

The prometheus.yml file:

global:
  scrape_interval: 15s        # pull metrics every 15 seconds

scrape_configs:
  # Monitor Prometheus itself
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  # Monitor the nodes (the server machines)
  - job_name: 'node'
    static_configs:
      - targets:
        - 'server1:9100'
        - 'server2:9100'
        - 'server3:9100'

  # Monitor the app
  - job_name: 'myapp'
    metrics_path: '/metrics'
    static_configs:
      - targets: ['app:3000']

Docker Compose for the Monitoring Stack

The monitoring stack is easy to set up with Docker Compose — Prometheus + Grafana + Node Exporter (system metrics) + cAdvisor (container metrics), ready to use in a few minutes:

version: '3.8'
services:
  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3001:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=secret
    volumes:
      - grafana_data:/var/lib/grafana

  node-exporter:
    image: prom/node-exporter:latest
    ports:
      - "9100:9100"
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro

volumes:
  prometheus_data:
  grafana_data:
# Run the monitoring stack
docker compose up -d

# Open Prometheus: http://localhost:9090
# Open Grafana:    http://localhost:3001 (admin/secret)

PromQL — Querying Data Out of Prometheus

PromQL is Prometheus's query language — you use it to compute the metrics you want, such as the error rate over 5 minutes, 95th percentile latency, or average CPU usage. Learning PromQL is an essential DevOps skill:

# Average CPU usage over 5 minutes
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# Request rate per second
rate(http_requests_total[5m])

# Error rate (%)
rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) * 100

# 95th percentile response time
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))

# Memory usage (%)
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100

Pillar 2: Logs — The Record of Events

Logs are the record of events that happened in the system — "user X logged in successfully", "payment failed: insufficient funds", "database connection timeout". Metrics tell you "there is a problem", but logs tell you "what actually happened" — which matters enormously when debugging.

Structured Logging — Better Than Plain Text!

Instead of logging plain text ("User john logged in"), use structured logging (JSON format) — it makes searching, filtering and aggregating easy. Ask "every error from user X in the last hour" and you get an answer immediately:

// ❌ Bad — hard to parse
console.log("User login failed for user123");

// ✅ Good — structured JSON
logger.error({
  event: "login_failed",
  userId: "user123",
  reason: "invalid_password",
  ip: "203.0.113.50",
  timestamp: "2026-03-07T09:00:00Z"
});

Log Levels

Log levels help separate what matters — production should log INFO and above only (skip DEBUG, its volume is enormous). When a problem appears, turn DEBUG on temporarily:

Level Use when Example
ERROR A real failure has occurred Database connection failed
WARN There may be a problem later Disk usage > 80%
INFO A normal but significant event Server started on port 3000
DEBUG Details for debugging Query result: 42 rows

ELK Stack — Centralized Logging

Once you have many servers and containers, SSH-ing into each machine to read its log does not work — you need centralized logging that gathers every log in one place. The ELK Stack (Elasticsearch + Logstash + Kibana) is a popular solution:

📱 Apps
send logs
→
🚛 Logstash
collect + transform
→
🔍 Elasticsearch
store + search
→
📊 Kibana
visualize + explore

A lighter alternative: Loki + Promtail + Grafana (you can keep the Grafana you already have!)

# Loki + Promtail Docker Compose
services:
  loki:
    image: grafana/loki:latest
    ports:
      - "3100:3100"

  promtail:
    image: grafana/promtail:latest
    volumes:
      - /var/log:/var/log:ro
      - ./promtail.yml:/etc/promtail/config.yml

Pillar 3: Traces — Following a Request

When a single request has to pass through many services (microservices), how do we know where it is slow?

🌐 API Gateway
2ms
→
👤 User Service
15ms
→
💳 Payment Service
850ms ⚠️
→
📧 Email Service
45ms

The trace lets us see that Payment Service took 850ms — that is the bottleneck!

Tracing Tools

The main tracing tools — Jaeger (CNCF, open-source, good with Kubernetes), Zipkin (from Twitter, lightweight), OpenTelemetry (the new standard that unifies metrics + logs + traces in one vendor-neutral SDK):

  • Jaeger — open-source, from Uber
  • Zipkin — open-source, from Twitter
  • OpenTelemetry — the new standard (metrics + logs + traces together)
  • Datadog APM / New Relic — commercial (easy but expensive)
// OpenTelemetry example (Node.js)
const { trace } = require('@opentelemetry/api');

const tracer = trace.getTracer('my-service');

app.get('/api/checkout', async (req, res) => {
  const span = tracer.startSpan('checkout');

  try {
    // each step gets its own child span
    const userSpan = tracer.startSpan('get-user', { parent: span });
    const user = await getUser(req.userId);
    userSpan.end();

    const paySpan = tracer.startSpan('process-payment', { parent: span });
    await processPayment(user, req.amount);
    paySpan.end();

    res.json({ status: 'success' });
  } catch (err) {
    span.setStatus({ code: 2, message: err.message });
    res.status(500).json({ error: err.message });
  } finally {
    span.end();
  }
});

Alerting — Warning You Before It Breaks

However beautiful the dashboard is, it does not help if nobody is looking at it — you need alerts!

Alert Rules (Prometheus)

Alert rules define "when condition X holds for Y minutes → send an alert". The important part is the for duration, which prevents false alarms from momentary spikes, while labels and annotations help the on-call team understand the problem quickly:

# alert-rules.yml
groups:
  - name: critical
    rules:
      # Server down
      - alert: InstanceDown
        expr: up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "{{ $labels.instance }} is down!"

      # CPU above 90% for 5 minutes
      - alert: HighCPU
        expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "CPU > 90% on {{ $labels.instance }}"

      # Error rate above 5%
      - alert: HighErrorRate
        expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) * 100 > 5
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Error rate > 5% on {{ $labels.job }}"

      # Less than 10% disk remaining
      - alert: DiskSpaceLow
        expr: (node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 < 10
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Disk < 10% on {{ $labels.instance }}"

Where Do Alerts Go? (Alertmanager)

Alertmanager receives alerts from Prometheus and forwards them to the appropriate channels — Slack, PagerDuty, email, webhook. It supports grouping (merging identical alerts), silencing (muting temporarily) and routing (critical → PagerDuty, warning → Slack):

# alertmanager.yml
route:
  receiver: 'team-slack'
  routes:
    - match:
        severity: critical
      receiver: 'pagerduty'     # Critical → wake someone up to fix it!
    - match:
        severity: warning
      receiver: 'team-slack'    # Warning → post it in Slack

receivers:
  - name: 'team-slack'
    slack_configs:
      - api_url: 'https://hooks.slack.com/services/xxx'
        channel: '#alerts'
        title: '🚨 {{ .GroupLabels.alertname }}'
        text: '{{ .CommonAnnotations.summary }}'

  - name: 'pagerduty'
    pagerduty_configs:
      - service_key: 'your-pagerduty-key'
🐕 Alert Fatigue: do not put an alert on everything! Too many notifications and people start ignoring them → Critical = act immediately | Warning = look at it today | Info = look when you have time

Popular Monitoring Stacks

There are a great many monitoring tools — the table below compares the popular stacks, both open-source and commercial, to help you choose according to your needs (budget, scale, complexity):

Stack Components Strengths
PLG Prometheus + Loki + Grafana Open-source, K8s friendly, all 3 pillars covered
ELK Elasticsearch + Logstash + Kibana Excellent log search, enterprise
TIG Telegraf + InfluxDB + Grafana Good for IoT and time-series
Datadog All-in-one SaaS The easiest, but expensive
New Relic All-in-one SaaS Good APM, free tier

4 Golden Signals (Google SRE)

The 4 Golden Signals come from the Google SRE Book — if you can only monitor four things, monitor these four; together they cover the whole user experience. Latency tells you about the experience, Traffic tells you about demand, Errors tell you about quality, Saturation tells you about the limit:

  1. Latency — how long does it take to answer? (p50, p95, p99)
  2. Traffic — how many requests arrive per second?
  3. Errors — what percentage of requests are errors? (HTTP 5xx)
  4. Saturation — how full is the system? (CPU, memory, disk, queue)
💡 SLO Tip: set an SLO (Service Level Objective) such as "99.9% uptime" or "p95 latency < 200ms", then monitor whether you actually meet it — that measurement is the SLI (Service Level Indicator)

Summary

Monitoring & Observability is a must-have, not a nice-to-have — without it you are driving a car with no dashboard, with no idea when the fuel runs out or how hot the engine is. Start with metrics + alerting (Prometheus + Grafana), then add logs and traces as the system grows more complex:

  • Monitoring = "is something wrong?" | Observability = "why is something wrong?"
  • 3 Pillars = Metrics (numbers) + Logs (records) + Traces (following a request)
  • Prometheus + Grafana = the popular metrics stack, queried with PromQL
  • Loki / ELK = centralized logging — every server's logs gathered in one place
  • Jaeger / OpenTelemetry = distributed tracing, finding the bottleneck in microservices
  • Alerting = notifications through Slack/PagerDuty — beware alert fatigue!
  • 4 Golden Signals = Latency, Traffic, Errors, Saturation 📊🐕
บทความจากซีรีส์ DevOps & Vibe Coding 2026From the DevOps & Vibe Coding 2026 series
← Previous
Infrastructure as Code — จัดการ Server ด้วย Terraform & Ansible
Next →
Linux Command Line — คำสั่งพื้นฐานที่ DevOps ต้องรู้