Kodeloka
  1. Kodeloka
  2. Kelas OpenTelemetry
  3. Materi

3 · Metrik & Log · Modul 5 dari 8

Metrik & Instrumen

Memilih jenis instrumen yang tepat, dan menghindari ledakan kardinalitas yang menjatuhkan sistem metrik.

Jenis Instrumen

Counter                  hanya naik           permintaan, galat, byte terkirim
UpDownCounter            naik dan turun       koneksi aktif, antrean
Histogram                sebaran nilai        latensi, ukuran muatan
Gauge (asinkron)         nilai saat diamati   pemakaian memori, suhu
Counter asinkron         diamati berkala      penghitung dari sumber luar
import { metrics } from "@opentelemetry/api";

const meter = metrics.getMeter("layanan-pesanan", "2.4.1");

const pesananDibuat = meter.createCounter("pesanan.dibuat", {
    description: "Jumlah pesanan yang berhasil dibuat",
    unit: "{pesanan}"
});

const durasiProses = meter.createHistogram("pesanan.durasi_proses", {
    description: "Waktu memproses pesanan",
    unit: "ms"
});

const antreanAktif = meter.createUpDownCounter("pesanan.antrean", {
    unit: "{pesanan}"
});

pesananDibuat.add(1, { "pesanan.jenis": "langganan", "wilayah": "id-jkt" });
durasiProses.record(142, { "pesanan.jenis": "langganan" });

Kardinalitas: Bahaya Terbesar pada Metrik

Setiap kombinasi unik nilai atribut menghasilkan deret waktu tersendiri yang disimpan terpisah. Jumlahnya berlipat, bukan bertambah.

pesanan.dibuat{jenis, wilayah, status}
  jenis    5 nilai
  wilayah  8 nilai
  status   4 nilai
  → 5 × 8 × 4 = 160 deret waktu — masih aman

pesanan.dibuat{jenis, wilayah, status, pengguna_id}
  pengguna_id  500.000 nilai
  → 80.000.000 deret waktu — sistem metrik tumbang
🚫 Jangan pernah memasang ID sebagai label metrik

ID pengguna, ID pesanan, ID sesi, alamat IP, dan URL lengkap dengan parameter — semuanya memiliki kardinalitas tak terbatas. Satu penerapan yang menambahkan label semacam ini dapat menjatuhkan Prometheus dalam hitungan menit dan membuat seluruh pemantauan buta persis saat dibutuhkan. Nilai per-entitas adalah wilayah trace dan log, bukan metrik.

Histogram dan Pemilihan Bucket

const durasi = meter.createHistogram("http.server.request.duration", {
    unit: "s",
    advice: {
        explicitBucketBoundaries: [0.005, 0.01, 0.025, 0.05, 0.1,
                                   0.25, 0.5, 1, 2.5, 5, 10]
    }
});
⚠️ Persentil hanya seakurat batas bucket di sekitarnya

Nilai p99 dihitung dengan interpolasi di dalam bucket tempat ia jatuh. Bila mayoritas permintaan berada antara 100 dan 250 milidetik sementara bucket melompat dari 0,1 langsung ke 0,25, seluruh persentil di rentang itu hanya perkiraan kasar. Sesuaikan batas bucket dengan sebaran latensi yang sebenarnya, bukan memakai nilai bawaan begitu saja.

Temporalitas: Delta atau Kumulatif

Kumulatif   nilai terus bertambah sejak proses dimulai
            → yang diharapkan Prometheus
Delta       perubahan sejak pelaporan terakhir
            → yang diharapkan sebagian besar backend SaaS

export OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta
⚠️ Ketidakcocokan temporalitas menghasilkan grafik yang salah tanpa galat

Bila backend mengharapkan kumulatif tetapi menerima delta, tidak ada pesan kesalahan — angkanya sekadar keliru, biasanya jauh lebih kecil dan naik-turun tanpa pola. Ini termasuk masalah OTel yang paling lama tidak disadari karena semuanya tampak berjalan normal. Periksa preferensi temporalitas backend saat pertama kali menyiapkan metrik.

Log yang Terhubung ke Trace

import { trace } from "@opentelemetry/api";

function log(pesan, data = {}) {
    const span = trace.getActiveSpan();
    const ctx = span?.spanContext();
    console.log(JSON.stringify({
        waktu: new Date().toISOString(),
        pesan,
        trace_id: ctx?.traceId,
        span_id:  ctx?.spanId,
        ...data
    }));
}
💡 trace_id di dalam log adalah penghubung yang mengubah alur penyelidikan

Tanpa itu, menyelidiki insiden berarti mencocokkan stempel waktu antara trace dan log secara manual — lambat dan sering salah pada sistem yang sibuk. Dengan trace_id tercatat, satu klik dari span membuka seluruh log permintaan tersebut di semua layanan yang dilaluinya. Ini perubahan kecil di kode dengan dampak terbesar pada kecepatan penyelidikan.

Metrik dari Span

connectors:
  spanmetrics:
    dimensions:
      - name: http.request.method
      - name: http.response.status_code
      - name: service.name
    histogram:
      explicit:
        buckets: [5ms, 10ms, 50ms, 100ms, 500ms, 1s, 5s]

Konektor ini menghasilkan laju permintaan, laju galat, dan sebaran durasi langsung dari span — sehingga metrik dasar tersedia tanpa instrumentasi metrik terpisah, dan angkanya tetap benar meskipun trace kemudian disampel.

⚠️ Perhatikan dimensi yang dipilih pada spanmetrics

Setiap dimensi yang ditambahkan mengalikan jumlah deret waktu, persis seperti label metrik biasa. Menambahkan url.path yang berisi ID akan membawa ledakan kardinalitas dari sisi trace ke sisi metrik. Pastikan nama span sudah memakai pola rute sebelum dijadikan dimensi.