จัดการล็อกเว็บไซต์แบรนด์เอง: เก็บและวิเคราะห์ access log, error log และ application log
หนึ่ง ล็อกสามประเภทต่างทำหน้าที่คนละอย่าง อย่าดูรวมกัน
很多人把服务器上所有 .log 文件当成”日志”一锅端,出了事挨个翻。其实三类日志回答的是三个完全不同的问题。访问日志(Nginx/Apache 的 access.log)回答”谁在什么时候请求了什么”;错误日志(Nginx error.log、PHP-FPM 错误)回答”服务端哪里报错了”;应用日志(你代码里自己写的 log)回答”这笔订单处理到哪一步、为什么没成功”。
การตัดสินที่ขัดกับสัญชาตญาณอยู่ตรงนี้:พอเกิดเหตุบนระบบจริง สิ่งที่ควรเปิดดูเป็นอันดับสุดท้ายคือ access log access log มีปริมาณมากและมี noise เยอะ เปิดดูก่อนจะจมอยู่กับ 200 หลายพันบรรทัด ลำดับที่ถูกต้องคือดู error log ก่อนเพื่อหาจุดพัง จากนั้นใช้ access log ดูขอบเขตผลกระทบ (ผู้ใช้กี่คน, URL ไหนบ้าง) สุดท้ายใช้ application log ย้อนขั้นตอนธุรกิจ วิธีนี้เหมือนกับ การวิเคราะห์ log ของ AI crawler ที่เน้นว่า “แยกก่อนว่าใครเป็นคนอ่านคุณ” คือแบ่งประเภทก่อน แล้วค่อยวิเคราะห์
| ประเภทล็อก | คำถามที่ตอบ | ตำแหน่งทั่วไป | ระยะเวลาเก็บที่แนะนำ |
|---|---|---|---|
| access log | ใคร ขออะไร ตอนไหน | access.log ของ Nginx | ข้อมูลร้อน 90 วัน |
| error log | 服务端哪里报错、为什么 | error.log ของ Nginx / error ของ PHP | 1 ปี |
| application log | ขั้นตอนธุรกิจไปถึงไหน ติดตรงไหน | log ที่เขียนเองในโค้ด | 30 วัน |
| system log | เหตุการณ์ของตัวเซิร์ฟเวอร์เอง | /var/log/messages | 30 วัน |
สอง ไปป์ไลน์การเก็บรวบรวม: จาก “กระจัดกระจายตามไฟล์ต่างๆ” สู่ “รวมที่เดียวแล้วค้นหาได้”
สภาพที่พบบ่อยในทีมคนเดียวคือ: Nginx มีล็อกหนึ่ง, PHP มีล็อกหนึ่ง, แอปเขียนล็อกเองอีกหนึ่ง กระจายอยู่คนละไดเรกทอรี พอเซิร์ฟเวอร์รีสตาร์ทหรือย้ายเครื่อง ประวัติก็ขาดตอน ขั้นแรกของการจัดการล็อกไม่ใช่การวิเคราะห์ แต่คือรวมมันเข้าด้วยกัน
วางท่อ 4 ช่วง: โปรแกรมเขียนไฟล์, ตัดตามวัน, รวมไว้ที่เดียว, ตั้งแจ้งเตือนเมื่อเกิดข้อผิดพลาด การตัดใช้ logrotate ตัดรายวัน บีบอัดด้วย gzip กันไฟล์เดียวใหญ่หลาย GB เปิดไม่ขึ้น ส่วนการรวมทำแบบง่ายก่อนก็ได้ — ใช้ rsyslog หรือ agent เบา ๆ ส่ง log ไปยังเครื่องเฉพาะหรือบริการ log บนคลาวด์
ทีมคนเดียวไม่จำเป็นต้องใช้สแตกหนักอย่าง ELK ตั้งแต่แรก เริ่มจากเก็บรวมที่เดียวแล้วมีหน้าค้นหาก็พอ โตขึ้นค่อยคิดเรื่องอื่น เว็บที่มี CDN ต้องเก็บทั้ง edge log และ origin log ด้วย ดูรายละเอียดที่CDN เร่งความเร็วทั่วโลก。
| ขั้นตอน | แนวทาง | เครื่องมือ / การตั้งค่า | ถ้าไม่ทำจะเกิดอะไร |
|---|---|---|---|
| เขียนไฟล์ | เอาต์พุตรูปแบบเดียวกัน | รูปแบบ combined | ฟิลด์ไม่ครบ เขียนสคริปต์วิเคราะห์ยาก |
| ตัดไฟล์ | ตัดรายวันพร้อมบีบอัด | logrotate | ไฟล์เดียวใหญ่เกินจนดิสก์เต็ม |
| รวมศูนย์ | รวมเก็บไว้ที่เดียว | rsyslog / log บนคลาวด์ | เปลี่ยนเครื่องแล้วประวัติขาด |
| แจ้งเตือน | แจ้งเตือนตามเกณฑ์อัตราข้อผิดพลาด | กฎบนแพลตฟอร์มมอนิเตอร์ | กว่าจะรู้ก็ต่อเมื่อผู้ใช้ร้องเรียน |
สาม. error log: ประเภทที่ทีมคนเดียวควรจับตาที่สุด
ในสามประเภท error log ให้ข้อมูลต่อหน่วยสูงสุดและควรจับตาก่อน access log วันหนึ่งหลายแสนบรรทัด แต่ error log อาจมีแค่ไม่กี่ร้อยบรรทัด ทุกบรรทัดคือความล้มเหลวจริงหนึ่งครั้ง การแยก error log ไปรวมศูนย์และตั้งแจ้งเตือนต่างหากให้ผลตอบแทนคุ้มค่าที่สุด
เกณฑ์ให้เป็นตัวเลขชัดเจน: อัตรา error 5xx เกิน 1% ต่อเนื่อง 10 นาที แจ้งเตือนทันที; error ผิดปกติแบบครั้งเดียว (เช่น เชื่อมต่อฐานข้อมูลไม่สำเร็จ, callback การชำระเงินล้มเหลว) เกิดครั้งเดียวก็แจ้งเตือน ไม่ต้องรอสะสม error log ต้องแยกระดับ: warning เก็บไว้ดูเป็นระยะ ส่วน error และ critical ต้องแจ้งแบบเรียลไทม์ แอปอย่าง PHP ต้องดึง fatal error กับ slow query ออกมาแยกด้วย
ตัวอย่างสถานการณ์: เช้าวันหนึ่งสัญญาณเตือนดังขึ้น อัตรา error 5xx กระโดดจาก 0.1% ไป 3% เราเปิด error log ก่อน เห็น “PHP-FPM: unable to connect” เต็มไปหมด จึงรู้ว่าพูลโปรเซสฝั่งแบ็กเอนด์เต็ม จากนั้นดู access log ว่า URL ไหนเป็นตัวกระตุ้น พบว่าเป็น API ที่เพิ่งเปิดใช้ ซึ่งคิวรีช้าไปถ่วงพูลโปรเซสจนเต็ม สุดท้ายดู application log เพื่อยืนยันว่าเป็น SQL ตัวไหน รู้จุดในสิบนาที นี่คือคุณค่าของการดู error log ก่อน
| ระดับความรุนแรง | ตัวอย่าง | วิธีจัดการ | เกณฑ์แจ้งเตือน |
|---|---|---|---|
| critical | เชื่อมต่อฐานข้อมูลไม่ได้, ชำระเงินล้มเหลว | แจ้งทันที | เกิดครั้งเดียวก็แจ้งเตือน |
| error | 5xx, fatal error | แจ้งแบบเรียลไทม์ | เกิน 1% ภายใน 10 นาที |
| warning | slow query, retry | สรุปรายวันดู | สรุปเมื่อเกินเบสไลน์ 2 เท่า |
| notice | ข้อความธุรกิจปกติ | เก็บถาวร ไม่แจ้งเตือน | ไม่แจ้งเตือน |
สี่. application log: ทำให้กระบวนการธุรกิจตรวจสอบย้อนหลังได้
access log และ error log เป็นบันทึก “ตามจริง” ของเซิร์ฟเวอร์ แต่ตอบคำถามธุรกิจอย่าง “ทำไมลีดนี้ไม่เข้า CRM” ไม่ได้ จึงต้องพึ่ง application log — คุณเขียน log เองที่จุดสำคัญของธุรกิจ: ลีดถูกส่งแล้ว, เขียนลงฐานข้อมูลแล้ว, ส่งไป CRM แล้ว, CRM ส่งกลับล้มเหลว
หัวใจของ log แอปพลิเคชันคือทุกบรรทัดต้องมีตัวระบุทางธุรกิจติดมาด้วย เช่น เลขที่ inquiry หรือเลขที่คำสั่งซื้อ พอเกิดปัญหา คุณเอาตัว ID นี้ไปค้น ก็จะร้อยเส้นทางทั้งหมดของธุรกิจนี้ตั้งแต่ยื่นจนจบได้ อย่าเขียน log ที่ไม่มีความหมาย (“ทำงานถึงบรรทัดที่ 10”) ทุกบรรทัดต้องตอบคำถามทางธุรกิจได้ ปริมาณ log ให้คุมไว้ไม่เกินวันละไม่กี่สิบ MB อย่าใส่ request body ทั้งก้อนลงไป ทั้งช้าและรั่วข้อมูลส่วนตัว
ความสัมพันธ์ระหว่างประสิทธิภาพที่ช้ากับ log ก็ควรพูดถึงด้วย: การเขียน log มากเกินไป เขียนลงดิสก์แบบ synchronous ทุก request ก็ทำให้การตอบสนองช้าลงเอง วิธีดูตัวชี้วัดการตอบสนองที่ช้า ดูที่Core Web Vitals ส่วนกรอบการทำงานโดยรวมของการ monitor และแจ้งเตือน ดูที่การมอนิเตอร์และแจ้งเตือนเว็บไซต์。
| โหนดธุรกิจ | สิ่งที่ควรบันทึก | ตัวระบุที่ติดมา | เกิดปัญหาแล้วค้นยังไง |
|---|---|---|---|
| ยื่น inquiry | ฟิลด์ฟอร์ม, หน้าต้นทาง | เลขที่ inquiry | ค้นบันทึกการยื่นด้วย ID |
| บันทึกลงฐานข้อมูล | เขียนสำเร็จ / ล้มเหลว | เลขที่ inquiry | ดูว่าลงฐานข้อมูลหรือไม่ |
| ส่งต่อไปยัง CRM | รหัสตอบกลับของ API, เวลาที่ใช้ | เลขที่ inquiry | ดูว่า CRM รับหรือไม่ |
| แจ้งเตือนทางอีเมล | ส่งสำเร็จ / ล้มเหลว | เลขที่ inquiry | ดูว่าฝ่ายขายได้รับหรือไม่ |
ห้า: ข้อผิดพลาดที่พบบ่อยที่สุดสามข้อในการจัดการ log
กับดักแรกคือ “ไม่ตัดไฟล์ไม่เก็บย้อนหลัง” เขียน log ลงไฟล์เดียวตลอด สามเดือนผ่านไปไฟล์เดียวหลาย GB พอหาสาเหตุ grep ทีนึงค้างเป็นครึ่งวัน หรือไม่ก็เขียนดิสก์เต็มจนเว็บตัวเองล่ม การตัดไฟล์รายวันพร้อมนโยบายเก็บย้อนหลังคือขั้นต่ำสุด
กับดักที่สองคือ “เก็บแค่ real-time ไม่ archive” ดิสก์เต็มก็ลบไฟล์เก่าสุด พออยากดูจุดเริ่มต้นของเหตุขัดข้องเมื่อสองเดือนก่อนก็ไม่มีเลย ข้อมูลร้อนเก็บ 90 วัน เกินนั้นบีบอัด archive ไว้อย่างน้อยหนึ่งปี ต้นทุนต่ำมาก กับดักที่สามคือ “เขียนข้อมูลอ่อนไหวลง log” เอารหัสผ่านผู้ใช้หรือเลขบัตรเครดิตเต็มๆ เขียนลง log เท่ากับสร้างแหล่งรั่วไหลอีกจุดใน log store ฟิลด์อ่อนไหวให้ปิดบังหรือไม่ลงดิสก์ทุกกรณี
| ข้อผิดพลาดที่พบบ่อย | อาการที่เห็น | ปัญหาจริง | วิธีแก้ที่ถูกต้อง |
|---|---|---|---|
| ไม่ตัดไฟล์ | ไฟล์เดียวใหญ่ขึ้นเรื่อยๆ | ดิสก์เต็ม ค้นหาช้า | logrotate ตัดรายวัน |
| ไม่เก็บย้อนหลัง | ดิสก์เต็มก็ลบ | อยากย้อนดูกลับไม่มีข้อมูล | ข้อมูลร้อน 90 วัน, archive 1 ปี |
| เขียนข้อมูลอ่อนไหว | log ช่วย debug | log store กลายเป็นแหล่งรั่วไหล | ปิดบังฟิลด์อ่อนไหว |
| ดูสามประเภทปนกัน | เกิดเรื่องก็ไล่เปิดทีละอัน | หาตำแหน่งช้า เสียงรบกวนเยอะ | เริ่มจาก error ก่อน ค้นแยกตามประเภท |
FAQ คำถามที่พบบ่อย
เว็บไซต์อิสระจำเป็นต้องใช้แพลตฟอร์ม log อย่าง ELK ไหม?
ทำไม log สามประเภทคือ access, error และ application ถึงวางรวมกันไม่ได้?
log แต่ละประเภทควรเก็บนานแค่ไหน?
กำหนด threshold แจ้งเตือนของ error log ยังไง?
application log ควร log ละเอียดแค่ไหน จะกระทบ performance ไหม?
log เก็บรหัสผ่านผู้ใช้และข้อมูลการชำระเงินได้ไหม?
ทิ้งท้าย
คุณค่าของการจัดการ log ไม่ได้อยู่ที่ “เก็บได้เท่าไหร่” แต่อยู่ที่ “เกิดเรื่องแล้วหาจุดได้ในสามนาทีไหม” สำหรับคนทำเว็บคนเดียว แยก log สามประเภทออกจากกัน ตัดไฟล์รายวันรวมศูนย์ แจ้งเตือนเมื่ออัตรา error เกิน 1% วางพื้นฐานชุดนี้ให้ดี เวลา troubleshoot ประจำวันก็ลดจาก “งม log ครึ่งวัน” เหลือ “มองแจ้งเตือนแวบเดียว” ส่วน log platform ระดับหนัก ๆ เป็นเรื่องหลังจาก scale ขึ้นแล้ว ไม่ใช่สิ่งที่จำเป็นตั้งแต่เริ่ม
เริ่มจาก 3 ขั้นตอนนี้ ขั้นแรก แยกเก็บ log 3 ประเภท คือ access, error และ application ออกจากกัน ตัดไฟล์รายวันแล้วตั้งระยะเวลาเก็บต่างกัน ขั้นที่สอง รวม log ไปไว้ที่เดียวด้วย rsyslog หรือบริการ log บนคลาวด์ ให้ค้นหาด้วย business ID ได้ ขั้นที่สาม ตั้ง alert เมื่อ error rate เกิน 1% ใน 10 นาที หรือมี critical error เกิดขึ้นแม้แค่ครั้งเดียว ทำครบสามขั้นนี้แล้ว สิ่งที่คุณรับรู้เกี่ยวกับระบบก็จะเปลี่ยนจาก “รอผู้ใช้บ่นถึงจะรู้” เป็น “รู้ก่อนใคร” ส่วนจังหวะการดูแลรักษาเทียบได้กับ ช่วงดูแลเว็บไซต์ จัดตารางไปพร้อมกันได้เลย
ประโยคเดียวที่จำง่าย ๆ: log ไม่ใช่ไฟล์ในฮาร์ดดิสก์ที่เก็บไว้ให้ระลึกถึงความหลัง แต่เป็นกล้องหน้ารถที่บันทึกเหตุการณ์ ณ จุดเกิดเหตุ ถ้าปกติไม่แยกประเภท ไม่รวมศูนย์ พอเกิดเรื่องก็ได้แต่เดาจากความทรงจำ
