07 Uji, gagal, dan perbaiki
Catatan instruktur untuk modul 07 — waktu, alur pembicaraan, kegagalan umum, dan langkah reset.
Pendamping fasilitator untuk pelajaran pembelajar 07 Uji, gagal, dan perbaiki.
Waktu
Sekitar 20 menit. Ini lab insiden; lindungi cukup ruang agar diagnosisnya mendarat sebelum modul 08 dan penutup. Lab menjalankan fault 01 (diagnosis 5-15 menit). Fault 02 (5-10 menit) dan 03 (10-20 menit, dan hanya dengan dataset penuh sekitar 30 juta baris) tetap tersedia sebagai insiden tambahan opsional untuk ruangan yang cepat. Tetapkan hard-stop saat gladi bersih agar penutup tidak terhimpit.
Alur pembicaraan
- Ini bagian hasilnya: gunakan semua yang dibangun sejauh ini untuk menjalankan insiden nyata.
- Deskripsikan gejalanya, bukan penyebabnya, dan biarkan agen bertemu jawaban dari telemetri.
- Pertimbangkan menampilkan diagnosis beberapa peserta bersebelahan di proyektor.
- Lab menjalankan fault 01. Jika waktu memungkinkan satu ronde tambahan, tambahkan fault 02 (dan fault 03 hanya ketika dataset penuh sudah di-seed sebelumnya); gunakan reset stash-and-switch bersama di bawah di antara fault.
Kunci jawaban
Jangan bagikan bagian ini kepada pembelajar; bagian ini hidup hanya di playbook dan tidak pernah
dicommit ke repo aplikasi. Setiap fault adalah satu perubahan kecil di branch-nya sendiri dari
build-workshop-v1;
perbaikannya adalah membalikkannya. Jalankan satu fault sekali waktu. Insiden lab ini adalah fault 01 (5-15 menit,
curveball — backend tidak bersalah). Tambahan opsional untuk ruangan yang cepat: fault 02 (5-10 menit,
pemanasan, trace menjelaskan semuanya) dan fault 03 hanya ketika dataset penuh tersedia
(10-20 menit, penalaran ClickHouse yang lebih dalam).
Reset bersama untuk setiap fault (stash mempertahankan hasil edit peserta dan menghindari pergantian branch yang terhalang):
git stash push --include-untracked -m "module-07-fix"
git switch build-workshop-v1
docker compose --env-file .env.workshop \
-f docker-compose.workshop.yml -f docker-compose.otel.yml up -d --buildFault 02 — zone stats 500 (fault/02-zone-stats-500)
Pesan commit yang dilihat peserta: "backend: align zone stats column names with API params"
(hanya menyentuh zone_stats_sql di backend/app/query_builders.py). Ia mengelompokkan berdasarkan
pickup_zone_id, kolom yang tidak ada di taxi_trips, alih-alih
pickup_location_id.
- Gejala: choropleth pada peta kosong (poligon ter-render, tapi setiap zona berada di
bucket paling terang) dan caption "Query Nms" hilang; ledakan 500 pada
GET /api/metrics/zone_stats(React Query mencoba ulang tiga kali). Semua kartu lainnya normal. - Di mana sinyalnya: span
clickhouse.querydi ClickStack denganerror=True,error.category="query_failed", dandb.statementyang memuatpickup_zone_id AS zone_id; exception yang terekam adalah ClickHouse Code 47UNKNOWN_IDENTIFIER. Log ERROR yang cocok: "ClickHouse query failed (category=query_failed, elapsed_ms=...): ... | sql=...". - Jalur diagnosis: temukan span 500 -> baca
db.statement->UNKNOWN_IDENTIFIERpadapickup_zone_id->DESCRIBE taxi_trips(atau bandingkan query builder sekerabat) -> kolom yang sebenarnya adalahpickup_location_id. - Perbaikan: ubah
pickup_zone_idkembali menjadipickup_location_iddizone_stats_sql(ataugit revertcommit fault-nya); build ulang backend. - Reset: reset bersama di atas.
Fault 03 — dashboard lambat (fault/03-slow-dashboard)
Pesan commit: "backend: window the trend series by bucket in HAVING" (menyentuh
timeseries_sql). Ia memindahkan predikat jendela waktu dari WHERE ke HAVING pada
alias bucket, sehingga WHERE menjadi 1. ClickHouse tidak lagi bisa memangkas berdasarkan
primary key (car_type, pickup_datetime) dan memindai penuh taxi_trips dengan dua
state quantileTDigest, melewati max_execution_time 5s.
- Gejala: hanya kartu tren "What's happening now?" yang gagal — ia berputar, lalu menampilkan "504 Query timed out...". Setiap kartu sekerabat tetap cepat.
- Di mana sinyalnya: span
clickhouse.querydenganerror.category="timeout",db.elapsed_mssekitar 5000, dandb.statementmenampilkanWHERE 1 ... GROUP BY ts HAVING ts >= ...; exception-nya adalah Code 159TIMEOUT_EXCEEDED. Kontrasnya dengan span 200 yang cepat pada endpoint lain adalah petunjuknya. - Jalur diagnosis: satu kartu lambat di antara kerabat yang cepat -> buka span timeout -> baca
SQL-nya -> filter waktu ada di
HAVINGdanWHEREtidak punya rentangpickup_datetime-> sebuah anti-pola pemangkasan primary key / predicate pushdown (kerabatnya menaruh jendela waktu diWHERE). - Perbaikan: kembalikan jendela waktu ke
WHERE(balikkan commit fault-nya); build ulang backend. - Reset: reset bersama di atas.
- Catatan untuk instruktur: tingkat keparahan berskala dengan volume data dan ukuran service. Pada
dataset penuh yang di-seed (~30 juta baris) di service tier workshop (yang mungkin baru bangun dari idle),
timeout 5s menyala secara andal; pada seed sampel kecil ia hanya lebih lambat, bukan 504 keras.
send_receive_timeoutdi klien danmax_execution_timedi server keduanya 5s, jadi perlombaan socket-timeout kadang bisa muncul sebagai 500 alih-alih 504 yang bersih — itu sifat dari setelan baseline, bukan dari fault-nya.
Fault 01 — peta tidak memuat (fault/01-map-not-loading)
Pesan commit: "frontend: serve map geojson from /static asset path" (menyentuh
path fetch di frontend/src/ui/ZoneMap.tsx). Ia mem-fetch /static/taxi_zones.geojson, yang
tidak ada. Nuansa kunci: fallback SPA di nginx (try_files ... /index.html) mengembalikan HTTP 200
dengan dokumen HTML alih-alih 404, jadi r.ok lolos dan r.json() melempar
SyntaxError seperti Unexpected token '<'.
- Gejala: kartu peta mati — base tile ter-render tapi tidak ada poligon NYC atau choropleth, dan muncul error inline berwarna merah. Sisanya normal.
- Di mana sinyalnya: tidak ada apa pun di ClickStack backend — aset itu tidak pernah mencapai
FastAPI. Console browser menampilkan error parse JSON yang menyebut
/static/taxi_zones.geojson; tab Network menampilkan request itu mengembalikantext/htmldengan status 200; log akses nginx menampilkan fallback-nya. - Jalur diagnosis: trace backend bersih -> pindah ke console / tab Network browser
-> sebuah request
.geojsonmengembalikan 200text/html-> kenali jebakan fallback SPA -> file-nya sebenarnya berada di web root,/taxi_zones.geojson. - Perbaikan: balikkan path fetch (dua baris) atau
git revertcommit fault-nya; build ulang frontend. - Reset: reset bersama di atas.
- Poin ajar: tidak setiap kegagalan muncul di trace backend, dan 404 bisa menyamar sebagai 200 di balik fallback SPA — jadi baca body respons dan content-type yang sebenarnya, bukan hanya kode statusnya.
- Catatan (SDK browser): dengan SDK browser HyperDX aktif (overlay modul 05),
frontend sekarang memunculkannya di ClickStack sendiri — kegagalan parse
ZoneMapterekam sebagai spanconsole.errordi bawahServiceName=nyc-taxi-frontend, berpasangan dengan span resource untuk 200text/htmlitu. Jadi agen bisa melokalisasinya dari telemetri tanpa meninggalkan ClickStack; console / tab Network browser adalah cadangan, bukan satu-satunya jalan.
Contoh respons agen (fault 01, via ClickStack MCP):

Diagnosis yang diharapkan: agen mengaitkan kegagalan itu dengan request geojson yang mengembalikan 200 text/html (fallback SPA), error JSON.parse yang timbul dan terekam di bawah nyc-taxi-frontend, lalu merekomendasikan mengirim aset itu ke /static/ atau mengamankan proses parse .json().
Kegagalan umum
- Baseline telemetri tidak cukup bagi agen untuk melokalisasi; modul 05 harus sudah berjalan lebih awal.
- Peserta melompat ke perbaikan sebelum memastikan akar masalah dari bukti.
- Gejala fault belum terlihat karena stack baru saja dijalankan — atau, untuk fault 03, karena data historis yang dimuat terlalu sedikit. Terukur pada dry run: pada seed satu bulan default (~3,17 juta baris) fault WHERE-vs-HAVING tidak teramati — pemindaian penuh berjalan dalam ~300-560ms, tidak bisa dibedakan dari baseline. Seed beberapa bulan sebelum mendemokan fault 03, atau tetap pakai fault 01 (yang langsung tereproduksi) dan perlakukan fault 03 sebagai ilustrasi pada skala besar.
- Fault 01 sama sekali tidak menghasilkan trace backend, dan request yang salah mengembalikan 200
text/htmlvia fallback SPA alih-alih 404; peserta bisa mencari di trace tanpa akhir. Dorong mereka ke console / tab Network browser, tempat error parse JSON dan responstext/htmlterlihat. - Lupa
--buildsetelah checkout branch fault, sehingga image lama tetap berjalan.
Langkah reset
- Reset stash-and-switch bersama memulihkan aplikasi secara lengkap tanpa membuang upaya perbaikan seorang peserta.
- Suntikkan ulang sebuah fault dengan checkout salah satu dari
fault/01-map-not-loading/fault/02-zone-stats-500/fault/03-slow-dashboarddan build ulang dengan file compose workshop plus otel. - Gejala, sinyal, dan perbaikan per fault ada di bagian Kunci jawaban di atas. Simpan kunci jawaban hanya di playbook ini; kunci itu tidak pernah dicommit ke repo aplikasi.