14.4 Log reading & error hunting
บทนี้รวบรวม path ของ log ทุกประเภท, pattern ที่บ่งชี้ปัญหา, และตัวอย่างวิธีค้นหาต้นตอของ error
แผนภาพ log ทั้งระบบ
vtrc-api host
├── /home/dev/vtrc-api/api-logs/ ←── wlog.js เขียน (log file รายวัน)
│ ├── 2025-07-11.log ←── info log
│ ├── error_2025-07-11.log ←── error log
│ ├── warning_2025-07-11.log ←── warning log
│ ├── query_2025-07-11.log ←── SQL query log
│ ├── notificationLog_2025-07-11.log
│ ├── notificationLogError_2025-07-11.log
│ ├── slipError_2025-07-11.log ←── PDF payslip error
│ ├── verify_2025-07-11.log
│ └── forceLogs_2025-07-11.log
│
├── docker logs vtrc-api-nodejs ←── stdout/stderr (console.log)
│ (แต่ละ replica แยกกัน: ...-2, ...-3, ...-5)
│
└── /home/dev/vtrc-api/nginx-log/
├── access-api-443.log ←── access log ของ vtrcapi.redcross.or.th
├── error-api-443.log
├── access-web-443.log ←── access log ของ vtrc.redcross.or.th
└── error-web-443.log
cu-central-api host
├── /home/dev/cu-central-api/main-api/logs/
└── /home/dev/cu-central-api/nginx-log/
centralize-api host
└── /home/dev/centralize-api/logs/ ←── I3GatewayLoggerวิธีอ่าน log
อ่าน log ของ vtrc-api (wlog)
wlog.js เขียน log ในรูปแบบ:
2025-07-11 14:30:45 - {"CODE":"...","SOURCE":"Method:getUsers","TYPE":"INFO","text":"..."}หรือ plain text ในไฟล์ info:
2025-07-11 14:30:45 - server started# อ่าน log ล่าสุดของวันนี้
tail -100 /home/dev/vtrc-api/api-logs/$(date +%Y-%m-%d).log
# ติดตาม log แบบ live
tail -f /home/dev/vtrc-api/api-logs/$(date +%Y-%m-%d).log
# อ่านเฉพาะ error
tail -f /home/dev/vtrc-api/api-logs/error_$(date +%Y-%m-%d).logอ่าน stdout ของ container (console.log)
# ดู 100 บรรทัดสุดท้ายของ replica 1
docker logs --tail 100 vtrc-api-nodejs
# ติดตาม live
docker logs -f vtrc-api-nodejs
# ดู log ตั้งแต่เวลาที่กำหนด
docker logs --since 2h vtrc-api-nodejs
# ดูเฉพาะช่วงเวลา
docker logs --since 2025-07-11T14:00:00 --until 2025-07-11T15:00:00 vtrc-api-nodejsอ่าน nginx access log
# request ล่าสุด 50 รายการที่ vtrcapi.redcross.or.th
tail -50 /home/dev/vtrc-api/nginx-log/access-api-443.log
# หา request ที่ status code 5xx
grep ' 5\d\d ' /home/dev/vtrc-api/nginx-log/access-api-443.log | tail -20
# หา request ที่ช้า (over 1 วินาที — คอลัมน์ `$request_time`)
awk '$NF > 1.0' /home/dev/vtrc-api/nginx-log/access-api-443.log | tail -20Pattern ที่บ่งชี้ปัญหา
Error ระดับวิกฤต
| Pattern | ความหมาย | สาเหตุที่เป็นไปได้ |
|---|---|---|
Unable to connect to the database | vtrc-api เชื่อมต่อ MariaDB ไม่ได้ | db host down, credentials ผิด, network |
JWT_SECRET is invalid | JWT verification fail | secret ถูกเปลี่ยนระหว่าง deploy |
ECONNREFUSED | ไม่สามารถเชื่อมต่อ service อื่น | downstream service ล้มเหลว |
ETIMEDOUT | connection timeout | network ช้า, downstream ไม่ตอบ |
Cannot read property 'X' of undefined | bug ใน code | มักเกิดกับ GraphQL resolver |
SequelizeConnectionAcquireTimeoutError | connection pool ไม่พอ | pool ล็อค, db ช้า |
execSync ใน log | PDF generation ทำงาน | ปกติ แต่ถ้าบ่อยเกินไปแสดงว่าช้า |
qpdf: command not found | qpdf binary ไม่อยู่ | Docker image ผิด |
EACES | LDAP bind ไม่สำเร็จ | credentials ผิด, AD ล้มเหลว |
Error ที่ควรสังเกต
| Pattern | ความหมาย |
|---|---|
Too many connections | MariaDB เปิด connection ไม่พอ |
ER_LOCK_WAIT_TIMEOUT | row lock ค้างนาน — มักจาก transaction ที่ไม่ commit |
ER_DUP_ENTRY | INSERT ซ้ำ — มักเป็น race condition |
REDIS ENOTFOUND | Redis ล้มเหลว |
Failed to send notification | FCM หรือ push ล้มเหลว |
การ grep หา error ของ user เฉพาะ
กรณีที่ 1 — รู้ empcode
# nginx log มี empcode ใน URL (path /readfile/prs/...)
grep '/readfile/prs/.*EMP001' /home/dev/vtrc-api/nginx-log/access-api-443.log
# wlog อาจมี empcode ใน JSON
grep 'EMP001' /home/dev/vtrc-api/api-logs/error_$(date +%Y-%m-%d).logกรณีที่ 2 — รู้เวลาที่เกิดปัญหา
# ดู nginx log ในช่วงเวลาที่รายงาน
awk '/11\/Jul\/2025:14:[3-4][0-9]:/' /home/dev/vtrc-api/nginx-log/access-api-443.log
# ดู wlog ในช่วงเวลา
grep '2025-07-11 14:3' /home/dev/vtrc-api/api-logs/error_2025-07-11.logกรณีที่ 3 — รู้ feature ที่ใช้
# หา log ที่เกี่ยวกับ leave request
grep -i 'leave' /home/dev/vtrc-api/api-logs/error_2025-07-11.log
# หา log ที่เกี่ยวกับ payslip
grep -i 'slip\|prs\|pdf' /home/dev/vtrc-api/api-logs/slipError_2025-07-11.logตัวอย่าง error จริงจาก codebase
ตัวอย่างที่ 1 — PDF payslip ไม่ออก
log ใน slipError_*.log:
2025-07-11 14:30:45 - {"CODE":"PDF_GEN_FAIL","SOURCE":"Mutation:genSlip","TYPE":"ERROR","text":"execSync failed: Command failed: qpdf --encrypt ..."}ตีความ: qpdf ทำงานผิดพลาด อาจเป็นเพราะ:
- password PDF มีอักขระพิเศษที่ break shell command (SEC-1)
- qpdf binary ไม่ได้ติดตั้ง (ตรวจสอบ Docker image)
- disk เต็ม
ตัวอย่างที่ 2 — login ไม่สำเร็จ
log ใน error_*.log:
2025-07-11 14:30:45 - {"CODE":"LDAP_FAIL","SOURCE":"Mutation:login","TYPE":"ERROR","text":"Invalid Credentials"}หรือจาก cu-central-api stdout:
LDAP connection error: ECONNREFUSED 10.188.128.213:389ตีความ: LDAP ไม่ตอบ ตรวจสอบ network ระหว่าง cu-central-api host กับ on-prem
ตัวอย่างที่ 3 — cron ไม่รัน
ไม่มี log ใน notificationLog_*.log หรือ forceLogs_*.log ในวันที่คาดไว้
ตีความ (แยกตาม job):
- ถ้าเป็น fund rate (
updateSuccessFundChangeRateByJob) หรือ cron ของ cu-central → ตรวจว่า replicaAPP_NO=1ยังรัน (docker exec … printenv APP_NO) - ถ้าเป็น
updateDelegatesExpire/statLog→ job เหล่านี้รันทุก replica; อย่าโทษ APP_NO=1 เป็น SPOF — ตรวจ timezone, error ใน log ของทุก replica, และ idempotency ของ handler
วิธีการทำ log rotation
ปัจจุบันไม่มี log rotation ที่ automate — ทีมต้องลบเอง
ลบ log เก่า (manual)
# ลบ log ที่เก่ากว่า 30 วัน
find /home/dev/vtrc-api/api-logs/ -mtime +30 -delete
find /home/dev/vtrc-api/nginx-log/ -mtime +30 -delete
# ดูขนาด log ก่อนลบ
du -sh /home/dev/vtrc-api/api-logs/
ls -lhS /home/dev/vtrc-api/api-logs/ | headDocker container log rotation
Docker log ของ container เก็บใน /var/lib/docker/containers/<id>/<id>-json.log — โตขึ้นเรื่อย ๆ
ตั้งค่าใน /etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "5"
}
}ต้อง restart Docker daemon หลังแก้
nginx log rotation
ใช้ logrotate ของ host:
cat > /etc/logrotate.d/vtrc-nginx <<EOF
/home/dev/vtrc-api/nginx-log/*.log {
daily
rotate 30
compress
missingok
notifempty
create 644 root root
sharedscripts
postrotate
docker exec vtrc-web-server nginx -s reopen 2>/dev/null || true
endscript
}
EOFปัญหาเฉพาะตัวของระบบนี้
1. log กระจายหลายที่
ไม่มีจุดรวม — ต้องดูทั้ง api-logs/, docker logs, nginx-log/ แยกกัน
2. PII ใน log
nginx access log มี pid (identityCard) และ empcode ใน URL — ต้องระวังการ share log กับบุคคลภายนอก
3. log format ไม่ consistent
บางบรรทัดเป็น JSON, บางบรรทัดเป็น plain text — grep ยาก
4. timestamp ใช้ timezone ท้องถิ่น
log ใช้ Asia/Bangkok — ต้องระวังเวลาเทียบกับ UTC ถ้ารวมข้าม timezone
แนะนำ
- เก็บ log อย่างน้อย 90 วัน สำหรับ audit
- อย่า share log ดิบกับบุคคลภายนอก โดยไม่ redact PII
- ทดลอง grep ใน UAT ก่อนทำบน production
- ติดตั้ง logrotate ทุก host เพื่อกัน disk เต็ม
- พิจารณาใช้ log aggregation (Loki, ELK) ในระยะยาว — รายละเอียด Volume 15