16.2 · Debugging cross-service issues
แพลตฟอร์ม VTRC เป็น "distributed monolith" — ~30 repo ที่แยก deploy กันแล้ว แต่ผูกกันแน่นด้วย shared database, shared secret, และ hardcoded URL (Canonical Truths) การ debug ปัญหาที่ข้าม repo จึงยากกว่าระบบ microservice ที่ออกแบบมาให้ decouple จริง เพราะไม่มีเครื่องมือ observability กลางที่ช่วยเชื่อมจุดให้
16.2.1 · ไม่มี correlation ID ข้าม service — ต้อง trace ด้วยเวลาและ business key แทน
ยืนยันจาก vtrc-api/09-cross-cutting §สิ่งที่มี/ไม่มี — vtrc-api มี request log + response log แต่ไม่มี tracing ID/correlation ID ที่ผูก request เดียวกันข้าม service เข้าด้วยกัน เมื่อ vtrc-api เรียก cu-central-api ทั้งสอง log แยกกันคนละไฟล์คนละ format ไม่มี field ร่วมที่ join ได้ตรง ๆ
วิธี trace แทน correlation ID:
- บันทึกเวลาที่ user รายงานปัญหาให้ละเอียดที่สุด (นาที:วินาที)
- หา business key ที่ unique พอ —
userId,citizenId(ระวัง PII — ดู runbook 7 ใน 16.1), หรือ ID ของ record ที่เกี่ยวข้อง (เช่น withdraw request ID) - Grep log ของ service ต้นทาง (
vtrc-api) หา business key นั้นในช่วงเวลาที่ user รายงาน - ถ้า log บอกว่าเรียกไป downstream (
cu-central-api,benefit-api, ฯลฯ) ให้ไปหา log ของฝั่งนั้นในช่วงเวลาเดียวกัน ±2-3 วินาที (เผื่อ network latency) - ทำซ้ำจนถึง service ปลายทางที่ error เกิดขึ้นจริง
ข้อจำกัด — วิธีนี้พังทันทีถ้า business key ไม่ปรากฏใน log ของทุก hop (เช่น ถ้า vtrc-api log ด้วย userId แต่ benefit-api log ด้วย record ID ภายในที่ generate ใหม่โดยไม่ผูกกับ userId ในบรรทัดเดียวกัน) — ต้องอ่านโค้ด logging ของแต่ละ service ก่อนเพื่อรู้ว่า field ไหนใช้ join ได้จริง
16.2.2 · Log location ต่อ repo type
ไม่มี log aggregation กลาง (Vol 15) — ต้องเข้าไปดู log ที่ host ของแต่ละ service เอง รูปแบบต่างกันตาม stack:
| Stack | รูปแบบ log | ตำแหน่ง |
|---|---|---|
vtrc-api (Express + custom wlog) | ไฟล์ JSON string ต่อบรรทัด แยกตาม type | logs/{yyyy}/{mm}/{dd}/ ภายใน container/host (vtrc-api/09-cross-cutting) |
vtrc-api request/response log | Apollo plugin log ทุก GraphQL request+response พร้อม PII redaction เฉพาะ header | ไฟล์แยกจาก app log — รูปแบบเดียวกับที่ report-log เคย consume (request_{yyyy-mm-dd}.log) |
NestJS service ทั่วไป (benefit-api, recruitment-api, pms-api, ฯลฯ) | console.log/Nest built-in logger → stdout ของ container | docker logs {container} — ไม่มี rotation กลาง ต้องพึ่ง Docker log driver ของ host |
Express service อื่น (ai-recruitment-api, meeting-vtrc-api, 2way-vtrc-api) | console.log ล้วน ไม่มี structured logger | stdout ของ container เช่นกัน |
cu-central-api | ไม่ยืนยันรูปแบบ log แยกในรอบสำรวจนี้ — UNVERIFIED | ต้องตรวจกับทีมที่ดูแลจริง |
ข้อสังเกตสำคัญ — เพราะทุก service ใช้ console.log/stdout เป็นหลัก การ debug production ต้องมีสิทธิ์ SSH เข้า host ที่รัน container นั้นโดยตรง (หรือสิทธิ์ดู Docker log ผ่านเครื่องมือ orchestration ถ้ามี) ไม่มีทางดู log จาก dashboard กลางได้
16.2.3 · ลำดับการ trace ที่แนะนำเมื่อปัญหาข้าม repo
- ระบุ entry point ที่ user เห็น — frontend ไหน (
vtrc-web,vtrc-mobile, backoffice ตัวใด) เรียก endpoint/query อะไร ใช้browser_network_requestsหรือ mobile network log เพื่อยืนยัน URL ปลายทางจริง (ห้ามเดาจากชื่อ repo — ดู runbook 10 ใน 16.1) - หา service ที่รับ request นั้นตรง — เทียบกับ Volume 13 §03 Inter-service map ว่า service นี้ต่อไปที่ไหนอีกบ้าง
- เช็ค log ของ service แรกก่อน — ถ้า error เกิดที่นี่เลย (validation, auth) ไม่ต้องไล่ต่อ
- ถ้า log บอกว่าเรียก downstream แล้ว error — ระบุว่าเป็น network error (timeout, connection refused) หรือ business error (4xx/5xx ที่มี body) — network error ให้เช็คว่า downstream service ยังรันอยู่ก่อน (ดู runbook 5 ใน 16.1 เป็นตัวอย่าง)
- ถ้าสงสัยว่าเป็น data drift ระหว่าง 2 schema (เช่น
WdHospitals) — เทียบ record ตรงด้วย SQL ทั้งสองฝั่งแทนการไล่ log เพราะ sync เป็น manual/raw-SQL ไม่ผ่าน API ที่ log ได้ (Vol 14 §02) - ถ้าสงสัยว่าเป็น auth — เช็คว่า service ไหน verify token ด้วย secret ตัวไหน (
SEC-API-02— 4 service ใช้ secret เดียวกัน,vtrc-api/cu-central-apiใช้คนละ mechanism) — token ที่ valid ที่ service หนึ่งอาจ invalid ที่อีกตัวถ้า issuer/secret ไม่ match
16.2.4 · ข้อจำกัดที่ต้องยอมรับ
- ไม่มีทาง reconstruct request timeline ข้าม 3+ service ได้แม่นยำระดับ millisecond เพราะไม่มี distributed tracing (Jaeger/Zipkin/OpenTelemetry) ในทุก repo ที่ตรวจสอบ
- Log ที่มี PII (ดู runbook 7 ใน 16.1) ต้องระมัดระวังเป็นพิเศษตอน grep/copy ออกมาวิเคราะห์ — ห้าม commit ไฟล์ log ที่มี PII เข้า repo ใหม่ไม่ว่าเพื่อจุดประสงค์ใด (บทเรียนจาก
report-log) - ถ้าปัญหาเกี่ยวกับ cron/scheduled job ที่ไม่มี health-check (Vol 14 §03
CORR-BIZ-03) log อาจไม่มีหลักฐานว่า cron "ควรจะ" รันแต่ไม่รัน (silent failure) — ต้องเทียบ timestamp ของ record ล่าสุดกับความถี่ cron ที่ประกาศในโค้ดเสมอ ไม่ใช่แค่ดูว่า log มี error หรือไม่