Membedah tiga pilar observability — metrics, logs, traces — peran OpenTelemetry sebagai standar vendor-neutral, dan cara mengkorelasikan ketiganya untuk menjawab apa yang terjadi, kenapa, dan di mana, lalu menginstrumentasi satu service dengan OTel

Setelah di episode 3-4 kita mendefinisikan SLI dan SLO, kini tiba saatnya menjawab pertanyaan praktis: dari mana angka SLI itu datang? Jawabannya adalah observability — kemampuan sistem untuk dieksplorasi berdasarkan data yang dikeluarkannya sendiri. Tanpa observability, SLO hanyalah janji; dengan observability, SLO menjadi fakta yang bisa diukur, di-debug, dan dikelola.
Episode ini membangun fondasi yang dipakai di seluruh sisa series: tiga pilar observability, standar OpenTelemetry, dan teknik korelasi lintas pilar. Kita akhiri dengan instrumentasi nyata satu service memakai OpenTelemetry (OTel) — yang sudah kalian kenal dari series terpisah — agar korelasi di episode-episode selanjutnya terasa konkret.
Metrics adalah angka teragregasi yang mencerminkan perilaku sistem pada titik waktu tertentu: request count, latency histogram, CPU usage. Kekuatannya: murah, padat, dan bisa diagregasi untuk dashboard dan alert. Kelemahannya: angka agregat tidak memberi tahu kalian request mana yang gagal, atau mengapa.
Contoh metrik khas sebuah service HTTP:
http_requests_total{status="500"} — total request per status.http_request_duration_seconds_bucket{le="0.1"} — histogram latency.http_in_flight_requests — request yang sedang berjalan (bagus untuk mendeteksi queuing).Logs adalah catatan kejadian diskrit dengan timestamp — satu baris per kejadian. Kekuatannya: detail penuh, konteks variabel, dan urutan kejadian yang jelas. Kelemahannya: volumenya besar dan mahal; tanpa agregasi yang baik, logs jadi tumpukan sampah.
2026-08-16T12:00:01.123Z ERROR payment-service order=8f3a charge failed: card_declined
2026-08-16T12:00:01.124Z INFO payment-service order=8f3a retry in 3sTraces adalah perjalanan satu request melintasi banyak service, direpresentasikan sebagai kumpulan span yang tersambung (parent-child). Kekuatannya: korelasi lintas service — kalian bisa melihat bahwa 80% latency datang dari call ke database. Kelemahannya: tanpa sampling yang benar, biaya penyimpanannya meledak.
Setiap pilar punya backend yang berbeda-beda (Prometheus untuk metrics, Loki untuk logs, Jaeger/Tempo untuk traces). Tanpa standar, tiap service memakai SDK berbeda dan korelasi antar-pilar hampir mustahil. OpenTelemetry (OTel) menyelesaikan ini: satu set API/SDK untuk menghasilkan semua telemetry, plus Collector sebagai router data yang menerima lalu meneruskan ke backend mana pun.
Skenario khas SRE modern:
service-python --OTLP--> otel-collector --> prometheus (metrics)
--> loki (logs)
--> tempo/jaeger(traces)Dengan OTel, kode aplikasi tidak tahu ke mana data dikirim — keputusan ada di konfigurasi Collector. Ini memisahkan instrumentasi dari backend, persis prinsip "jangan kunci aplikasi ke vendor observability".
Pilar terpisah belum berarti observability. Nilainya muncul saat bisa dilintasi: dari grafik metrics yang aneh, menyelam ke trace yang lambat, lalu membuka log span tersebut.
Alat penghubungnya adalah korelasi otomatis:
trace_id=8f3a...).Praktik wajib sejak hari pertama: selalu log trace_id. Tanpa itu, menemukan log yang relevan saat trace terdeteksi lambat adalah pencarian jarum di tumpukan jerami.
Tip
Mulailah dengan menginstrumentasi satu jalur kritis — misalnya POST /api/checkout. Instrumentasi penuh semua endpoint sekaligus hanya membuat noise. Satu jalur yang benar-benar terinstrumentasi memberi kalian cetak biru untuk sisanya, dan hasilnya bisa langsung dikorelasi dari metrics sampai logs.
Buat service Python kecil yang mengekspos metrics dan traces. Pertama, install SDK:
pip install opentelemetry-sdk \
opentelemetry-api \
opentelemetry-exporter-otlp-proto-grpc \
opentelemetry-instrumentation-flask \
opentelemetry-instrumentation-requestsLalu service-nya:
from flask import Flask
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry.sdk.resources import Resource
resource = Resource.create({"service.name": "demo-service"})
trace.set_tracer_provider(TracerProvider(resource=resource))
trace.get_tracer_provider().add_span_processor(
BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4317"))
)
app = Flask(__name__)
FlaskInstrumentor().instrument_app(app)
@app.route("/health")
def health():
return {"status": "ok"}Jalankan dengan collector yang menerima OTLP (stack episode 0 opsional ditambah collector):
python app.py &
curl -s localhost:5000/health
curl -s "http://localhost:9090/api/v1/query?query=http_server_duration_count" | jq .data.result[].metricNote
Instrumentasi otomatis (FlaskInstrumentor) menangkap span HTTP dan metrics request tanpa menyentuh logika bisnis. Untuk jalur bisnis (seperti perhitungan harga), tambahkan span manual — contoh lengkapnya kita bedah di episode 21 saat membahas pola resiliency dalam kode.
Pada episode 5 ini, kalian telah membangun fondasi observability yang dipakai seluruh series.
Inti yang harus dibawa pulang:
trace_id.Di episode 6 selanjutnya, kita akan membahas alerting & on-call — cara merancang alert yang akurat, relevan, dan actionable, mengatasi alert fatigue, serta menyusun on-call rotation yang sehat untuk tim. Sampai jumpa di episode 6!