Operasikan dan dokumentasikan

Mengoperasikan pipeline, yakni pemantauan, runbook, dan narasi lineage.

Daftar isi

Pipeline yang sudah berjalan belum selesai sebelum orang lain dapat memeriksa kondisinya dan merespons kegagalan tanpa bertanya kepada pembuatnya. Topik ini menambahkan tiga perangkat operasional pada proyek peminjaman perpustakaan, yaitu metrik pemantauan, berkas runbook yang berisi prosedur tanggap kegagalan, dan narasi lineage yang mencatat asal-usul data. Hasil akhirnya berupa skrip laporan pemantauan yang mencetak status SLA, runbook yang siap dipakai, dan penjelasan rantai data dari sumber sampai laporan.

Memantau kesegaran, status run, dan kegagalan#

Pemantauan pipeline berdiri di atas tiga metrik yang saling melengkapi, yaitu kesegaran, status run, dan kegagalan. Kesegaran (freshness) mengukur selisih antara run terakhir yang lulus dan saat pemeriksaan, dan angka inilah yang dijanjikan oleh SLA pukul 07:00. Status run mencatat lulus atau gagalnya setiap eksekusi beserta catatan penyebabnya, sedangkan analisis kegagalan bertumpu pada daftar run gagal beserta pesannya. Ketiganya dihitung dari satu sumber yang sama, sehingga laporan tidak berisiko saling bertentangan.

Tanpa pencatatan, ketiga metrik itu hilang begitu proses berakhir, sehingga status run disimpan sebagai tabel kecil bernama run dengan kolom tanggal, status, dan catatan. Tabel semacam ini biasanya diisi orkestrator setiap kali satu task selesai, dan pada contoh proyek diisikan langsung oleh skrip. Dari tabel yang sama dihitung status SLA, yaitu TERPENUHI apabila kesegaran maksimum satu hari dan TERLEWAT apabila lebih dari itu. Metrik yang tidak ditampilkan tidak ada bedanya dengan metrik yang tidak dicatat, karena itulah laporannya dibuat sebagai teks yang mudah dibaca, ditambahkan ke log, atau dikirim sebagai peringatan.

Laporan pemantauan sebagai skrip kecil#

Skrip pantau.py menyiapkan tabel status run dengan tanggal literal, lalu mencetak laporan kesegaran dan daftar run gagal. Tanggal pemeriksaan dibuat literal demi keluaran yang deterministik, sedangkan pada pekerjaan nyata nilainya tanggal berjalan. Basis data status dibuat ulang di awal skrip supaya eksekusi ulang menghasilkan laporan yang sama persis. Skrip dijalankan dengan perintah python3 pantau.py dari dalam direktori topik.

python pantau.py
"""Laporan pemantauan sederhana untuk pipeline peminjaman perpustakaan.

Skrip menyiapkan basis data status run kecil dengan tanggal literal, lalu
mencetak laporan kesegaran dan daftar run gagal. Jalankan dari dalam
direktori topik: python3 pantau.py
"""

from pathlib import Path

import duckdb

BERKAS_DB = Path("status_proyek.duckdb")
TANGGAL_PERIKSA = "2026-10-05"  # dalam produksi: tanggal hari ini

RUN = [
    ("2026-09-26", "lulus", None),
    ("2026-09-27", "lulus", None),
    ("2026-09-28", "lulus", None),
    ("2026-09-29", "gagal", "berkas CSV sumber tidak ditemukan"),
    ("2026-09-30", "lulus", None),
    ("2026-10-01", "lulus", None),
    ("2026-10-02", "lulus", None),
    ("2026-10-03", "gagal", "validasi gagal: id anggota tidak terdaftar"),
    ("2026-10-04", "lulus", None),
    ("2026-10-05", "lulus", None),
]


def siapkan_db() -> duckdb.DuckDBPyConnection:
    """Buat ulang basis data status run agar eksekusi ulang idempoten."""
    if BERKAS_DB.exists():
        BERKAS_DB.unlink()
    con = duckdb.connect(str(BERKAS_DB))
    con.execute("CREATE TABLE run (tanggal DATE, status VARCHAR, catatan VARCHAR)")
    con.executemany("INSERT INTO run VALUES (?, ?, ?)", RUN)
    return con


def laporan(con: duckdb.DuckDBPyConnection) -> str:
    """Susun laporan kesegaran dan run gagal dari tabel run."""
    terakhir_lulus = con.execute(
        "SELECT max(tanggal) FROM run WHERE status = 'lulus'"
    ).fetchone()[0]
    kesegaran = con.execute(
        "SELECT date_diff('day', max(tanggal), CAST(? AS DATE)) "
        "FROM run WHERE status = 'lulus'",
        [TANGGAL_PERIKSA],
    ).fetchone()[0]
    gagal = con.execute(
        "SELECT tanggal, catatan FROM run WHERE status = 'gagal' ORDER BY tanggal"
    ).fetchall()
    total = con.execute("SELECT count(*) FROM run").fetchone()[0]
    status_sla = "TERPENUHI" if kesegaran <= 1 else "TERLEWAT"
    baris = [
        f"Laporan pemantauan pipeline peminjaman (pemeriksaan: {TANGGAL_PERIKSA})",
        f"run terakhir lulus : {terakhir_lulus}",
        f"kesegaran data     : {kesegaran} hari (target maksimum 1 hari)",
        f"status SLA         : {status_sla}",
        f"run gagal          : {len(gagal)} dari {total} run",
    ]
    for tanggal, catatan in gagal:
        baris.append(f"  {tanggal} : {catatan}")
    return "\n".join(baris)


def main() -> None:
    con = siapkan_db()
    print(laporan(con))
    con.close()


if __name__ == "__main__":
    main()
text Keluaran
Laporan pemantauan pipeline peminjaman (pemeriksaan: 2026-10-05)
run terakhir lulus : 2026-10-05
kesegaran data     : 0 hari (target maksimum 1 hari)
status SLA         : TERPENUHI
run gagal          : 2 dari 10 run
  2026-09-29 : berkas CSV sumber tidak ditemukan
  2026-10-03 : validasi gagal: id anggota tidak terdaftar

Laporan menunjukkan kesegaran nol hari karena run terakhir yang lulus bertepatan dengan tanggal pemeriksaan, sehingga SLA TERPENUHI. Dua run gagal tercatat lengkap dengan penyebabnya, dan keduanya diikuti run lulus pada hari berikutnya, yang berarti pipeline pulih tanpa intervensi berkepanjangan. Catatan kegagalan sengaja memakai istilah yang sama dengan pesan aserasi pada tahap pembangunan, sehingga pencarian penyebabnya hanya butuh satu langkah.

Skrip ini juga menjadi titik sambung yang murah untuk peringatan otomatis, karena keluarannya berupa teks yang dapat dikirim ke kanal tim atau diperiksa orkestrator sebagai salah satu task. Apabila status berubah menjadi TERLEWAT, catatan pada run gagal terakhir sudah cukup untuk memulai diagnosis sebelum runbook dibuka. Perbaikan biasanya berupa eksekusi ulang setelah sumber diperbaiki, dan tabel run mencatat seluruh riwayatnya.

Runbook memuat prosedur tanggap kegagalan yang ditulis agar dapat dieksekusi oleh orang lain, biasanya saat pembuat pipeline sedang tidak tersedia. Isinya meliputi informasi dasar pipeline, tabel gejala beserta tindakan pertamanya, langkah pemulihan yang berurutan, dan aturan eskalasi. Runbook yang baik mengasumsikan pembacanya paham dasar sistem, tetapi tidak menghafal keputusan yang pernah diambil. Karena itu, setiap langkahnya menyebut perintah dan berkas yang persis. Berkas runbook.md berikut menjadi runbook lengkap untuk proyek peminjaman.

markdown runbook.md
# Runbook pipeline peminjaman perpustakaan

Runbook ini memuat prosedur tanggap kegagalan untuk pipeline peminjaman yang
berjalan harian dan wajib selesai sebelum pukul 07:00. Sasarannya adalah
pemulihan layanan dalam satu jam kerja, dan prosedurnya dapat dilakukan
oleh orang yang bukan pembuat pipeline.

## Informasi dasar

- Pipeline: `pipeline_proyek.py`, dijadwalkan pukul 06:30 melalui DAG `peminjaman_perpustakaan`.
- Basis data target: `peminjaman_proyek.duckdb`.
- SLA: kesegaran maksimum 24 jam, muat selesai sebelum pukul 07:00.
- Pemantauan: `pantau.py` mencetak status SLA dan daftar run gagal.

## Gejala dan tindakan pertama

| Gejala pada status run | Penyebab yang mungkin | Tindakan pertama |
|---|---|---|
| `berkas CSV sumber tidak ditemukan` | ekspor harian belum dibuat | minta ekspor ulang, lalu jalankan ulang DAG |
| `id anggota tidak terdaftar` | data anggota tidak sinkron | muat ulang `anggota.json` terbaru, lalu jalankan ulang |
| `urutan tanggal terbalik` | kesalahan isian pada sumber | laporkan baris bermasalah ke petugas perpustakaan |

## Prosedur pemulihan

1. Buka status run terakhir dan catat pesan kegagalannya.
2. Perbaiki penyebabnya sesuai tabel gejala di atas.
3. Jalankan `python3 pipeline_proyek.py` secara manual dari direktori proyek.
4. Periksa laporan pemantauan dengan `python3 pantau.py`.
5. Pastikan status SLA kembali `TERPENUHI` sebelum insiden ditutup.

## Eskalasi

Apabila dua kali percobaan ulang tetap gagal, naikkan insiden ke pemilik
sumber data perpustakaan dan catat tanggal run serta pesan errornya pada
log insiden. Pipeline bersifat idempoten, sehingga eksekusi ulang tidak
menduplikasi data di tabel target.

Prosedur ditulis sebagai langkah bernomor yang dapat diikuti tanpa konteks tambahan, sedangkan gejala dipetakan ke tindakan pertama supaya keputusan cepat diambil. Runbook juga menyebut perintah persis yang harus diketik, bukan deskripsi samar seperti periksa log. Nomor langkah dipertahankan meski isinya berubah, karena pihak yang sedang memulihkan layanan merujuk langkah lewat nomornya. Dokumen ini disimpan bersama proyek dan diperbarui setiap kali tata letak berkas atau penjadwalan berubah.

Narasi lineage#

Lineage menjelaskan rantai yang menghubungkan setiap tabel kembali ke sumbernya, sehingga pertanyaan “angka ini berasal dari mana” selalu punya jawaban tertulis. Narasi ini juga menjadi acuan cepat saat skema sumber berubah, karena dampaknya dapat dilacak ke semua tabel di hilirnya. Narasi lineage paling mudah dipelihara bila ditulis berantai dari sumber sampai pemakaian.

Rantai lineage proyek peminjaman tersusun sebagai berikut. Berkas peminjaman.csv dan anggota.json dimuat ke tabel staging peminjaman_mentah dan anggota_mentah. Tabel staging membentuk dim_buku dan dim_anggota, dan keduanya dirangkai oleh fakta_peminjaman. Laporan harian dan analisis bulanan dibaca dari tabel fakta beserta dimensinya.

Diagram berikut menunjukkan rantai tersebut dari sumber sampai pemakaian.

Sumberpeminjaman.csvanggota.jsonStagingpeminjaman_mentahanggota_mentahModelfakta_peminjamandim_buku, dim_anggotaPemakaianlaporan hariananalisis bulanan
Lineage proyek peminjaman dari sumber sampai pemakaian

Apabila suatu hari kolom kategori berubah nama di sistem perpustakaan, lineage menunjukkan dengan cepat bahwa peminjaman_mentah, dim_buku, dan fakta_peminjaman perlu diperiksa secara berurutan. Karena itu, narasi lineage disimpan bersama proyek, bukan hanya disampaikan lisan saat demonstrasi, dan diperbarui setiap kali rantainya berubah. Bentuk narasi maupun diagram sama-sama sah, yang penting rantainya lengkap dan tersimpan.

Kesalahan umum#

Perangkat operasional yang tidak dirawat cepat kehilangan kepercayaan penggunanya. Empat kesalahan berikut paling sering muncul saat proyek mulai dioperasikan. Semuanya dapat dicegah dengan mencatat dan mendokumentasikan sejak hari pertama. Kebiasaan kecil yang konsisten lebih efektif daripada alat pemantau besar yang jarang dibuka.

  • Status run yang tidak tersimpan. Log yang hanya hidup di terminal hilang setelah sesi ditutup, sehingga kesegaran tidak dapat dihitung. Catat setiap run ke tabel permanen sejak pipeline pertama berjalan.
  • Runbook yang tidak pernah diuji. Prosedur yang baru dibaca saat kepanikan sering mengandung perintah yang sudah tidak sesuai dengan berkas yang ada. Uji langkahnya di waktu tenang, lalu perbarui dokumennya.
  • Lineage yang hanya ada di ingatan. Anggota tim baru tidak dapat menelusuri asal-usul tabel tanpa dokumen. Tulis narasi atau diagram lineage bersama proyek dan perbarui saat skema berubah.
  • Peringatan yang tidak pernah ditindaklanjuti. Laporan yang dicetak tetapi tidak pernah dibaca melatih tim untuk mengabaikannya. Sambungkan laporan ke saluran yang benar-benar dipantau dan jelaskan tindakan pertamanya.

Ringkasan#

  • Pemantauan berdiri di atas tiga metrik, yaitu kesegaran, status run, dan kegagalan, yang dihitung dari tabel run kecil.
  • Skrip pantau.py mencetak status SLA dan daftar run gagal dengan keluaran yang deterministik.
  • Runbook memuat informasi dasar, gejala beserta tindakan pertamanya, prosedur pemulihan bernomor, dan eskalasi.
  • Narasi lineage menghubungkan berkas sumber, tabel staging, tabel fakta dan dimensi, sampai laporan yang dipakai.

Referensi#