Dua minggu setelah pipeline berjalan, pertanyaan yang muncul bukan “apakah malam ini sukses” melainkan “berapa baris yang biasanya diproses, dan kapan angkanya mulai menyimpang”. Pertanyaan seperti itu hanya bisa dijawab bila setiap eksekusi meninggalkan jejak yang terstruktur. Kita memakai dua buku yang berbeda: data/state/state.json mencatat keadaan per tanggal (watermark), sedangkan data/state/runs/ menyimpan satu manifest JSON per eksekusi. Buku pertama menjawab “tanggal apa yang sudah selesai”; buku kedua menjawab “apa yang terjadi pada setiap percobaan”.
Checksum sebagai Sidik Jari #
Fungsi sha256_hex menggabungkan baris-baris terurut menjadi satu nilai:
def sha256_hex(baris: Iterable[str]) -> str:
"""SHA-256 atas baris teks; tiap baris diakhiri newline."""
h = hashlib.sha256()
for b in baris:
h.update((b + "\n").encode("utf-8"))
return h.hexdigest()Baris fact dibentuk oleh load._baris_fact dengan ORDER BY order_id, dan angka uang diformat dua desimal lewat printf('%.2f', ...). Dengan demikian checksum mencerminkan isi baris, terlepas dari kapan baris itu dimuat. Checksum inilah yang membedakan “jumlahnya kebetulan sama” dari “isinya benar-benar identik” pada bukti Bagian 5.
Manifest Eksekusi #
Setiap run_for_date diakhiri satu manifest. Strukturnya adalah dataclass RunManifest dengan kolom: run_id, status, waktu mulai dan selesai, durasi milidetik, jumlah baris per tahap, checksum, berkas gold, dan galat bila gagal. Nama berkasnya mengikuti run_id, misalnya run-2026-11-02-075011.json. Tabrakan nama dalam satu detik yang sama diselesaikan dengan sufiks -2, -3, dan seterusnya.
Isi ketiga manifest untuk tanggal 2026-11-02 telah kita lihat pada Bagian 5; berikut manifest kegagalannya:
Output yang Dihasilkan:
== manifest kegagalan 2026-11-05 ==
run-2026-11-05-075018: status=failed error={'jenis': 'ExtractError', 'pesan': 'partisi tidak ditemukan: data/raw/pesanan_2026-11-05.csv', 'exit_code': 3, 'alert': 'disabled'}
run-2026-11-05-075019: status=failed error={'jenis': 'ExtractError', 'pesan': 'partisi tidak ditemukan: data/raw/pesanan_2026-11-05.csv', 'exit_code': 3, 'alert': 'stub'}Manifest mencatat juga apakah alert aktif (disabled atau stub), sehingga riwayat eksekusi sekaligus menjadi riwayat konfigurasi. Menjalankan laporan itu semudah:
python3 -m src.monitoringOutput yang Dihasilkan:
run_id tanggal status baris durasi(ms) checksum fact
-------------------------------------------------------------------------------
run-2026-11-02-075011 2026-11-02 success 8 43 597d2f68aa8be0d…
run-2026-11-02-075015 2026-11-02 skipped 8 0 597d2f68aa8be0d…
run-2026-11-02-075017 2026-11-02 success 8 46 597d2f68aa8be0d…
run-2026-11-03-075012 2026-11-03 success 7 51 10d48d93f879d9a…
run-2026-11-04-075014 2026-11-04 success 8 49 8bd653745eeca46…
run-2026-11-05-075018 2026-11-05 failed - 0 -
run-2026-11-05-075019 2026-11-05 failed - 1 -
-------------------------------------------------------------------------------
total eksekusi: 7Membaca Laporan Status #
Tabel di atas adalah riwayat operasional proyek ini, dan tiga hal langsung terlihat darinya:
- Checksum kolom untuk 2026-11-02 sama pada tiga baris. Sukses pertama, lewati, dan sukses ulang menghasilkan isi warehouse yang identik; inilah bukti idempotensi yang dibahas Bagian 5, kali ini terbaca dari sisi monitoring.
- Baris gagal menampilkan tanda
-pada kolom baris dan checksum, karena eksekusi gagal tidak menghasilkan beban. Durasi0-1 msmenunjukkan kegagalan terjadi di tahap paling awal. - Durasi sehat berkisar 43-51 ms untuk beban 7-8 baris. Bila suatu hari durasi melonjak dua tingkat besaran, itu pertanda volume sumber berubah atau ada yang perlu diperiksa.
Dua Buku yang Berbeda Peran #
| Aspek | state.json (watermark) | runs/*.json (manifest) |
|---|---|---|
| Kuncinya | tanggal partisi | satu eksekusi (bisa lebih dari satu per tanggal) |
| Menjawab | tanggal apa yang sudah selesai | apa yang terjadi pada tiap percobaan |
| Dibaca oleh | due_runs pada scheduler | build_status_report dan penyelidikan kegagalan |
| Umur | diperbarui, entri lama tetap | menempel terus sebagai riwayat |
Pemisahan ini sejalan dengan chapter Pipeline Logging: log per baris berguna untuk menelusuri, sedangkan ringkasan per eksekusi berguna untuk dipantau. Pola Metrics dan Alerting menambahkan pengiriman metrik ke sistem eksternal; pada proyek ini baris manifest sudah berbentuk yang tepat untuk dikirim bila suatu saat diperlukan. Selanjutnya kita memasang pemeriksaan terakhir yang membaca kembali seluruh hasil: validasi dan rekonsiliasi.