Post

Belajar SRE #2: Monitoring Basics

Pelajari dasar-dasar monitoring untuk SRE: metrics, logs, traces, dan observability. Panduan praktis membangun monitoring stack.

Belajar SRE #2: Monitoring Basics

Monitoring adalah mata dan telinga dari setiap SRE team. Tanpa monitoring yang baik, Anda seperti mengemudikan mobil di malam hari tanpa lampu, mungkin tetap bisa berjalan, tapi tidak akan tahu ada masalah di perjalanan. Artikel ini membahas fondasi monitoring dari perspektif SRE: four golden signals, perbedaan monitoring vs observability, dan hands-on setup Prometheus dan Grafana untuk memantau kesehatan service.

Jika Anda belum membaca artikel sebelumnya, mulai dari Foundation SRE: Apa Itu Site Reliability Engineering.

Prerequisites

  • Pemahaman dasar Linux dan command line
  • Memahami konsep dasar SRE, toil, dan reliability mindset — baca: Foundation SRE: Apa Itu Site Reliability Engineering
  • Familiar dengan Docker dan docker-compose
  • Tidak memerlukan pengalaman monitoring sebelumnya — artikel ini adalah starting point

Mengapa Monitoring Penting untuk SRE?

Monitoring adalah fondasi dari semua SRE practices. Tanpa monitoring, Anda tidak bisa:

  • Mengetahui apakah SLO Anda terpenuhi
  • Mendeteksi incident sebelum user melaporkan
  • Membuat keputusan berbasis data tentang error budget
  • Mengidentifikasi toil yang perlu diotomasi
  • Melakukan capacity planning yang akurat

Tiga Pilar Observability

Monitoring modern dibangun di atas tiga pilar utama yang saling melengkapi:

PilarDeskripsiContohTool Modern
MetricsData numerik yang diukur dari waktu ke waktuCPU usage 75%, request rate 500 rpsPrometheus, OpenTelemetry Metrics
LogsRecord event diskrit yang terjadi di sistem“ERROR: Database connection timeout”Loki, OpenTelemetry Logs
TracesJejak request yang melewati multiple servicesRequest → API Gateway → User Service → DB (250ms)Jaeger, Tempo, OpenTelemetry Traces
flowchart LR
    subgraph Metrics
        M[Numbers over time<br/>What is happening?]
    end
    subgraph Logs
        L[Events<br/>What happened?]
    end
    subgraph Traces
        T[Request flow<br/>Where did it go?]
    end
    M --> OTel[OpenTelemetry Collector]
    L --> OTel
    T --> OTel
    OTel --> Backend[Backend: Prometheus, Loki, Tempo]

Catatan: OpenTelemetry (OTel) telah menjadi standar industri untuk instrumentasi observability. OTel Collector berfungsi sebagai telemetry pipeline yang menerima, memproses, dan mengekspor data dari ketiga pilar ini ke berbagai backend. Jika Anda baru memulai, gunakan OTel SDK sebagai fondasi — ini menghindari vendor lock-in.

Four Golden Signals

Google SRE Book mendefinisikan empat sinyal emas yang harus dimonitor untuk setiap service:

flowchart TD
    A[LATENCY<br/>Seberapa cepat?] --> E[SERVICE HEALTH]
    B[TRAFFIC<br/>Seberapa banyak?] --> E
    C[ERRORS<br/>Seberapa sering gagal?] --> E
    D[SATURATION<br/>Seberapa penuh?] --> E

Signal 1: Latency

Latency mengukur waktu yang dibutuhkan untuk memproses sebuah request. Yang penting: bedakan antara latency dari request yang berhasil dan request yang gagal.

AspekDetail
DefinisiWaktu dari request diterima hingga response dikirim
Metric typeHistogram (distribusi, bukan rata-rata)
Contoh SLI95th percentile latency < 200ms
Common mistakeHanya melihat average — ini menyembunyikan outliers

Tip: Gunakan percentiles (p50, p90, p95, p99) bukan average. 1% dari 1 juta request = 10.000 user yang terkena tail latency.

Signal 2: Traffic

Traffic mengukur seberapa banyak demand yang diterima oleh service Anda.

AspekDetail
DefinisiVolume request yang diterima service per satuan waktu
Metric typeCounter (monotonically increasing)
Contoh SLIHTTP requests per second
VariasiWeb: HTTP rps, API: API calls/sec, DB: queries/sec

Anomaly detection pada traffic: drop tiba-tiba → possible outage, spike 10x → flash sale atau DDoS, traffic = 0 → service down.

Signal 3: Errors

Errors mengukur rate request yang gagal — baik secara eksplisit (HTTP 5xx) maupun implisit (response yang salah atau terlalu lambat).

AspekDetail
DefinisiPersentase request yang gagal
Metric typeCounter → dihitung sebagai rate
Contoh SLIError rate < 0.1% dari total requests
Jenis errorExplicit (5xx), implicit (wrong content), policy (> SLA threshold)

Formula: Error Rate = (Total Errors / Total Requests) × 100%

Signal 4: Saturation

Saturation mengukur seberapa “penuh” resource Anda — seberapa dekat sistem dengan kapasitas maksimumnya.

AspekDetail
DefinisiPersentase utilisasi resource terhadap kapasitas maksimum
Metric typeGauge (nilai yang naik-turun)
Contoh SLICPU utilization < 70%, memory usage < 80%
Key insightPerforma degradasi sebelum 100% — monitor threshold
ResourceHealthyWarningCritical
CPU< 60%60-80%> 80%
Memory< 70%70-85%> 85%
Disk< 70%70-85%> 85%
DB Connections< 60%60-80%> 80%

Ringkasan Four Golden Signals

SignalPertanyaanMetric TypeContoh PromQL
LatencySeberapa cepat?Histogramhistogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
TrafficSeberapa banyak?Countersum(rate(http_requests_total[5m]))
ErrorsSeberapa sering gagal?Countersum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m]))
SaturationSeberapa penuh?Gaugenode_memory_MemAvailable_bytes / node_memory_MemTotal_bytes

Monitoring vs Observability

Monitoring dan observability sering digunakan secara bergantian, tapi memiliki perbedaan penting:

AspekMonitoringObservability
FokusKnown-knowns dan known-unknownsUnknown-unknowns
Pertanyaan“Apakah X bermasalah?”“Mengapa X bermasalah?”
DataMetrics dan alertsMetrics + Logs + Traces (correlated)
ApproachPredefined dashboardsAd-hoc exploration
MaturityFoundation (mulai di sini)Intermediate-Advanced

Relationship: Monitoring adalah subset dari observability — Anda butuh monitoring dulu, baru bisa observability. Artikel ini fokus pada monitoring sebagai fondasi.

Untuk Foundation level: Fokus pada monitoring dulu — setup metrics collection, buat dashboard untuk four golden signals, dan konfigurasi basic alerts. Observability yang lebih mendalam (distributed tracing, log correlation) akan dibahas di level Intermediate.

Hands-on: Prometheus + Grafana Setup

Architecture Overview

flowchart TD
    App[Application<br/>/metrics] -->|scrape| Prom[Prometheus<br/>:9090]
    NE[Node Exporter<br/>:9100] -->|scrape| Prom
    CA[cAdvisor<br/>:8080] -->|scrape| Prom
    Prom -->|query| Graf[Grafana<br/>:3000]

Docker Compose untuk Monitoring Stack

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# docker-compose.yml — Basic Monitoring Stack
version: '3.8'

services:
  prometheus:
    image: prom/prometheus:v2.53.0
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
      - ./prometheus/alert-rules.yml:/etc/prometheus/alert-rules.yml
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.retention.time=15d'
      - '--web.enable-lifecycle'
      - '--enable-feature=native-histograms'
    restart: unless-stopped

  grafana:
    image: grafana/grafana:11.1.0
    container_name: grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=monitoring-2024
      - GF_USERS_ALLOW_SIGN_UP=false
    volumes:
      - grafana-data:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning
    depends_on:
      - prometheus
    restart: unless-stopped

  node-exporter:
    image: prom/node-exporter:v1.8.1
    container_name: node-exporter
    ports:
      - "9100:9100"
    restart: unless-stopped

  cadvisor:
    image: gcr.io/cadvisor/cadvisor:v0.49.1
    container_name: cadvisor
    ports:
      - "8080:8080"
    restart: unless-stopped

volumes:
  prometheus-data:
  grafana-data:

Konfigurasi Prometheus

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# prometheus/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s
  scrape_timeout: 10s

rule_files:
  - "alert-rules.yml"

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node-exporter'
    static_configs:
      - targets: ['node-exporter:9100']

  - job_name: 'cadvisor'
    static_configs:
      - targets: ['cadvisor:8080']

  - job_name: 'application'
    metrics_path: '/metrics'
    static_configs:
      - targets: ['app:8080']

Basic Alert Rules

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# prometheus/alert-rules.yml
groups:
  - name: golden-signals
    rules:
      - alert: HighLatency
        expr: |
          histogram_quantile(0.95,
            sum(rate(http_request_duration_seconds_bucket[5m])) by (le, job)
          ) > 0.5
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "High p95 latency on "

      - alert: HighErrorRate
        expr: |
          sum(rate(http_requests_total{status=~"5.."}[5m])) by (job)
          / sum(rate(http_requests_total[5m])) by (job)
          > 0.01
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Error rate > 1% on "

      - alert: HighCPUUsage
        expr: |
          100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
          > 80
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "CPU > 80% on "

      - alert: HighMemoryUsage
        expr: |
          (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
          > 85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Memory > 85% on "

Jalankan Monitoring Stack

1
2
3
4
5
6
7
8
9
10
11
12
# Buat folder structure
mkdir -p prometheus grafana/provisioning/datasources

# Jalankan stack
docker-compose up -d

# Verifikasi semua container running
docker-compose ps

# Akses UI
# Prometheus: http://localhost:9090/targets
# Grafana:    http://localhost:3000 (admin/monitoring-2024)

PromQL Queries untuk Golden Signals

Latency Queries

# p95 latency
histogram_quantile(0.95,
  sum(rate(http_request_duration_seconds_bucket[5m])) by (le)
)

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

# Latency per endpoint
histogram_quantile(0.95,
  sum(rate(http_request_duration_seconds_bucket[5m])) by (le, handler)
)

Traffic Queries

# Total request rate (requests per second)
sum(rate(http_requests_total[5m]))

# Request rate per status code
sum(rate(http_requests_total[5m])) by (status)

# Traffic comparison: sekarang vs 1 jam lalu
sum(rate(http_requests_total[5m]))
/ sum(rate(http_requests_total[5m] offset 1h))

Error Queries

# Error rate (percentage)
sum(rate(http_requests_total{status=~"5.."}[5m]))
/ sum(rate(http_requests_total[5m]))

# Availability (inverse of error rate)
1 - (
  sum(rate(http_requests_total{status=~"5.."}[5m]))
  / sum(rate(http_requests_total[5m]))
)

Saturation Queries

# CPU utilization (%)
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

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

# Disk utilization (%)
(1 - node_filesystem_avail_bytes{mountpoint="/"}
/ node_filesystem_size_bytes{mountpoint="/"}) * 100

Studi Kasus: TechStartup Indonesia

Konteks

Setelah “Monday Morning Incident”, CTO menugaskan tim DevOps untuk membangun monitoring yang proper.

Kondisi sebelumnya:

  • Stack: Node.js monolith di AWS EC2, 50.000 DAU
  • Monitoring: hanya CloudWatch basic + manual SSH log checking
  • MTTD: 30-45 menit
  • 80% incident diketahui dari customer complaint, bukan dari alert

Tantangan utama:

  • Tidak ada application-level metrics (hanya infra metrics dari CloudWatch)
  • Budget terbatas: Rp 5 juta/bulan
  • Tim belum familiar dengan Prometheus/Grafana

Apa yang Dilakukan (3 Minggu)

  1. Install Prometheus + Grafana self-hosted di 1 VM (biaya ~$15/bulan)
  2. Instrumentasi golden signals ke aplikasi Node.js menggunakan library prom-client
  3. Konfigurasi basic alerts ke Slack channel #incidents
  4. Pertahankan CloudWatch sebagai backup untuk RDS dan infra metrics

Metrics Improvement

MetricSebelumSesudahPerubahan
MTTD (detect)30-45 min2-5 min-90%
MTTR (recover)3.5 hours30 min-86%
Customer-reported incidents80%15%-65pp
Golden signals coverage0/44/4Full coverage
Dashboard usage (views/day)050+Team habit

Dalam minggu pertama setelah monitoring aktif, TSI menemukan: memory leak (Node.js heap growing 50MB/hour), slow endpoint /api/search dengan p95 = 2.3s (missing database index), error spike 5% setiap jam 02:00 (cron job conflict), dan traffic pattern 3x spike setiap Jumat sore (payday effect).

Lessons Learned

Yang Berhasil:

  • Mulai dari four golden signals saja — 4 signals sudah cukup untuk detect 90% masalah
  • Grafana dashboard sebagai “morning ritual” — membangun awareness terhadap baseline normal
  • Alert ke Slack channel dedicated (#incidents) — semua orang bisa lihat, tidak ada yang terlewat

Yang Perlu Dihindari:

  • Alert threshold terlalu sensitif (CPU > 50%) menyebabkan alert fatigue — gunakan symptom-based alerts
  • Tidak set retention policy di awal — Prometheus disk penuh setelah 2 minggu
  • Gunakan rate() bukan value untuk error metrics — rate memberikan trend yang lebih actionable

Best Practices

  • Monitor four golden signals — latency, traffic, errors, saturation adalah minimum yang harus dimonitor untuk setiap service
  • Gunakan percentiles, bukan averages — p50, p95, p99 memberikan gambaran distribusi yang jauh lebih akurat
  • Set alert berdasarkan user impact — “Error rate > 1%” lebih bermakna daripada “CPU > 80%”
  • Buat dashboard yang actionable — dashboard harus menjawab “apakah ada masalah?” dalam 5 detik pertama
  • Mulai dengan sedikit metrics, tambahkan gradually — 10 metrics yang dipahami lebih baik dari 1000 yang diabaikan
  • Dokumentasikan setiap dashboard — tambahkan deskripsi panel: apa yang diukur, threshold, dan tindakan jika abnormal
  • Monitor your monitoring — Prometheus down = blind spot total

Selanjutnya

Artikel berikutnya: Foundation SRE: Pengantar Incident Response — membahas proses incident response, severity levels, dan komunikasi saat incident terjadi.

Topik terkait yang bisa Anda eksplorasi:

  • Incident response dan komunikasi saat incident
  • Alerting strategy untuk mengurangi alert fatigue
  • OpenTelemetry sebagai standar observability modern

References


⬅️ Sebelumnya: Foundation SRE: Apa Itu Site Reliability Engineering

➡️ Selanjutnya: Foundation SRE: Pengantar Incident Response

This post is licensed under CC BY 4.0 by the author.