# ๐Ÿšจ EVLOG โ€” Event & Error Log **Project:** Web Antrean โ€” Sistem Manajemen Antrean Rawat Jalan RSSA **Author:** Akbar **Stack:** JavaScript ยท Vue 3 ยท TypeScript ยท Nuxt 3 ยท Vuetify 3 ยท Pinia --- ## ๐Ÿง  AI Prompt โ€” Cara Menggunakan Dokumen Ini > Salin prompt berikut ke Claude untuk menganalisis dan mendokumentasikan error: ``` Kamu adalah senior engineer Nuxt 3 + TypeScript. Aku menemukan error berikut: Error message: [paste error] Stack trace: [paste stack trace] Context: [dimana terjadi, langkah reproduksi] Tech: Nuxt 3, Vue 3, TypeScript, Vuetify 3, Pinia, WebSocket, Keycloak Bantu aku: 1. Analisis root cause error ini 2. Berikan solusi step-by-step 3. Sarankan cara mencegah error serupa 4. Format hasilnya untuk EVLOG dalam Markdown ``` --- ## Severity Legend | Level | Icon | Deskripsi | SLA | |-------|------|-----------|-----| | Critical | ๐Ÿ”ด | App down / data loss / security | < 4 jam | | High | ๐ŸŸ  | Fitur utama break | < 1 hari | | Medium | ๐ŸŸก | Fitur minor terganggu | < 3 hari | | Low | ๐ŸŸข | UI/kosmetik | Backlog | --- ## Format Entry ```markdown ### [EV-XXX] โ€” [Judul Singkat Error/Event] | Field | Value | |-------|-------| | **ID** | EV-XXX | | **Tanggal** | YYYY-MM-DD | | **Severity** | ๐Ÿ”ด Critical / ๐ŸŸ  High / ๐ŸŸก Medium / ๐ŸŸข Low | | **Environment** | Development / Staging / Production | | **Status** | ๐Ÿ” Investigating / ๐Ÿ”ง In Fix / โœ… Resolved / โญ Wontfix | | **Reporter** | Akbar | **Error Message:** > [paste error message] **Langkah Reproduksi:** 1. ... **Root Cause:** > ... **Solusi / Fix:** > ... **Prevention:** > ... **Related:** [commit / file] ``` --- ## Event Log --- ### [EV-012] โ€” Info Klinik Ruang Tidak Muncul di Layar Display | Field | Value | |-------|-------| | **ID** | EV-012 | | **Tanggal** | 2026-05-21 | | **Severity** | ๐ŸŸ  High | | **Environment** | Development | | **Status** | โœ… Resolved | | **Reporter** | Akbar | **Error Message:** > Layar informasi klinik ruang menampilkan data kosong โ€” tidak ada info klinik ruang yang muncul. **Langkah Reproduksi:** 1. Buka halaman display screen klinik ruang 2. Data klinik ruang seharusnya muncul 3. Layar kosong โ€” tidak ada informasi tampil **Root Cause:** > Data binding untuk info klinik ruang tidak ter-update setelah fetch dari API. Kemungkinan reactive state tidak di-watch dengan benar sehingga UI tidak re-render saat data berubah. **Solusi / Fix:** > Perbaikan data binding dan reactive state untuk informasi klinik ruang pada layar display. **Related:** Commit `ec9dac0` โ€” "push perbaikan layar informasi info klinik ruang tidak muncul" --- ### [EV-011] โ€” Data Antrean Tidak Sinkron Antar Display Screen | Field | Value | |-------|-------| | **ID** | EV-011 | | **Tanggal** | 2026-05-22 | | **Severity** | ๐Ÿ”ด Critical | | **Environment** | Development | | **Status** | โœ… Resolved | | **Reporter** | Akbar | **Error Message:** > Display screen di lokasi berbeda menampilkan nomor panggil yang berbeda. Admin memanggil pasien tapi layar display tidak update, atau update terlambat > 10 detik. **Langkah Reproduksi:** 1. Buka admin loket di PC A 2. Buka display screen di TV/monitor B 3. Panggil pasien berikutnya di PC A 4. Display di monitor B tidak menampilkan nomor panggil terbaru **Root Cause:** > WebSocket client ID menggunakan random ID, sehingga server tidak bisa menargetkan pesan ke device tertentu secara reliable. Saat koneksi putus lalu reconnect, client ID berubah dan device kehilangan subscription. **Solusi / Fix:** ```typescript // โŒ Before โ€” random client ID const clientId = `client_${Math.random().toString(36).substr(2, 9)}` // โœ… After โ€” deterministic client ID berdasarkan page + device const clientId = `${pageType}_${loketId || 'global'}_${deviceFingerprint}` ``` Ditambahkan juga polling fallback setiap 30 detik sebagai safety net. **Prevention:** > Selalu gunakan deterministic identifier untuk WebSocket client. Implementasi polling fallback untuk semua halaman yang bergantung pada real-time data. **Related:** Conversation `6fe234cf` โ€” "Stabilizing WebSocket Queue Synchronization" --- ### [EV-010] โ€” Cross-Loket Interference pada Patient Processing | Field | Value | |-------|-------| | **ID** | EV-010 | | **Tanggal** | 2026-05-21 | | **Severity** | ๐Ÿ”ด Critical | | **Environment** | Development | | **Status** | โœ… Resolved | | **Reporter** | Akbar | **Error Message:** > Loket A memproses pasien yang seharusnya milik Loket B. `currentProcessingPatient` menampilkan pasien dari loket yang salah. **Langkah Reproduksi:** 1. Login sebagai admin loket A di browser tab 1 2. Login sebagai admin loket B di browser tab 2 3. Panggil pasien di loket A 4. Loket B menampilkan pasien yang sama sebagai "sedang diproses" **Root Cause:** > `currentProcessingPatient` menggunakan key persisted state yang sama untuk semua loket. Karena `pinia-plugin-persistedstate` menyimpan ke `localStorage` dengan key yang sama, operasi di satu loket menimpa state loket lain. **Solusi / Fix:** ```javascript // โŒ Before โ€” shared key persist: { key: 'currentProcessingPatient' } // โœ… After โ€” unique key per loket persist: { key: `currentPatient_loket_${loketId}` } ``` Ditambahkan juga strict filter di `processNextQueue` dan `callNext` berdasarkan `loketId`, serta guard check di WebSocket event handler. **Prevention:** > Setiap state yang bersifat per-instance (per loket, per klinik) HARUS menggunakan unique key. Jangan pernah share persisted state key antar instance. **Related:** Conversation `7a37e693` โ€” "Isolating Loket Queue Operations" --- ### [EV-009] โ€” Bug Tampilan Loket | Field | Value | |-------|-------| | **ID** | EV-009 | | **Tanggal** | 2026-05-20 | | **Severity** | ๐ŸŸก Medium | | **Environment** | Development | | **Status** | โœ… Resolved | | **Reporter** | Akbar | **Error Message:** > Layout admin loket tidak render dengan benar โ€” elemen UI tumpang tindih atau alignment salah. **Langkah Reproduksi:** 1. Login sebagai admin loket 2. Buka halaman `/admin-loket` 3. Layout tampilan loket tidak sesuai desain **Root Cause:** > CSS layout issue dan data binding yang tidak sinkron dengan state loket. **Solusi / Fix:** > Perbaikan layout dan data binding di halaman admin loket. **Related:** Commit `f622052` โ€” "perbaikan bug tampilan loket" --- ### [EV-008] โ€” Memory Leak & Request Spam dari doctorStore | Field | Value | |-------|-------| | **ID** | EV-008 | | **Tanggal** | 2026-05-18 | | **Severity** | ๐ŸŸ  High | | **Environment** | Development | | **Status** | โœ… Resolved | | **Reporter** | Akbar | **Error Message:** ``` Internal Server Error (500) โ€” /klinik-api/doctors/... ``` Error terjadi berulang-ulang tanpa henti, menyebabkan request spam ke backend. **Langkah Reproduksi:** 1. Buka halaman yang memuat `doctorStore.js` 2. Backend endpoint `/doctors` return 500 3. Store terus retry tanpa batas 4. Network tab penuh dengan request gagal, memory usage naik terus **Root Cause:** > `doctorStore.js` tidak memiliki mekanisme backoff atau blacklist untuk endpoint yang gagal. Setiap kali fetch gagal, store langsung retry tanpa delay, menyebabkan infinite loop request ke server. **Solusi / Fix:** ```javascript // โœ… Implementasi blacklist endpoint gagal const blacklistedEndpoints = new Set() async function fetchDoctors(endpoint) { if (blacklistedEndpoints.has(endpoint)) { return [] // skip, sudah di-blacklist } try { return await $fetch(endpoint) } catch (error) { if (error.status === 500) { blacklistedEndpoints.add(endpoint) console.warn(`Endpoint blacklisted: ${endpoint}`) } return [] } } ``` **Prevention:** > Semua API fetch HARUS memiliki: (1) error handling, (2) retry limit atau backoff, (3) blacklist mechanism untuk persistent failures. Jangan pernah retry tanpa batas. **Related:** Conversation `c7502197` โ€” "Optimizing Web Antrean Memory Usage", commit `cb3310b` --- ### [EV-007] โ€” Console.log Verbose Memperlambat Performa | Field | Value | |-------|-------| | **ID** | EV-007 | | **Tanggal** | 2026-05-18 | | **Severity** | ๐ŸŸข Low | | **Environment** | Development | | **Status** | โœ… Resolved | | **Reporter** | Akbar | **Error Message:** > Tidak ada error message, tapi browser DevTools penuh dengan log output, menyebabkan performa menurun terutama di device yang lebih lambat. **Langkah Reproduksi:** 1. Buka halaman yang menggunakan WebSocket atau QR scanner 2. Buka browser DevTools โ†’ Console 3. Log membanjir setiap detik dari `useWebSocket.ts` dan QR scanner di `checkIn.vue` **Root Cause:** > `console.log` debugging statements di high-frequency code paths (WebSocket message handler yang dipanggil per-detik, QR scanner frame processing) tidak dihapus setelah debugging selesai. **Solusi / Fix:** > Cleanup semua `console.log` di: > - `composables/useWebSocket.ts` โ€” WebSocket message handler > - `pages/CheckInPasien/checkIn.vue` โ€” QR scanner frame processing > Hanya sisakan `console.warn` dan `console.error` untuk kondisi yang benar-benar perlu. **Prevention:** > Gunakan convention: `console.log` hanya untuk debugging sementara, `console.warn`/`console.error` untuk production logging. Tambahkan lint rule atau pre-commit hook untuk mendeteksi `console.log` yang tersisa. **Related:** Conversation `c7502197` โ€” "Optimizing Web Antrean Memory Usage" --- ### [EV-006] โ€” Header Origin/Referer Tidak Konsisten di Proxy Routes | Field | Value | |-------|-------| | **ID** | EV-006 | | **Tanggal** | 2026-05-22 | | **Severity** | ๐ŸŸก Medium | | **Environment** | Development | | **Status** | โœ… Resolved | | **Reporter** | Akbar | **Error Message:** > CORS error atau origin validation failure saat memanggil backend API melalui proxy routes. Beberapa request berhasil, beberapa gagal secara intermittent. **Langkah Reproduksi:** 1. Panggil API via proxy route `stats-api`, `visit-api`, atau `klinik-api` 2. Beberapa request gagal dengan CORS error 3. Request yang sama kadang berhasil, kadang gagal **Root Cause:** > Setiap proxy route handler (`server/routes/stats-api/`, `visit-api/`, `klinik-api/`) menggunakan header origin dan referer yang berbeda-beda. Backend melakukan validasi origin, dan header yang tidak konsisten menyebabkan intermittent failure. **Solusi / Fix:** > Standardisasi semua proxy route handler agar menggunakan origin dan referer yang sama: ```typescript // โœ… Semua proxy routes menggunakan header yang sama headers: { 'Origin': 'http://10.10.150.175:3000', 'Referer': 'http://10.10.150.175:3000', } ``` **Prevention:** > Buat shared utility function untuk proxy header configuration agar semua route handler menggunakan config yang sama. Hindari copy-paste header config per file. **Related:** Conversation `97867794` โ€” "Standardizing Header Configurations Across APIs" --- ### [EV-005] โ€” Duplikasi Tiket di Admin Klinik Loket | Field | Value | |-------|-------| | **ID** | EV-005 | | **Tanggal** | 2026-02-11 | | **Severity** | ๐ŸŸ  High | | **Environment** | Development | | **Status** | โœ… Resolved | | **Reporter** | Akbar | **Error Message:** > Daftar pasien di admin klinik menampilkan tiket yang sama dua kali. Setelah check-in, tiket pasien menghilang dari daftar. **Langkah Reproduksi:** 1. Pasien ambil antrean di anjungan 2. Buka admin klinik loket 3. Pasien yang sama muncul 2x di daftar 4. Setelah check-in, tiket menghilang dari daftar **Root Cause:** > WebSocket event handler menambahkan pasien ke `allPatients` tanpa deduplication check. Saat event masuk bersamaan dari multiple sources (initial load + WebSocket), data terduplikasi. Saat check-in, state update menghapus entry yang salah. **Solusi / Fix:** ```javascript // โœ… Deduplication check sebelum add ke allPatients function addPatient(patient) { const exists = allPatients.value.find(p => p.nomorAntrean === patient.nomorAntrean) if (!exists) { allPatients.value.push(patient) } else { // Update existing instead of duplicate Object.assign(exists, patient) } } ``` **Prevention:** > Semua operasi mutasi pada `allPatients` harus melalui function yang melakukan deduplication check. Jangan pernah langsung `push` tanpa cek duplikat. **Related:** Commit `c02905e` โ€” "fix duplication and ticket disappear in adminklinik loket" --- ### [EV-004] โ€” WebSocket Check-in Tidak Trigger UI Update | Field | Value | |-------|-------| | **ID** | EV-004 | | **Tanggal** | 2026-02-10 | | **Severity** | ๐ŸŸ  High | | **Environment** | Development | | **Status** | โœ… Resolved | | **Reporter** | Akbar | **Error Message:** > Pasien check-in via QR berhasil (API return success), tapi status di admin loket tidak berubah. UI tetap menampilkan pasien sebagai "belum hadir". **Langkah Reproduksi:** 1. Pasien scan QR di halaman check-in 2. API return success โ€” pasien tercatat hadir 3. Buka admin loket โ€” status pasien masih "belum hadir" 4. Perlu manual refresh untuk melihat update **Root Cause:** > WebSocket event listener untuk check-in event tidak ter-bind dengan benar. Event `checkin_success` diterima oleh WebSocket, tapi handler tidak melakukan state update ke Pinia store. **Solusi / Fix:** > Fix event listener binding di `useWebSocket.ts` โ€” pastikan `checkin_success` event memicu update pada `queueStore.allPatients`. **Prevention:** > Setiap WebSocket event type harus memiliki dedicated handler yang ter-test. Buat mapping event โ†’ handler yang eksplisit. **Related:** Commits `e686dda`, `b6dc252` โ€” "fix socket checkin", "update bug ws checkin loket" --- ### [EV-003] โ€” HTTPS Implementation Gagal di Check-in | Field | Value | |-------|-------| | **ID** | EV-003 | | **Tanggal** | 2026-02-02 | | **Severity** | ๐ŸŸก Medium | | **Environment** | Development | | **Status** | โœ… Resolved | | **Reporter** | Akbar | **Error Message:** > Check-in via QR tidak berfungsi saat HTTPS aktif. Kamera QR scanner tidak bisa diakses. **Langkah Reproduksi:** 1. Aktifkan HTTPS di dev server 2. Buka halaman check-in 3. QR scanner gagal โ€” kamera tidak muncul **Root Cause:** > Browser memerlukan HTTPS untuk akses kamera (MediaDevices API), tapi mixed content policy memblokir request ke backend HTTP. Konfigurasi HTTPS tidak lengkap โ€” SSL certificate self-signed tidak dipercaya browser. **Solusi / Fix:** > Fix implementasi HTTPS menggunakan `@vitejs/plugin-basic-ssl` di `nuxt.config.ts`. Konfigurasi dev server untuk HTTPS dengan self-signed cert yang di-trust browser. **Prevention:** > Saat menggunakan Web API yang memerlukan secure context (kamera, geolocation), pastikan HTTPS sudah configured end-to-end termasuk backend. **Related:** Commit `c899a71` โ€” "fix https implementation and checkin" --- ### [EV-002] โ€” Loop & Duplikasi Data di Fetch API | Field | Value | |-------|-------| | **ID** | EV-002 | | **Tanggal** | 2026-01-29 | | **Severity** | ๐ŸŸ  High | | **Environment** | Development | | **Status** | โœ… Resolved | | **Reporter** | Akbar | **Error Message:** > Data pasien terduplikasi di daftar antrean. Fetch API dipanggil berulang-ulang dalam loop. **Langkah Reproduksi:** 1. Buka halaman yang memuat data antrean 2. Data pasien muncul berkali-kali 3. Network tab menunjukkan API dipanggil berulang-ulang **Root Cause:** > `watch` atau `computed` yang bergantung pada reactive state memicu re-fetch setiap kali state berubah, dan hasil fetch mengubah state lagi โ€” menyebabkan infinite loop. **Solusi / Fix:** > Fix logic watch/computed agar tidak circular. Tambahkan guard condition untuk mencegah re-fetch saat data sudah di-load. **Prevention:** > Hindari circular dependency antara watcher dan state mutation. Gunakan flag `isLoading` untuk mencegah concurrent fetch. **Related:** Commit `0bd5311` โ€” "fix loop dan duplicate data" --- ### [EV-001] โ€” Session & Tampilan Screen Tidak Sinkron | Field | Value | |-------|-------| | **ID** | EV-001 | | **Tanggal** | 2026-01-30 | | **Severity** | ๐ŸŸก Medium | | **Environment** | Development | | **Status** | โœ… Resolved | | **Reporter** | Akbar | **Error Message:** > Display screen menampilkan data lama setelah session expire. Setelah re-login, data tidak refresh otomatis. **Langkah Reproduksi:** 1. Login dan buka display screen 2. Tunggu session expire (1 jam) 3. Re-login 4. Display masih menampilkan data dari session sebelumnya **Root Cause:** > Pinia persisted state menyimpan data lama di `localStorage`. Saat session expire dan user re-login, store tidak di-reset โ€” data lama masih tampil. **Solusi / Fix:** > Reset persisted state saat login baru. Pastikan display screen melakukan fresh fetch setelah session recovery. **Prevention:** > Implementasi session lifecycle hooks: on session expire โ†’ clear stale state, on re-login โ†’ fresh fetch semua data. **Related:** Commit `8dd94ed` โ€” "update fix session dan tampilan screen" --- ## ๐Ÿ“Š Error Statistics | Bulan | Critical | High | Medium | Low | Total | |-------|---------|------|--------|-----|-------| | Jan 2026 | 0 | 1 | 1 | 0 | 2 | | Feb 2026 | 0 | 3 | 1 | 0 | 4 | | Mar 2026 | 0 | 0 | 0 | 0 | 0 | | Apr 2026 | 0 | 0 | 0 | 0 | 0 | | Mei 2026 | 2 | 2 | 1 | 1 | 6 | | **Total** | **2** | **6** | **3** | **1** | **12** | --- ## ๐Ÿ” Recurring Issues > Daftar error yang muncul lebih dari sekali โ€” kandidat untuk refactor/improvement permanen. | Error Pattern | Frekuensi | Action | |---------------|-----------|--------| | WebSocket disconnect โ†’ data tidak sinkron | 3x (EV-004, EV-011, EV-012) | โœ… Implemented: polling fallback 30 detik + auto-reconnect + deterministic client ID | | Duplikasi data pasien di daftar | 2x (EV-002, EV-005) | โœ… Implemented: deduplication check di `allPatients` mutation | | Session/state stale setelah reconnect | 2x (EV-001, EV-011) | โœ… Implemented: fresh fetch on reconnect + state reset on re-login | | Request spam ke endpoint yang gagal | 1x (EV-008) | โœ… Implemented: blacklist + retry limit. **Monitor untuk recurring** | | Cross-instance state conflict (loket) | 1x (EV-010) | โœ… Implemented: unique persisted state key per instance. **Audit untuk klinik/penunjang** |