DevOps & Cloud

Monitoring & Observability untuk Developer

Tutorial lengkap memahami dan menerapkan monitoring serta observability β€” metrics, logs, distributed traces, Prometheus, Grafana, alerting, dan SLA/SLO untuk aplikasi production

1. Pengenalan Monitoring & Observability

Monitoring dan Observability adalah dua konsep krusial dalam pengembangan dan operasi sistem modern. Monitoring adalah praktik mengumpulkan dan menganalisis data dari sistem untuk memahami kondisinya. Observability adalah kemampuan untuk memahami kondisi internal sistem hanya dari output eksternalnya.

Bayangkan sebuah mobil tanpa dashboard β€” Anda tidak tahu kecepatan, sisa bahan bakar, atau suhu mesin. Tanpa monitoring, sistem aplikasi Anda seperti mobil tanpa dashboard. Dengan observability, Anda bisa menjawab pertanyaan seperti "mengapa aplikasi lambat?" bahkan tanpa merencanakan pertanyaan tersebut sebelumnya.

Mengapa Monitoring & Observability Penting?

Manfaat Penjelasan
Detect Issues EarlyMendeteksi masalah sebelum pengguna terdampak secara signifikan
Root Cause AnalysisMenemukan penyebab akar masalah dengan cepat dan akurat
Performance OptimizationMengidentifikasi bottleneck dan mengoptimalkan performa sistem
Capacity PlanningMerencanakan kebutuhan infrastruktur berdasarkan data historis
Compliance & AuditMemenuhi kepatuhan regulasi dan kebutuhan audit keamanan
Business IntelligenceInsight bisnis dari data penggunaan dan pola aplikasi

Monitoring vs Observability

Aspek Monitoring Observability
DefinisiMengumpulkan data & memberi peringatanMemahami kondisi internal dari data eksternal
FokusWhat is happening?Why is it happening?
PertanyaanPredefined (yang sudah diketahui)Ad-hoc (spontan, tidak terduga)
DataMetrics & LogsMetrics, Logs, & Traces
Tool ContohNagios, ZabbixPrometheus, Grafana Tempo, Jaeger
Cocok untukSistem sederhana, infrastructureMicroservices, distributed systems
Diagram: Monitoring vs Observability
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      OBSERVABILITY STACK                             β”‚
β”‚                                                                      β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                  β”‚
β”‚  β”‚  METRICS   β”‚    β”‚    LOGS    β”‚    β”‚  TRACES    β”‚                  β”‚
β”‚  β”‚  (Angka)   β”‚    β”‚  (Teks)    β”‚    β”‚ (Jejak)    β”‚                  β”‚
β”‚  β”‚            β”‚    β”‚            β”‚    β”‚            β”‚                  β”‚
β”‚  β”‚ CPU: 72%   β”‚    β”‚ [ERROR] DB β”‚    β”‚ ──req──►   β”‚                  β”‚
β”‚  β”‚ RAM: 4GB   β”‚    β”‚ timeout at β”‚    β”‚  svc-A     β”‚                  β”‚
β”‚  β”‚ Req/s: 1k  β”‚    β”‚ line 42    β”‚    β”‚   └─►svc-B β”‚                  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜                  β”‚
β”‚        β”‚                 β”‚                 β”‚                          β”‚
β”‚        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                          β”‚
β”‚                     β–Ό                                                β”‚
β”‚            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                         β”‚
β”‚            β”‚   CORRELATION  β”‚  ← Menghubungkan data                   β”‚
β”‚            β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                         β”‚
β”‚                    β–Ό                                                  β”‚
β”‚            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                         β”‚
β”‚            β”‚  DASHBOARDS &  β”‚  ← Visualisasi & Alerting               β”‚
β”‚            β”‚   ALERTS       β”‚                                         β”‚
β”‚            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2. Tiga Pilar Observability

Observability modern didasarkan pada tiga pilar utama: Metrics, Logs, dan Traces. Ketiga pilar ini saling melengkapi dan memberikan gambaran komprehensif tentang kondisi sistem.

Tiga Pilar dan Fungsinya

Pilar Deskripsi Format Data Contoh Tools
MetricsNumerik yang merepresentasikan kondisi sistem secara kuantitatifTime series dataPrometheus, InfluxDB, Datadog
LogsCatatan peristiwa detail dari aplikasi atau sistemStructured/Unstructured textELK Stack, Loki, Fluentd
TracesJejak perjalanan request melalui berbagai serviceDistributed trace dataJaeger, Zipkin, Tempo
πŸ’‘ Analogi Sederhana

Bayangkan Anda seorang dokter. Metrics seperti membaca detak jantung dan suhu tubuh (angka). Logs seperti rekam medis (catatan detail). Traces seperti mengikuti aliran darah dari jantung ke seluruh tubuh (perjalanan). Ketiganya dibutuhkan untuk diagnosis lengkap.

Kapan Menggunakan Pilar Mana?

Flowchart: Memilih Pilar Observability yang Tepat
        Apa yang ingin Anda ketahui?
                   β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β–Ό          β–Ό                                  β–Ό
  Seberapa banyak?   Apa yang terjadi?         Bagaimana mengalir?
        β”‚          β”‚                                  β”‚
        β–Ό          β–Ό                                  β–Ό
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚ METRICS β”‚  β”‚   LOGS   β”‚                  β”‚  TRACES   β”‚
   β”‚         β”‚  β”‚          β”‚                  β”‚           β”‚
   β”‚ CPU     β”‚  β”‚ Error    β”‚                  β”‚ Request   β”‚
   β”‚ Memory  β”‚  β”‚ Warnings β”‚                  β”‚ Latency   β”‚
   β”‚ Latency β”‚  β”‚ Events   β”‚                  β”‚ Per       β”‚
   β”‚ Traffic β”‚  β”‚ Debug    β”‚                  β”‚ Service   β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
⚠️ Kesalahan Umum

Jangan hanya mengandalkan satu pilar! Banyak tim hanya menggunakan metrics dan mengabaikan logs/traces. Saat terjadi masalah yang tidak terprediksi, mereka kesulitan menemukan root cause. Gunakan ketiga pilar secara harmonis untuk observability yang maksimal.

3. Metrics: Angka yang Menceritakan Kondisi Sistem

Metrics adalah data numerik yang dikumpulkan dari waktu ke waktu (time series data). Metrics membantu Anda memahami kondisi sistem secara kuantitatif dan mendeteksi anomali atau tren tertentu.

Jenis-Jenis Metrics

Jenis Deskripsi Contoh
CounterNilai yang selalu naik, tidak pernah turunJumlah request HTTP, jumlah error
GaugeNilai yang bisa naik atau turunCPU usage, memory usage, jumlah koneksi aktif
HistogramDistribusi nilai dalam range tertentuResponse time distribution
SummaryStatistik agregat dari dataP95/P99 latency, total request count

RED Method untuk Microservices

RED Method adalah framework metrik yang dirancang khusus untuk microservices. Setiap service harus mengekspos metrik berikut:

PromQL β€” RED Method
# R = Rate β€” Jumlah request per detik
rate(http_requests_total[5m])

# E = Errors β€” Jumlah error per detik
rate(http_requests_total{status=~"5.."}[5m])

# D = Duration β€” Latency request
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))

# Error ratio = errors / total requests
rate(http_requests_total{status=~"5.."}[5m])
  /
rate(http_requests_total[5m])

USE Method untuk Infrastruktur

USE Method difokuskan pada infrastruktur (CPU, disk, network, memory):

PromQL β€” USE Method
# U = Utilization β€” Persentase penggunaan resource
node_cpu_seconds_total
node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes

# S = Saturation β€” Overload / queue yang menunggu
node_load1  # Load average 1 menit
node_disk_io_time_weighted_seconds_total

# E = Errors β€” Error yang terjadi
node_disk_read_errors_total
node_network_receive_errs_total
πŸ’‘ Tips Mengukur Metrics yang Baik
  • Gunakan RED Method untuk layanan/application level
  • Gunakan USE Method untuk infrastruktur level
  • Ingat formula: Latency Γ— Traffic = Errors (semua saling terkait)
  • Setiap microservice minimal harus mengekspos metrik RED

4. Logs: Cerita Peristiwa Sistem

Logs adalah catatan kronologis peristiwa yang terjadi dalam sistem. Logs memberikan detail kontekstual yang kaya tentang apa yang terjadi pada waktu tertentu, membuatnya sangat berharga untuk debugging dan audit trail.

Structured vs Unstructured Logs

Aspek Unstructured Logs Structured Logs (JSON)
FormatPlain text bebasJSON dengan key-value pair
ParsingSulit, perlu regexMudah, otomatis
SearchabilityLambatCepat dengan indexing
Contoh2026-06-25 ERROR: Connection timeout{"time":"2026-06-25","level":"error","msg":"timeout","db":"primary"}
RekomendasiHindariGunakan selalu

Menerapkan Structured Logging

JSON β€” Structured Log Output
{
  "timestamp": "2026-06-25T14:30:22.123Z",
  "level": "error",
  "service": "payment-api",
  "trace_id": "abc123def456",
  "span_id": "789ghi012",
  "method": "POST",
  "path": "/api/v1/payments",
  "status_code": 500,
  "duration_ms": 3420,
  "error": "Connection refused to payment-gateway:5432",
  "user_id": "u_12345",
  "request_id": "req_abc789",
  "host": "payment-api-3a7f9c",
  "message": "Payment processing failed"
}

Log Levels dan Kapan Menggunakannya

Level Contoh Kapan Digunakan
DEBUGVariable value, function entryDevelopment/debugging, nonaktifkan di production
INFOServer started, request handledOperasi normal, event penting
WARNDisk usage 80%, slow queryPerlu perhatian tapi belum error
ERRORConnection failed, payment errorOperasi gagal, perlu investigasi
FATALOut of memory, corrupted DBSistem tidak bisa melanjutkan operasi

ELK Stack: Solusi Logging Populer

Diagram: Arsitektur ELK Stack
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     ELK STACK                           β”‚
β”‚                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚
β”‚  β”‚ App Logs │───▢│Logstash  │───▢│ Elasticsearchβ”‚      β”‚
β”‚  β”‚          β”‚    β”‚(Parse &  β”‚    β”‚ (Search &    β”‚      β”‚
β”‚  β”‚ Web App  β”‚    β”‚ Enrich)  β”‚    β”‚  Index)      β”‚      β”‚
β”‚  β”‚ API      β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚
β”‚  β”‚ DB       β”‚                           β”‚               β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                           β–Ό               β”‚
β”‚                                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚                                β”‚   Kibana      β”‚        β”‚
β”‚                                β”‚ (Dashboard &  β”‚        β”‚
β”‚                                β”‚  Visualization)β”‚       β”‚
β”‚                                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

5. Distributed Traces: Jejak Request

Distributed Tracing memungkinkan Anda melacak perjalanan sebuah request dari awal hingga akhir melewati berbagai service dalam arsitektur microservices. Setiap operasi dalam request direpresentasikan sebagai span yang memiliki hubungan parent-child.

Konsep Dasar Distributed Tracing

Konsep Penjelasan
TraceSeluruh perjalanan request dari client hingga response lengkap
SpanSatu unit kerja dalam trace β€” misalnya query database atau HTTP call
Trace IDIdentifier unik yang menghubungkan semua span dalam satu request
Span IDIdentifier unik untuk setiap span individual
Parent Span IDID span induk β€” menunjukkan hubungan hierarchical
Context PropagationMekanisme meneruskan trace context antar service

Contoh Distributed Trace

Diagram: Distributed Trace dalam E-Commerce
Client ─────────────────────────────────────────────────────────
  β”‚
  β”‚  Trace ID: abc-123-def-456
  β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Gateway (Span 1) β€” 120ms                                    β”‚
β”‚ β”œβ”€β”€ Auth Service (Span 2) β€” 15ms                            β”‚
β”‚ β”œβ”€β”€ Product Service (Span 3) β€” 45ms                         β”‚
β”‚ β”‚   └── Redis Cache (Span 4) β€” 2ms                          β”‚
β”‚ β”œβ”€β”€ Cart Service (Span 5) β€” 30ms                            β”‚
β”‚ β”‚   └── PostgreSQL (Span 6) β€” 12ms                          β”‚
β”‚ └── Payment Service (Span 7) β€” 25ms                         β”‚
β”‚     └── Payment Gateway (Span 8) β€” 18ms                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Total latency: 120ms
Bottleneck: Product Service (45ms) β€” 37.5% dari total waktu

Implementasi Tracing dengan OpenTelemetry

JavaScript β€” OpenTelemetry Tracing
// Instalasi: npm install @opentelemetry/sdk-node @opentelemetry/api

const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
const { Resource } = require('@opentelemetry/resources');
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
const { trace } = require('@opentelemetry/api');

// Setup tracer provider
const provider = new NodeTracerProvider({
  resource: new Resource({
    [SemanticResourceAttributes.SERVICE_NAME]: 'payment-service',
    [SemanticResourceAttributes.SERVICE_VERSION]: '1.0.0',
  }),
});

// Export ke Jaeger
const exporter = new JaegerExporter({
  endpoint: 'http://jaeger:14268/api/traces',
});
provider.addSpanProcessor(new BatchSpanProcessor(exporter));
provider.register();

// Menggunakan tracing di kode aplikasi
const tracer = trace.getTracer('payment-service');

async function processPayment(orderId, amount) {
  return tracer.startActiveSpan('processPayment', async (span) => {
    try {
      span.setAttribute('order.id', orderId);
      span.setAttribute('payment.amount', amount);

      // Span untuk validasi
      await tracer.startActiveSpan('validateOrder', async (childSpan) => {
        await validateOrder(orderId);
        childSpan.end();
      });

      // Span untuk koneksi payment gateway
      await tracer.startActiveSpan('callPaymentGateway', async (childSpan) => {
        await callGateway(amount);
        childSpan.end();
      });

      span.setStatus({ code: 0 }); // OK
    } catch (error) {
      span.setStatus({ code: 2, message: error.message }); // ERROR
      span.recordException(error);
      throw error;
    } finally {
      span.end();
    }
  });
}
⚠️ Best Practice Tracing
  • Gunakan OpenTelemetry sebagai standar vendor-neutral
  • Pastikan semua service meneruskan trace context dalam HTTP headers (traceparent)
  • Tambahkan attributes bermakna pada span (user ID, order ID, dll)
  • Gunakan sampling strategis untuk sistem dengan traffic tinggi

6. Prometheus: Platform Monitoring Modern

Prometheus adalah sistem monitoring open-source yang dirancang untuk mengumpulkan dan mengekspos metrics sebagai time series data. Prometheus menggunakan model pull-based β€” ia aktif mengambil (scrape) metrics dari target aplikasi secara berkala.

Fitur Utama Prometheus

Fitur Penjelasan
Pull-based ModelPrometheus scrape metrics dari target, bukan push dari aplikasi
PromQLBahasa query yang powerful untuk analisis time series data
Multi-dimensional LabelsData bisa di-filter dan di-group dengan label
Built-in AlertingIntegrasi dengan Alertmanager untuk notifikasi
Service DiscoveryOtomatis menemukan target baru (Kubernetes, Consul, dll)
TSDB StorageTime series database lokal yang efisien

Instalasi Prometheus

Bash β€” Instalasi & Konfigurasi Prometheus
# Download Prometheus
wget https://github.com/prometheus/prometheus/releases/download/v2.53.0/prometheus-2.53.0.linux-amd64.tar.gz
tar xzf prometheus-2.53.0.linux-amd64.tar.gz
cd prometheus-2.53.0.linux-amd64

# Konfigurasi prometheus.yml
cat > prometheus.yml << 'EOF'
global:
  scrape_interval: 15s
  evaluation_interval: 15s

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - alertmanager:9093

rule_files:
  - "alert_rules.yml"

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

  # Monitor aplikasi Node.js
  - job_name: 'node-app'
    static_configs:
      - targets: ['app-server:9100']

  # Monitor dengan service discovery Kubernetes
  - job_name: 'kubernetes-pods'
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: true
EOF

# Jalankan Prometheus
./prometheus --config.file=prometheus.yml --storage.tsdb.retention.time=30d

PromQL: Bahasa Query Prometheus

PromQL β€” Query Examples
# Rate of HTTP requests per second (5m window)
rate(http_requests_total[5m])

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

# P99 latency
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))

# CPU usage per instance
100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

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

# Top 10 busiest endpoints
topk(10, sum by (handler) (rate(http_requests_total[5m])))

# Alert: Error rate lebih dari 5% dalam 5 menit
sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) > 0.05

Arsitektur Prometheus

Diagram: Arsitektur Monitoring dengan Prometheus
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  PROMETHEUS ARCHITECTURE                    β”‚
β”‚                                                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ Node     β”‚  β”‚ App      β”‚  β”‚ MySQL    β”‚  β”‚ Redis    β”‚  β”‚
β”‚  β”‚ Exporter β”‚  β”‚ Metrics  β”‚  β”‚ Exporter β”‚  β”‚ Exporter β”‚  β”‚
β”‚  β”‚ :9100    β”‚  β”‚ :8080    β”‚  β”‚ :9104    β”‚  β”‚ :9121    β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β”‚
β”‚       β”‚              β”‚              β”‚              β”‚        β”‚
β”‚       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                             β”‚ Scrape (pull)                 β”‚
β”‚                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”                      β”‚
β”‚                    β”‚   PROMETHEUS    β”‚                      β”‚
β”‚                    β”‚   :9090         β”‚                      β”‚
β”‚                    β”‚                 β”‚                      β”‚
β”‚                    β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚                      β”‚
β”‚                    β”‚ β”‚ TSDB        β”‚ β”‚                      β”‚
β”‚                    β”‚ β”‚ (Storage)   β”‚ β”‚                      β”‚
β”‚                    β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚                      β”‚
β”‚                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                      β”‚
β”‚                             β”‚                                β”‚
β”‚              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                β”‚
β”‚              β–Ό                             β–Ό                β”‚
β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”‚
β”‚    β”‚     GRAFANA      β”‚          β”‚ ALERTMANAGER β”‚          β”‚
β”‚    β”‚  (Visualisasi)   β”‚          β”‚  (Notifikasi)β”‚          β”‚
β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

7. Grafana: Visualisasi & Dashboard

Grafana adalah platform visualisasi data open-source yang mendukung berbagai sumber data seperti Prometheus, Elasticsearch, InfluxDB, PostgreSQL, dan banyak lagi. Grafana memungkinkan Anda membuat dashboard interaktif yang indah untuk memvisualisasikan metrics.

Fitur Utama Grafana

Fitur Penjelasan
Multi-DataSourceHubungkan Prometheus, Elasticsearch, SQL, dll dalam satu dashboard
Panel BeragamGraph, gauge, table, heat map, stat, bar chart, dll
Alerting Built-inAlert langsung dari dashboard panel
AnnotationTandai event penting seperti deploy atau incident pada grafik
Sharing & ExportShare dashboard sebagai link atau JSON provisioned
Template VariablesDashboard interaktif dengan dropdown filter

Instalasi Grafana

Bash β€” Instalasi Grafana
# Instalasi Grafana OSS di Ubuntu/Debian
sudo apt-get install -y apt-transport-https software-properties-common wget
wget -q -O - https://apt.grafana.com/gpg.key | sudo gpg --dearmor > /etc/apt/keyrings/grafana.gpg
echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt-get update
sudo apt-get install grafana

# Jalankan Grafana
sudo systemctl daemon-reload
sudo systemctl enable grafana-server
sudo systemctl start grafana-server

# Akses dashboard di http://localhost:3000
# Default login: admin / admin

Provisioning Data Source & Dashboard

YAML β€” Grafana Data Source Provisioning
# /etc/grafana/provisioning/datasources/prometheus.yml
apiVersion: 1

datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://prometheus:9090
    isDefault: true
    editable: false

  - name: Loki
    type: loki
    access: proxy
    url: http://loki:3100
    editable: false

  - name: Jaeger
    type: jaeger
    access: proxy
    url: http://jaeger:16686
    editable: false

Dashboard Best Practices

πŸ’‘ Tips Membuat Dashboard Efektif
  • Overview β†’ Detail: Mulai dari dashboard ringkasan, lalu drill-down ke detail
  • Golden Signals: Tampilkan Latency, Traffic, Errors, Saturation (dari SRE book)
  • Consistent Layout: Panel paling penting di kiri atas, kurang penting di kanan bawah
  • Template Variables: Buat dropdown untuk filter namespace, service, instance
  • Annotation: Tandai waktu deploy untuk korelasi perubahan performa
  • Jangan Overload: Dashboard harus bisa dibaca dalam 5 detik sekilas

8. Alerting: Sistem Peringatan Cerdas

Alerting adalah komponen kritis dalam monitoring yang memastikan tim operasional mendapat notifikasi tepat waktu saat ada masalah. Alert yang baik harus informatif, actionable, dan tidak membuat tim kelelahan (alert fatigue).

Prinsip Alerting yang Baik

Prinsip Penjelasan
ActionableSetiap alert harus memerlukan tindakan manusia atau di-acknowledge
Urgent & ImportantHanya alert untuk kondisi yang mempengaruhi pengguna atau SLA
DiagnosableAlert harus menyertakan konteks yang cukup untuk diagnosis awal
ProportionalTingkat urgensi sesuai dengan dampak aktual
No Alert FatigueHindari alert terlalu sensitif yang sering false positive

Konfigurasi Alert Rules di Prometheus

YAML β€” Prometheus Alert Rules
# alert_rules.yml
groups:
  - name: application_alerts
    rules:
      # Alert: Error rate tinggi
      - alert: HighErrorRate
        expr: |
          sum(rate(http_requests_total{status=~"5.."}[5m]))
          / sum(rate(http_requests_total[5m]))
          > 0.05
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Error rate tinggi terdeteksi"
          description: "Error rate {{ $value | humanizePercentage }} melebihi 5% selama 5 menit"
          runbook_url: "https://wiki.internal/runbook/high-error-rate"

      # Alert: Latency P99 tinggi
      - alert: HighP99Latency
        expr: |
          histogram_quantile(0.99,
            sum(rate(http_request_duration_seconds_bucket[5m])) by (le)
          ) > 2
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "P99 latency tinggi: {{ $value }}s"

      # Alert: Disk usage hampir penuh
      - alert: DiskSpaceRunningLow
        expr: |
          (1 - node_filesystem_avail_bytes / node_filesystem_size_bytes)
          * 100 > 85
        for: 15m
        labels:
          severity: warning
        annotations:
          summary: "Disk usage {{ $value }}% pada {{ $labels.instance }}"

      # Alert: Pod restart berulang
      - alert: PodCrashLooping
        expr: |
          increase(kube_pod_container_status_restarts_total[1h]) > 3
        labels:
          severity: critical
        annotations:
          summary: "Pod {{ $labels.pod }} crash looping"

Konfigurasi Alertmanager

YAML β€” Alertmanager Configuration
# alertmanager.yml
global:
  resolve_timeout: 5m

route:
  receiver: 'default'
  group_by: ['alertname', 'severity']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  routes:
    - match:
        severity: critical
      receiver: 'pagerduty-critical'
      repeat_interval: 15m
    - match:
        severity: warning
      receiver: 'slack-warning'

receivers:
  - name: 'default'
    slack_configs:
      - api_url: 'https://hooks.slack.com/services/xxx'
        channel: '#alerts'
        title: '[{{ .Status | toUpper }}] {{ .GroupLabels.alertname }}'
        text: '{{ range .Alerts }}{{ .Annotations.description }}\n{{ end }}'

  - name: 'pagerduty-critical'
    pagerduty_configs:
      - service_key: 'your-pagerduty-key'

  - name: 'slack-warning'
    slack_configs:
      - api_url: 'https://hooks.slack.com/services/yyy'
        channel: '#alerts-warning'
        title: '[WARNING] {{ .GroupLabels.alertname }}'
⚠️ Hindari Alert Fatigue

Alert fatigue terjadi ketika tim menerima terlalu banyak alert, sehingga alert yang benar-benar penting diabaikan. Beberapa strategi untuk menghindarinya:

  • Gunakan for clause untuk memastikan kondisi berlangsung cukup lama sebelum alert
  • Group alert yang serupa untuk mengurangi noise
  • Rutin review dan matikan alert yang sering false positive
  • Gunakan escalation policy berbeda untuk severity berbeda

9. SLA, SLO & SLI: Mengukur Kualitas Layanan

Dalam operasi sistem production, penting untuk memiliki standar kualitas layanan yang jelas dan terukur. Tiga konsep utama dalam framework ini adalah SLI (Service Level Indicator), SLO (Service Level Objective), dan SLA (Service Level Agreement).

Perbedaan SLI, SLO, dan SLA

Istilah Definisi Contoh
SLIMetrik kuantitatif yang mengukur tingkat kualitas layananPersentase request yang berhasil, latency P99
SLOTarget internal untuk SLI yang ingin dicapaiAvailability 99.9%, P99 latency < 200ms
SLAPerjanjian formal dengan konsekuensi jika tidak terpenuhiUptime 99.9% dengan credit jika gagal

Error Budget

Error Budget adalah sisa toleransi error yang tersedia berdasarkan SLO. Jika SLO Anda adalah 99.9% availability, maka Anda memiliki error budget sebesar 0.1% atau sekitar 43.8 menit downtime per bulan.

PromQL β€” Menghitung Error Budget
# SLO: 99.9% availability (error budget = 0.1%)

# Total request dalam 30 hari
total_requests = sum(increase(http_requests_total[30d]))

# Total error request dalam 30 hari
error_requests = sum(increase(http_requests_total{status=~"5.."}[30d]))

# Actual availability
actual_availability = (1 - error_requests / total_requests) * 100

# Error budget remaining (dalam persentase)
error_budget_total = 0.1  # 0.1% for 99.9% SLO
error_budget_consumed = (error_requests / total_requests) * 100
error_budget_remaining = error_budget_total - error_budget_consumed

# Error budget remaining (dalam menit per bulan)
error_budget_minutes = error_budget_remaining / 100 * 30 * 24 * 60

Contoh SLO untuk Berbagai Layanan

Layanan SLI SLO Error Budget / Bulan
API GatewayAvailability99.95%~21.6 menit
Payment ServiceAvailability99.99%~4.38 menit
Notification ServiceAvailability99.9%~43.8 menit
Analytics PipelineData Freshness< 5 menit lagN/A
CDN / Static AssetsP95 Latency< 100msN/A
πŸ’‘ Error Budget Policy

Buat kebijakan error budget yang jelas. Contoh:

  • Error budget > 50% tersisa: Tim boleh melakukan deployment berisiko tinggi
  • Error budget 20-50%: Deployment dengan approval, tambah testing
  • Error budget < 20%: Freeze deployment, fokus stabilitas
  • Error budget habis: Code freeze total, semua engineer fokus reliability

10. Quiz: Uji Pemahamanmu!

Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang Monitoring & Observability:

Pertanyaan 1: Manakah yang merupakan tiga pilar observability?

a) CPU, Memory, Disk
b) Metrics, Logs, Traces
c) Monitoring, Alerting, Dashboard
d) Prometheus, Grafana, Elasticsearch

Pertanyaan 2: Apa kepanjangan SLI dalam konteks SRE?

a) Service Level Information
b) System Level Integration
c) Service Level Indicator
d) Standard Level Interface

Pertanyaan 3: Model apa yang digunakan Prometheus untuk mengumpulkan metrics?

a) Push model β€” aplikasi mengirim metrics ke Prometheus
b) Pull model β€” Prometheus mengambil (scrape) metrics dari target
c) Event-driven model β€” metrics dikirim hanya saat error
d) Hybrid model β€” gabungan push dan pull

Pertanyaan 4: Apa itu error budget dalam konteks SLO?

a) Batas maksimum biaya operasi server
b) Sisa toleransi error yang tersedia berdasarkan SLO yang ditetapkan
c) Jumlah maksimum alert yang boleh dikirim per hari
d) Batas minimum performa yang harus dicapai

Pertanyaan 5: Mengapa structured logs (JSON) lebih baik daripada unstructured logs?

a) Karena format JSON lebih ringan ukurannya
b) Karena lebih mudah di-parsing, di-search, dan di-index oleh sistem log management
c) Karena JSON didukung oleh semua bahasa pemrograman
d) Karena structured logs tidak memerlukan log storage