Membawa hasil load test keluar dari terminal: mengirim data ke InfluxDB, Prometheus, atau file JSON, menampilkannya di dashboard Grafana, serta memakai custom metrics dan tagging untuk analisis yang lebih dalam pada setiap endpoint dan skenario.

Di episode 13 kalian sudah belajar membaca ringkasan akhir k6 — p(95), p(99), error rate, throughput. Tapi ringkasan itu hanya snapshot di akhir tes: angka satu waktu, tanpa riwayat. Sebuah load test sesungguhnya punya bentuk, bukan hanya kesimpulan. Kapan latensi mulai memburuk? Apakah VU ke-50 adalah titik di mana sistem mulai lelah? Pertanyaan semacam ini tidak bisa dijawab oleh satu tabel terminal — butuh data mentah yang tersimpan dan bisa divisualisasikan.
Episode 14 menutup bagian fundamental series ini dengan observability: bagaimana mengirim hasil k6 ke sistem penyimpanan metrik (InfluxDB, Prometheus, atau file JSON), menampilkannya di dashboard Grafana yang bisa dibagikan ke tim, dan memperkaya data dengan custom metrics dan tagging agar analisisnya tajam, bukan sekadar cantik. Ringkasan terminal adalah laporan; dashboard adalah cerita yang terus bergulir.
k6 menampilkan ringkasan di akhir, tetapi data mentah itu bisa dikirim ke banyak tujuan dengan flag -o (output). Flag -o bisa ditumpuk, sehingga satu tes bisa menulis ke file dan ke database sekaligus. Tiga output yang paling penting untuk dipahami:
k6 run -o json=results.json script.jsk6 run -o influxdb=http://localhost:8086/k6 script.jsk6 run -o experimental-prometheus-rw=http://localhost:9090/api/v1/write script.jsjson=results.json — menyimpan seluruh data point mentah. Berguna untuk audit, post-processing, atau menggabungkan hasil beberapa tes. File JSON ini adalah kebenaran penuh; dashboard apa pun hanyalah cara membaca kebenaran itu.influxdb=http://host/db — menulis ke database time-series InfluxDB. Bagian setelah host adalah nama database (contoh di atas: k6). Ini jalur klasik dan sangat stabil untuk pairing k6 + Grafana.experimental-prometheus-rw=http://host/api/v1/write — menulis ke Prometheus melalui remote write. Jalur ini tumbuh menjadi standar modern karena Prometheus adalah pusat ekosistem metrik banyak organisasi.Tip
Grafana Cloud menyediakan integrasi k6 bawaan: jalankan tes dari cloud dan dashboard terisi otomatis. Untuk Datadog, k6 tidak punya output bawaan — gunakan ekosistem sekitarnya, misalnya extension xk6 atau meneruskan hasil lewat aggregator pihak ketiga. Polanya selalu sama: hasil tes dikirim ke tujuan eksternal, lalu divisualisasikan di sana.
Cara termurah untuk merasakan observability penuh adalah menjalankan InfluxDB dan Grafana lokal dengan Docker Compose, lalu menembaki stack itu dengan k6. Gambaran lengkapnya:
services:
influxdb:
image: influxdb:1.8
container_name: influxdb
ports:
- "8086:8086"
environment:
- INFLUXDB_DB=k6
volumes:
- influxdb-data:/var/lib/influxdb
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
volumes:
influxdb-data:
grafana-data:Perhatikan INFLUXDB_DB=k6 — ini menyuruh InfluxDB membuat database k6 saat pertama kali boot, database yang persis dituju oleh -o influxdb=http://localhost:8086/k6. Sedangkan Grafana hanya butuh port 3000 dan volume untuk menyimpan konfigurasi dashboard. Dengan satu docker compose up -d, kalian punya gudang data metrik dan tempat memandangnya.
Setelah stack hidup, jalankan tes dengan output InfluxDB:
k6 run -o influxdb=http://localhost:8086/k6 script.jsGrafana adalah panel tempat cerita performa dibaca. Langkah penyiapannya:
http://influxdb:8086 (nama service dari Compose, DNS internal berfungsi otomatis) dan database dengan k6.SELECT mean("value") FROM "http_req_duration" WHERE $timeFilter GROUP BY time($__interval) fill(null)http_req_duration), error rate (http_req_failed), jumlah request (http_reqs), dan VU aktif (vus). Keempatnya adalah empat sudut dari pertanyaan yang sama: "apakah sistem masih sehat, dan di titik mana ia mulai menderita?"Dari sini muncul analisis yang tidak mungkin dilakukan lewat terminal: grafik latensi yang naik bersamaan dengan kenaikan VU menunjukkan titik kapasitas; garis error yang menyentuh langit-langit di menit tertentu menunjukkan peristiwa yang perlu diselidiki. Dashboard juga bisa dibagikan — tim dapat melihat tren mingguan, bukan hanya hasil satu malam.
Tanpa tag, semua request tercampur dalam satu angka http_req_duration. Padahal login, daftar produk, dan checkout punya profil latensi yang sangat berbeda. Tag adalah label yang ditempel pada data point, dan inilah yang mengubah dashboard dari "berapa rata-rata seluruh aplikasi" menjadi "endpoint mana yang sedang menderita".
Tag test-wide didefinisikan di opsi, dan berlaku untuk semua metrik:
export const options = {
vus: 50,
duration: "5m",
tags: {
environment: "staging",
release: __ENV.RELEASE_TAG || "dev",
},
};Tag per-request memisahkan data di dalam satu tes — ini yang dipakai untuk membandingkan endpoint:
const res = http.get("https://api.example.com/v1/login", {
tags: { endpoint: "login" },
});
const res2 = http.get("https://api.example.com/v1/checkout", {
tags: { endpoint: "checkout" },
});Nilai tag yang ingin dikendalikan dari luar bisa disuntikkan lewat -e dan dibaca melalui __ENV — pola yang sama seperti secret di episode 12, tetapi untuk data non-rahasiakan:
k6 run -e K6_TAGS=staging -e RELEASE_TAG=v1.2.3 script.jsDi Grafana, tag menjadi kolom yang bisa dijadikan filter: WHERE "endpoint"='login' memisahkan kurva login dari checkout; environment='staging' membandingkan hasil antar lingkungan. Tanpa tagging, analisis semacam ini mustahil — dan dengan tagging, dashboard kalian menjawab pertanyaan yang jauh lebih tajam.
k6 mengukur latensi request, tapi ada hal yang tidak diukur otomatis — misalnya berapa lama waktu parsing JSON di sisi klien, atau ukuran response. Untuk itu k6 menyediakan custom metrics. Trend adalah tipe yang paling berguna untuk nilai yang berubah sepanjang waktu, dan ia mendapat perlakuan penuh: statistik, persentil, dan bisa ditampilkan di dashboard:
import { Trend } from "k6/metrics";
import http from "k6/http";
import { check } from "k6";
const waktuParseJson = new Trend("waktu_parse_json", true);
export default function () {
const res = http.get("https://api.example.com/v1/data");
check(res, { "response 200": (r) => r.status === 200 });
const mulai = Date.now();
JSON.parse(res.body);
waktuParseJson.add(Date.now() - mulai);
}Argumen kedua true pada new Trend("waktu_parse_json", true) menandakan nilai yang dimasukkan akan dianggap sebagai durasi (di-render dengan satuan waktu di ringkasan dan dashboard). Sekarang waktu_parse_json muncul di summary dan di InfluxDB seperti metrik bawaan — lengkap dengan p(95)-nya sendiri. Ini cara kalian menambahkan dimensi performa yang tidak terpikirkan oleh siapa pun sebelumnya, dan inilah esensi observability: bukan sekadar melihat data yang ada, tetapi mengumpulkan data yang menjawab pertanyaan spesifik tim kalian.
environment, release, dan endpoint sejak hari pertama — lebih mudah menambahkan tag daripada memutar waktu.true (durasi) atau false (nilai biasa) sesuai semantiknya.Pada episode 14 ini kalian telah membawa hasil k6 keluar dari terminal: memahami tiga output utama (json, influxdb, dan experimental-prometheus-rw), merakit stack lokal InfluxDB + Grafana + k6 dengan Docker Compose, menyusun dashboard Grafana dengan query dan panel yang menjawab pertanyaan performa, memperkaya data dengan tag test-wide dan per-request (termasuk injeksi nilai tag lewat -e), serta membuat custom metrics Trend untuk mengukur hal-hal yang belum diukur k6.
Inti yang harus kalian bawa:
-o bisa ditumpuk: file JSON untuk arsip, database untuk dashboard.Dengan observability, satu siklus pembelajaran k6 telah kalian tempuh dari nol: dari menulis script pertama hingga melihat performa aplikasi dalam kurva dan tren yang bisa dibagikan ke tim. Tapi dunia nyata tidak selalu menghasilkan kurva yang mulus. Di episode 15 selanjutnya kita akan membahas Resilience & Failure Analysis — bagaimana memuat skenario yang mengandung kegagalan (retry, timeouts, backpressure) agar kalian tahu aplikasi kalian tetap berdiri justru ketika keadaan sedang tidak baik-baik saja. Sampai jumpa di episode 15!