Membangun observability sebagai platform: Prometheus untuk metrics, Grafana untuk dashboard, Loki untuk logs, Tempo untuk traces, dan OpenTelemetry sebagai standar pengumpul data di seluruh stack

Setelah di episode 8 kita melihat bahwa service mesh menghasilkan telemetry otomatis, pertanyaannya menjadi: data itu mau dikirim ke mana, dan siapa yang memakainya? Tanpa observability platform, telemetry mesh hanyalah angka yang menumpuk di proxy. Observability platform mengubah data menjadi jawaban atas pertanyaan operasional: kenapa lambat? kenapa error? apa yang berubah?
Mengapa observability harus menjadi platform, bukan koleksi tool per tim? Karena dalam insiden, data dari berbagai sumber harus bisa di-correlate: metrik (nilai), log (detail), dan trace (perjalanan request). Platform engineer menyediakan satu stack terpadu sehingga tim tidak perlu membangun dan memelihara stack observability sendiri-sendiri — yang hampir selalu berakhir dengan biaya besar dan cakupan yang tidak merata.
Tiga sinyal klasik yang saling melengkapi:
| Sinyal | Pertanyaan yang Dijawab | Alat Utama |
|---|---|---|
| Metrics | Apa yang terjadi? (angka, tren) | Prometheus |
| Logs | Kenapa terjadi? (detail per peristiwa) | Loki |
| Traces | Di mana terjadi? (perjalanan request) | Tempo |
Di belakangnya ada OpenTelemetry (OTel) — standar terbuka untuk mengumpulkan telemetry dari aplikasi. Alur lengkapnya:
Prometheus adalah standar de facto metrics di ekosistem CNCF — hampir semua sistem cloud-native mengekspos metrics dalam format Prometheus. Di platform, Prometheus mengambil peran sentral:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: payments-api
namespace: team-payments-prod
spec:
selector:
matchLabels:
app: payments-api
endpoints:
- port: http
path: /metrics
interval: 15sDengan ServiceMonitor (dari kube-prometheus-stack), setiap service yang mengekspos /metrics otomatis di-scrape — tanpa konfigurasi manual per service. Ini adalah bagian dari "secure by default" observability: service baru langsung terlihat.
Metrik yang paling penting untuk dipantau platform-wide — empat golden signals:
| Sinyal | Contoh Query PromQL | Pertanyaan |
|---|---|---|
| Latency | histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service)) | Seberapa cepat? |
| Traffic | sum(rate(http_requests_total[5m])) by (service) | Seberapa ramai? |
| Errors | sum(rate(http_requests_total{status=~"5.."}[5m])) by (service) | Berapa yang gagal? |
| Saturation | 100 - (avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) | Sudah hampir penuh? |
Keempat sinyal ini adalah bahan dasar SLO yang akan kita bangun di episode 17.
Loki berbeda dari Elasticsearch: ia tidak mengindeks isi log, hanya label — sehingga jauh lebih murah dan terintegrasi native dengan Prometheus (label yang sama). Pola pemakaiannya: log dicari berdasarkan label, lalu isi log dibaca dari tempatnya.
# Selector log per service
{namespace="team-payments-prod"} |= "ERROR"
{app="payments-api"} | json | level="error" | line_format "{{.message}}"Loki menyelesaikan masalah praktis: correlate log dengan metrik. Saat metrik error rate naik, satu klik dari Grafana langsung ke log service yang sama — tanpa pindah tool.
Di platform microservice, satu request melewati banyak service. Tempo menyimpan traces dengan pendekatan seperti Loki: menyimpan raw traces murah, mencari berdasarkan label. Ini melengkapi loop: trace menunjukkan service mana yang lambat, log menunjukkan detailnya, metrik menunjukkan trennya.
# 1. Aplikasi kirim traces via OTel
# 2. Tempo simpan raw traces dengan label service
# 3. Grafana trace view -> klik span yang lambat
# 4. Jumper langsung dari trace ke log (traceId) & metrik serviceKunci integrasi: traceId juga ditulis di log (bagian dari OTel semantic conventions), sehingga dari log bisa lompat ke trace dan sebaliknya. Ini adalah pengalaman "one pane of glass" yang menjadi tujuan observability platform.
OpenTelemetry adalah standar yang menyatukan semuanya: SDK di aplikasi (otomatis atau manual), lalu OTel Collector sebagai router data yang fleksibel. Collector adalah komponen yang dipelihara platform team:
receivers:
otlp:
protocols:
grpc:
http:
processors:
batch:
exporters:
prometheus:
endpoint: 0.0.0.0:8889
namespace: otel
otlp:
endpoint: tempo:4317
tls:
insecure: true
loki:
endpoint: http://loki:3100/loki/api/v1/push
service:
pipelines:
metrics:
receivers: [otlp]
processors: [batch]
exporters: [prometheus]
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp]
logs:
receivers: [otlp]
processors: [batch]
exporters: [loki]Dengan Collector, aplikasi hanya mengirim ke satu tempat (OTLP) — urusan routing ke Prometheus/Loki/Tempo menjadi tanggung jawab platform. Standar ini juga mencegah vendor lock-in; jika besok pindah dari Grafana Stack ke Datadog, Collector saja yang berubah.
Important
Jangan biarkan setiap tim mengirim telemetry ke cloud vendor-nya sendiri. Aturan platform: semua telemetry lewat OTel Collector yang dikelola platform team, dengan endpoint dan retensi terpusat. Ini menjaga biaya terkendali (episode 11) dan data bisa di-correlate.
Grafana menyatukan semua sinyal di satu antarmuka. Dari sisi platform engineer, hal yang penting bukan hanya dashboard, tapi struktur folder dan permission:
| Folder | Isi | Viewer |
|---|---|---|
| Platform | Infrastruktur, cluster, stack | Tim platform |
| Team | Dashboard per tim | Tim terkait |
| Public | Golden signals semua service | Semua |
Pola folder ini menjaga Grafana tetap bisa dinavigasi saat service bertambah ratusan — dashboard yang berantakan menjadi tidak terpakai.
{
"title": "Service Overview",
"templating": {
"list": [
{
"name": "service",
"type": "query",
"query": "label_values(http_requests_total, service)"
}
]
},
"panels": [
{
"title": "Latency p99 per service",
"type": "timeseries",
"targets": [
{
"expr": "histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket{service=\"$service\"}[5m])) by (le))"
}
]
}
]
}Satu dashboard generic dengan dropdown $service jauh lebih baik daripada 50 dashboard per service — dan itulah pola yang seharusnya menjadi default platform.
Observability belum lengkap tanpa alerting. Di Grafana Stack, alatnya adalah Alertmanager (pasangan Prometheus). Prinsip alerting yang benar:
page (mendadak, butuh tindakan) vs ticket (informasional).groups:
- name: service-health
rules:
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
/ sum(rate(http_requests_total[5m])) by (service) > 0.05
for: 10m
labels:
severity: page
annotations:
summary: "Error rate {{ $labels.service }} di atas 5%"
runbook: "https://wiki/platform/runbooks/high-error-rate"Warning
Alert yang terlalu banyak akan diabaikan — alert fatigue adalah musuh terbesar observability. Platform engineer harus rela memangkas alert yang tidak actionable. Aturan praktis: jika alert tidak pernah menghasilkan tindakan, hapus.
Inti yang harus dibawa pulang:
Di episode 10 selanjutnya kita akan mengamankan sisi yang paling sering bocor: secrets & security platform — Vault/OpenBao untuk pengelolaan secrets, policy engine (OPA), dan pola secrets management yang benar di seluruh platform. Observability yang baik juga harus menyaksikan secrets yang aman!