Kodeloka
  1. Kodeloka
  2. Kelas Grafana
  3. Materi

Modul 3 · Modul 3 dari 15

Data Source: Prometheus, Loki, SQL, dan Aturan UID

Menghubungkan Grafana ke sumber data dengan benar, memahami UID, dan menghindari jebakan kredensial serta keamanan kueri SQL.

Data Source adalah Kontrak

Sebuah data source di Grafana bukan sekadar URL. Ia menentukan bahasa kueri yang tersedia, editor yang muncul, kemampuan alerting, serta cara Grafana menghitung interval waktu. Salah memilih tipe berarti seluruh dashboard harus ditulis ulang.

UID — Bagian yang Paling Sering Diabaikan

Setiap data source punya UID, dan JSON dashboard menyimpan referensi ke UID itu, bukan ke namanya.

cuplikan paneljson
{
  "datasource": { "type": "prometheus", "uid": "prom-utama" },
  "targets": [{ "expr": "up", "refId": "A" }]
}
⛔ Ini penyebab "Datasource not found" saat impor dashboard

Bila UID dibiarkan digenerate acak, maka data source di staging dan produksi punya UID berbeda. Dashboard yang diekspor dari staging akan mencari UID yang tidak ada di produksi.

Solusinya: tetapkan UID secara eksplisit lewat provisioning, dan pakai UID yang sama di seluruh lingkungan.

Provisioning Data Source (cara yang benar)

provisioning/datasources/sumber.ymlyaml
apiVersion: 1

deleteDatasources:
  - name: Prometheus Lama
    orgId: 1

datasources:
  - name: Prometheus
    uid: prom-utama              # WAJIB eksplisit
    type: prometheus
    access: proxy                # server-side, bukan browser
    url: http://prometheus:9090
    isDefault: true
    jsonData:
      httpMethod: POST           # query panjang tidak kena batas URL
      timeInterval: "15s"        # = scrape_interval; dasar $__rate_interval
      queryTimeout: "60s"
      manageAlerts: true
      prometheusType: Prometheus
      prometheusVersion: "3.1.0"
      cacheLevel: "Low"
      exemplarTraceIdDestinations:
        - name: trace_id
          datasourceUid: tempo-utama
    editable: false              # cegah perubahan diam-diam lewat UI

  - name: Loki
    uid: loki-utama
    type: loki
    access: proxy
    url: http://loki:3100
    jsonData:
      maxLines: 1000
      derivedFields:
        - name: TraceID
          matcherRegex: "trace_id=(\\w+)"
          url: "${__value.raw}"
          datasourceUid: tempo-utama

  - name: Postgres Bisnis
    uid: pg-bisnis
    type: postgres
    access: proxy
    url: db:5432
    user: grafana_ro             # WAJIB read-only
    database: bayarcepat
    secureJsonData:
      password: $__env{PG_GRAFANA_PASSWORD}
    jsonData:
      sslmode: require
      postgresVersion: 1700
      timescaledb: false
      maxOpenConns: 10
      maxIdleConns: 5
      connMaxLifetime: 14400

access: proxy vs direct

proxy (server)direct (browser)
Siapa yang memanggilServer GrafanaBrowser pengguna
Data source di jaringan privat✅ Bisa❌ Tidak bisa
Kredensial terlihat pengguna❌ Tidak✅ Ya — bocor
Perlu CORSTidakYa

Praktis selalu gunakan proxy. Mode direct sudah usang dan dihapus untuk banyak tipe data source.

timeInterval: Setelan Kecil, Dampak Besar

timeInterval memberi tahu Grafana berapa scrape interval data source Anda. Nilai ini menjadi dasar perhitungan $__rate_interval.

rumustext
$__rate_interval = max(interval + scrape_interval, 4 × scrape_interval)

Dengan scrape_interval 15s dan interval panel 30s:
  max(30s + 15s, 60s) = 60s

Bila timeInterval TIDAK diset (default 1s):
  max(30s + 1s, 4s) = 31s   ← terlalu pendek, grafik rate berlubang
⚠️ Kredensial SQL wajib read-only

Grafana mengirimkan kueri SQL apa adanya. Siapa pun yang bisa mengedit panel bisa menulis DELETE FROM pesanan. Grafana tidak menyaring kueri untuk Anda.

setup-user.sqlsql
CREATE USER grafana_ro WITH PASSWORD 'rahasia';
GRANT CONNECT ON DATABASE bayarcepat TO grafana_ro;
GRANT USAGE ON SCHEMA public TO grafana_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO grafana_ro;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT ON TABLES TO grafana_ro;

-- opsional tapi dianjurkan: batasi durasi kueri
ALTER ROLE grafana_ro SET statement_timeout = '30s';

Makro SQL yang Wajib Dipakai

Panel SQL harus menghormati time range dashboard. Grafana menyediakan makro untuk itu:

MakroMenjadi
$__timeFilter(kolom)kolom BETWEEN '...' AND '...'
$__timeGroup(kolom, '5m')Pembulatan waktu untuk GROUP BY
$__timeGroupAlias(kolom, $__interval)Sama, plus alias time
$__intervalInterval otomatis sesuai lebar panel
$__unixEpochFilter(kolom)Filter untuk kolom epoch integer
panel transaksi per menitsql
SELECT
  $__timeGroupAlias(dibuat_pada, $__interval),
  status                              AS metric,
  count(*)                            AS nilai
FROM transaksi
WHERE $__timeFilter(dibuat_pada)
  AND merchant_id = $merchant
GROUP BY 1, 2
ORDER BY 1;
💡 Format time series dari SQL

Agar hasil SQL dibaca sebagai time series, frame harus punya: kolom waktu bernama time, kolom nilai numerik, dan opsional kolom string bernama metric sebagai pemisah series. Tanpa pola ini, panel akan menampilkannya sebagai tabel biasa.