Visualisasi pipeline CI/CD dengan scuff chart berguna ketika metrik rata-rata tidak cukup menjelaskan masalah. Dua job bisa sama-sama punya rata-rata 8 menit, tetapi yang satu stabil di 7-9 menit sementara yang lain kadang selesai 3 menit dan kadang melonjak ke 20 menit. Dalam praktik DX, perbedaan ini sangat penting karena memengaruhi feedback loop developer, waktu merge, dan kepercayaan tim terhadap pipeline.
Artikel ini membahas cara memakai pendekatan scuff marks atau jejak gesekan untuk memvisualisasikan durasi pipeline: data apa yang perlu diambil dari log CI/CD, bagaimana mengelompokkan data per branch/job/runner, cara membangun dashboard sederhana, dan bagaimana membaca temuan untuk aksi nyata seperti paralelisasi, cache, split job, dan alert regresi durasi.
Apa itu scuff chart dan kapan lebih berguna daripada rata-rata
Scuff chart adalah visualisasi distribusi yang menampilkan banyak titik atau goresan tipis pada sumbu waktu. Alih-alih merangkum durasi job hanya dengan satu angka seperti rata-rata atau median, chart ini memperlihatkan sebaran, kepadatan, dan outlier secara langsung.
Secara praktis, setiap eksekusi job ditampilkan sebagai tanda kecil pada posisi durasinya. Jika banyak eksekusi menumpuk pada rentang tertentu, area itu terlihat lebih padat. Jika ada beberapa run yang jauh lebih lambat dari pola umum, outlier akan langsung terlihat sebagai titik yang menyendiri.
Mengapa rata-rata sering menyesatkan
- Distribusi bimodal: job kadang cepat karena cache hit, kadang lambat karena cache miss.
- Outlier tertutup agregasi: satu atau dua build yang sangat lambat bisa tidak terlalu terlihat pada rata-rata mingguan.
- Perubahan lingkungan: runner tertentu lebih lambat atau lebih sibuk daripada yang lain.
- Perbedaan branch: branch utama mungkin stabil, tetapi branch fitur memiliki pola yang lebih acak.
Jika tujuan Anda adalah meningkatkan developer experience, Anda tidak hanya ingin tahu “berapa rata-ratanya”, tetapi juga “seberapa sering pipeline terasa lambat” dan “apakah kelambatan terjadi pada kondisi tertentu”. Di sinilah scuff chart lebih informatif.
Data yang perlu diambil dari log pipeline
Untuk membangun visualisasi yang berguna, jangan mulai dari total durasi pipeline saja. Ambil data pada level run dan job. Semakin dekat ke unit kerja aktual, semakin mudah menemukan bottleneck yang bisa ditindaklanjuti.
Field minimal yang sebaiknya disimpan
- pipeline_id: identitas satu eksekusi pipeline.
- job_id: identitas satu job dalam pipeline.
- branch: misalnya main, develop, atau nama branch fitur.
- commit_sha: untuk menelusuri perubahan kode yang memicu regresi.
- job_name: contoh: test, lint, build-image, e2e.
- stage_name: jika CI Anda punya konsep stage.
- runner_id atau runner_label: penting untuk mengisolasi pengaruh lingkungan eksekusi.
- status: success, failed, canceled, timeout.
- queued_at, started_at, finished_at: untuk membedakan waktu antre dan waktu eksekusi.
- duration_seconds: lama job dieksekusi.
- queue_seconds: waktu tunggu sebelum job mulai, jika tersedia.
- cache_hit atau indikator serupa jika bisa diekstrak.
- retry_count: job yang sering retry sering menghasilkan distribusi aneh.
Jika memungkinkan, simpan juga metadata seperti ukuran artifact, perubahan file, atau jenis event pemicu pipeline (push, pull request, manual, scheduled). Data tambahan ini membantu saat menganalisis anomali, tetapi jangan menunda implementasi awal hanya karena belum lengkap.
Bedakan durasi eksekusi dan waktu tunggu
Kesalahan umum adalah mencampur queue time dan run time. Jika bottleneck sebenarnya ada pada kapasitas runner, optimasi script build tidak akan menyelesaikan masalah. Karena itu, idealnya Anda punya dua visualisasi:
- Durasi job: waktu dari job mulai hingga selesai.
- Waktu antre: waktu dari job dibuat hingga benar-benar mulai berjalan.
Jika pipeline terasa lambat bagi developer, queue time sama pentingnya dengan run time. Dari sudut pandang pengguna internal, keduanya sama-sama menambah waktu tunggu.
Skema data sederhana untuk dashboard
Anda tidak perlu langsung membangun data warehouse yang rumit. Untuk dashboard awal, satu tabel fakta untuk run job biasanya cukup.
Contoh skema data
table ci_job_runs {
pipeline_id string
job_id string
branch string
commit_sha string
job_name string
stage_name string
runner_label string
status string
queued_at timestamp
started_at timestamp
finished_at timestamp
duration_seconds integer
queue_seconds integer
cache_hit boolean
retry_count integer
created_at timestamp
}Jika Anda ingin ringkasan harian untuk query yang lebih cepat, tambahkan tabel agregat terpisah. Namun, tetap simpan data mentah per run agar analisis distribusi tidak hilang. Visualisasi seperti scuff chart bergantung pada sampel individual, bukan hanya statistik ringkasan.
Sumber data yang umum
- API CI/CD platform Anda untuk daftar pipeline dan job.
- Webhook dari event pipeline/job selesai.
- Ekspor log build atau observability pipeline jika sudah tersedia.
Pendekatan webhook biasanya lebih efisien untuk near-real-time. Pendekatan polling API lebih mudah untuk implementasi awal atau backfill histori.
Cara mengelompokkan data agar pola mudah dibaca
Visualisasi yang terlalu digabung justru mengaburkan pola. Kunci dari scuff chart yang berguna adalah segmentasi.
1. Per job
Mulai dari sini. Gabungan semua job hampir selalu terlalu bising karena karakteristik durasi lint, unit test, build image, dan end-to-end test sangat berbeda.
2. Per branch atau tipe branch
Branch main biasanya paling relevan untuk stabilitas baseline. Branch fitur atau pull request sering punya variasi lebih tinggi karena perubahan kode dan konteks build yang lebih beragam. Jika jumlah branch terlalu banyak, kelompokkan menjadi:
- main/default branch
- release branch
- feature/pull request branch
3. Per runner
Ini sering menjadi sumber insight tercepat. Jika job yang sama pada runner A stabil di 4-5 menit tetapi pada runner B sering 8-10 menit, masalahnya mungkin bukan di script pipeline, melainkan pada kapasitas CPU, I/O disk, jaringan, throttling, atau kontensi host.
4. Per hasil cache
Jika ada indikator cache hit, pisahkan chart untuk hit dan miss. Distribusi bimodal sering langsung terjelaskan dari sini.
5. Per rentang waktu
Lihat setidaknya dua jendela:
- 7-14 hari untuk memantau regresi terbaru.
- 30-90 hari untuk memahami pola musiman, perubahan infrastruktur, atau efek optimasi yang baru diterapkan.
Membangun scuff chart sederhana
Secara visual, scuff chart bisa dibuat sebagai titik-titik kecil atau garis pendek pada sumbu X yang mewakili durasi. Sumbu Y bisa diisi kategori, misalnya nama job atau runner. Jika ingin menonjolkan kepadatan, gunakan transparansi sehingga area yang sering dihuni terlihat lebih gelap.
Model visual yang praktis
- X-axis: durasi dalam detik atau menit.
- Y-axis: kategori, misalnya job_name.
- Mark: titik kecil atau garis pendek horizontal.
- Color: branch, runner, status, atau cache hit/miss.
- Opacity: rendah, agar kepadatan terlihat dari tumpukan mark.
Jika tool charting Anda tidak mendukung bentuk khusus, scatter plot biasa sudah cukup selama tiap run diplot sebagai titik individual.
Pseudocode agregasi data untuk dashboard
input:
job_runs[]
filters = {
from_date,
to_date,
branches[],
job_names[],
runner_labels[],
status[]
}
filtered = job_runs
.where(run.finished_at between filters.from_date and filters.to_date)
.where(run.branch in filters.branches if filters.branches not empty)
.where(run.job_name in filters.job_names if filters.job_names not empty)
.where(run.runner_label in filters.runner_labels if filters.runner_labels not empty)
.where(run.status in filters.status if filters.status not empty)
series = group filtered by run.job_name
for each group in series:
points = []
for each run in group:
points.push({
x: run.duration_seconds,
y: run.job_name,
color: run.runner_label,
branch: run.branch,
status: run.status,
queue_seconds: run.queue_seconds,
cache_hit: run.cache_hit,
commit_sha: run.commit_sha,
finished_at: run.finished_at
})
summary = {
count: count(group),
median: percentile(group.duration_seconds, 50),
p90: percentile(group.duration_seconds, 90),
p95: percentile(group.duration_seconds, 95),
min: min(group.duration_seconds),
max: max(group.duration_seconds)
}
output[group.job_name] = {
points,
summary
}
return outputPerhatikan bahwa statistik ringkasan seperti median dan p95 tetap berguna, tetapi jangan menggantikannya sebagai satu-satunya tampilan. Ringkasan dipakai untuk anotasi, sementara scuff marks dipakai untuk membaca pola.
Query agregasi contoh
Jika data Anda ada di SQL, pola query dasarnya sederhana:
SELECT
job_name,
branch,
runner_label,
duration_seconds,
queue_seconds,
status,
cache_hit,
commit_sha,
finished_at
FROM ci_job_runs
WHERE finished_at >= :from_date
AND finished_at < :to_date
AND status IN ('success', 'failed')
ORDER BY job_name, finished_at;Untuk dashboard yang responsif, Anda bisa menambahkan indeks pada kombinasi finished_at, job_name, branch, dan runner_label. Tetap sesuaikan dengan pola query nyata agar tidak menambah beban write yang tidak perlu.
Membaca pola scuff chart dan menerjemahkannya menjadi aksi
Nilai utama chart ini bukan pada bentuk visualnya, tetapi pada keputusan yang bisa diambil setelah pola terlihat.
Pola 1: Sebaran lebar, tetapi tanpa outlier ekstrem
Jika satu job sering bergerak antara 4 hingga 10 menit tanpa pola yang jelas, biasanya ada ketidakstabilan input atau lingkungan. Beberapa kemungkinan:
- test suite bergantung pada urutan atau resource eksternal
- runner berbagi resource dengan beban lain
- cache kadang terpakai, kadang tidak
Aksi yang mungkin:
- pisahkan berdasarkan runner untuk menguji pengaruh infrastruktur
- pisahkan berdasarkan cache hit/miss
- stabilkan dependency eksternal pada test
- cek apakah ada file glob atau langkah build yang memindai terlalu banyak file
Pola 2: Distribusi bimodal
Jika ada dua kumpulan yang jelas, misalnya satu di sekitar 3 menit dan satu lagi di sekitar 9 menit, hampir selalu ada kondisi biner yang memengaruhi runtime.
Penyebab umum:
- cache hit vs cache miss
- runner cepat vs runner lambat
- branch utama vs branch fitur
- full test vs subset test berdasarkan perubahan file
Aksi yang mungkin:
- audit strategi cache key agar tidak terlalu sering invalid
- pin job berat ke runner class yang konsisten
- pisahkan workflow berdasarkan jenis perubahan
Pola 3: Ekor panjang ke kanan
Jika sebagian besar build cepat tetapi ada ekor panjang yang sesekali melonjak, ini tanda klasik outlier. Rata-rata sering menutupi masalah ini, tetapi developer merasakannya langsung saat kebetulan terkena run lambat.
Aksi yang mungkin:
- ambil sampel commit atau run paling lambat untuk inspeksi log
- lihat apakah job gagal lalu retry otomatis
- cek timeout dependency eksternal
- cek artifact upload/download atau bottleneck jaringan
Pola 4: Runner tertentu selalu lebih lambat
Jika warna runner tertentu terkumpul pada durasi lebih tinggi, jangan buru-buru menyalahkan script CI.
Aksi yang mungkin:
- bandingkan spesifikasi runner dan utilisasi resource
- cek apakah runner memakai disk ephemeral yang lambat
- cek kontensi dari workload lain pada host yang sama
- drain atau keluarkan runner bermasalah dari pool
Pola 5: Job makin padat di durasi tinggi setelah perubahan tertentu
Ini biasanya menunjukkan regresi nyata. Jika sebelumnya job test padat di 4-5 menit lalu bergeser ke 6-7 menit setelah beberapa commit, lakukan korelasi dengan perubahan kode atau perubahan image build.
Aksi yang mungkin:
- bandingkan dependency lockfile sebelum dan sesudah
- cek apakah ada test baru yang mahal
- cek perubahan pada langkah bootstrap, install, atau compile
- buat alert regresi berbasis p95 atau median, bukan rata-rata saja
Contoh aksi nyata untuk perbaikan workflow tim
Paralelisasi job
Jika scuff chart menunjukkan satu job dominan paling lama dan relatif stabil, itu kandidat kuat untuk diparalelkan. Misalnya test suite 18 menit yang konsisten lebih tepat dipecah per shard atau per domain daripada mencoba optimasi mikro di script.
Kapan efektif:
- pekerjaan bisa dibagi tanpa banyak dependency silang
- waktu setup per shard tidak lebih besar daripada keuntungan paralelisasi
- runner tersedia cukup untuk menjalankan shard bersamaan
Trade-off:
- setup environment terduplikasi
- fan-out terlalu besar bisa menambah queue time
- debugging hasil test bisa lebih tersebar
Memperbaiki cache
Jika distribusi menunjukkan dua mode cepat/lambat, cache sering menjadi akar masalah. Evaluasi:
- apakah cache key terlalu sensitif terhadap perubahan kecil
- apakah path cache benar-benar mencakup dependency mahal
- apakah restore cache berjalan sebelum langkah yang memerlukan cache
Kesalahan umum: menganggap cache selalu membantu. Untuk artifact kecil atau dependency yang mudah diunduh, overhead kompresi dan transfer cache bisa membuat job justru lebih lambat.
Split job berdasarkan tanggung jawab
Satu job besar sering menyulitkan diagnosis. Jika build-and-test berdurasi 20 menit, Anda tidak tahu bagian mana yang boros tanpa log yang sangat rinci. Memecahnya menjadi install, build, unit-test, dan integration-test membuat distribusi masing-masing lebih mudah dianalisis.
Trade-off:
- lebih banyak job berarti overhead orkestrasi lebih tinggi
- perlu strategi artifact atau workspace antar job
Alert regresi durasi
Jangan memicu alert pada satu run lambat saja. Gunakan sinyal yang lebih tahan noise.
Pendekatan yang lebih aman:
- alert jika median job naik melewati baseline tertentu selama beberapa run berturut-turut
- alert jika p95 naik tajam dibanding jendela 7 hari sebelumnya
- alert terpisah untuk queue time dan run time
Dengan begitu, tim tidak dibanjiri false positive dari outlier tunggal.
Langkah membangun dashboard sederhana
1. Kumpulkan histori minimal 2-4 minggu
Tanpa sampel yang cukup, pola distribusi sulit dibaca. Mulailah dari job yang paling sering dijalankan: test, build, lint, dan deploy verification.
2. Tampilkan daftar job dengan median dan p95
Ini berguna sebagai pintu masuk. Pengguna dashboard bisa memilih job yang tampak mahal, lalu membuka scuff chart untuk melihat distribusinya.
3. Buat satu scuff chart per job
Hindari mencampur terlalu banyak kategori dalam satu panel. Satu panel per job biasanya paling mudah dibaca, lalu beri filter untuk branch, runner, dan status.
4. Tambahkan overlay statistik ringan
Garis vertikal untuk median dan p95 membantu interpretasi tanpa menutupi distribusi asli.
5. Sediakan drill-down ke run individual
Saat pengguna mengklik outlier, dashboard sebaiknya menampilkan:
- pipeline_id dan job_id
- commit_sha
- runner
- queue_seconds dan duration_seconds
- link ke log mentah job
Ini bagian penting. Visualisasi tanpa jalan menuju log hanya memberi sinyal, bukan alat diagnosis.
6. Pisahkan success, failed, dan canceled bila perlu
Job failed kadang selesai lebih cepat karena berhenti dini, atau justru lebih lama karena retry. Jika semua status dicampur, distribusi bisa membingungkan.
Tips debugging saat temuan mulai terlihat
- Cek ukuran sampel: jangan simpulkan terlalu cepat dari 5-10 run.
- Bandingkan apel dengan apel: branch release dan branch fitur mungkin tidak sebanding.
- Jangan abaikan queue time: optimasi script tidak akan membantu jika antrean runner penuh.
- Lihat perubahan infrastruktur: upgrade image, perubahan executor, atau rotasi runner bisa menggeser distribusi.
- Validasi timestamp: perbedaan zona waktu atau field yang salah bisa menghasilkan durasi negatif atau aneh.
- Waspadai sampling bias: hanya menyimpan run sukses bisa menutupi job yang timeout atau sering gagal lambat.
Keterbatasan scuff chart
Scuff chart sangat baik untuk membaca distribusi, tetapi bukan solusi tunggal.
- Untuk tren jangka panjang, line chart median/p95 tetap berguna.
- Untuk membandingkan proporsi status gagal/sukses, bar chart bisa lebih jelas.
- Jika volume run sangat besar, chart bisa terlalu padat dan perlu sampling atau binning ringan.
Karena itu, pendekatan yang praktis adalah menggabungkan:
- scorecard ringkas: median, p95, jumlah run, failure rate
- scuff chart: distribusi individual dan outlier
- drill-down log: diagnosis akar masalah
Penutup
Visualisasi pipeline CI/CD dengan scuff chart membantu tim melihat hal yang sering hilang dari rata-rata: kepadatan durasi, dua mode performa, outlier, dan pengaruh runner atau cache. Dengan menyimpan data run per job, memisahkan queue time dari run time, lalu mengelompokkan per job, branch, dan runner, Anda bisa mengubah keluhan “pipeline kadang lambat” menjadi keputusan teknis yang spesifik.
Mulailah dari dashboard sederhana: ambil data job run, tampilkan distribusinya, beri filter yang tepat, dan sediakan link ke log mentah. Setelah pola terlihat, tindak lanjuti dengan aksi nyata seperti paralelisasi, perbaikan cache, split job, atau alert regresi durasi berbasis median dan p95. Fokus akhirnya bukan pada chart yang indah, tetapi pada feedback loop developer yang lebih cepat dan workflow tim yang lebih stabil.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!