การใช้ Monolog กับ Docker
ในบทที่แล้ว เราได้พูดถึงการ Config Logging สำหรับ Production ซึ่งเน้นไปที่การตั้งค่า Monolog ให้เหมาะสมกับการใช้งานจริงบนเซิร์ฟเวอร์ Production ในบทนี้ เราจะมาดูวิธีการใช้งาน Monolog ภายใน Docker Container ซึ่งเป็นสภาพแวดล้อมที่นิยมใช้กันอย่างแพร่หลายในการ Deploy Application ในปัจจุบัน
การใช้งาน Monolog ใน Docker มีความสำคัญเนื่องจาก Docker Container มักจะถูกออกแบบมาให้เป็น ephemeral (อายุสั้น) นั่นหมายความว่า Log ไฟล์ที่ถูกเขียนไว้ใน Container อาจจะหายไปเมื่อ Container ถูกทำลายหรือ Restart ดังนั้นเราจึงต้องมีวิธีการจัดการ Log ที่เหมาะสมเพื่อให้สามารถติดตามและแก้ไขปัญหาได้
Docker Logging Drivers
Docker มี Logging Drivers ให้เลือกใช้งานหลายแบบ ซึ่งแต่ละแบบก็มีข้อดีข้อเสียแตกต่างกันไป Logging Drivers ทำหน้าที่ในการจัดการ Log ที่ถูกสร้างขึ้นภายใน Container และส่งต่อไปยังปลายทางที่กำหนด ตัวอย่าง Logging Drivers ที่นิยมใช้กันได้แก่:
- json-file: Driver พื้นฐานที่ Docker ใช้โดย default จะบันทึก Log เป็นไฟล์ JSON บน Host Machine เหมาะสำหรับการใช้งานใน Development หรือการ Debug เบื้องต้น
- syslog: ส่ง Log ไปยัง Syslog Server เหมาะสำหรับ Centralized Logging
- journald: ส่ง Log ไปยัง Systemd Journald เหมาะสำหรับระบบที่ใช้ Systemd
- fluentd: ส่ง Log ไปยัง Fluentd ซึ่งเป็น Open Source Data Collector เหมาะสำหรับ Centralized Logging และการจัดการ Log ที่ซับซ้อน
- gelf: ส่ง Log ไปยัง Graylog Extended Log Format (GELF) Server เหมาะสำหรับ Centralized Logging และการวิเคราะห์ Log
Trade-off: การเลือก Logging Driver ที่เหมาะสมขึ้นอยู่กับความต้องการและโครงสร้างพื้นฐานของระบบ หากต้องการความเรียบง่ายและไม่ได้ต้องการ Centralized Logging การใช้ json-file ก็เพียงพอ แต่หากต้องการ Centralized Logging และการจัดการ Log ที่ซับซ้อน การใช้ syslog, fluentd หรือ gelf จะเหมาะสมกว่า
Sending Logs to a Centralized System
แนวปฏิบัติที่ดีที่สุดในการใช้งาน Monolog กับ Docker คือการส่ง Log ไปยัง Centralized Logging System ซึ่งจะช่วยให้เราสามารถรวบรวมและวิเคราะห์ Log จาก Container ต่างๆ ได้จากส่วนกลาง ทำให้ง่ายต่อการติดตามและแก้ไขปัญหา
ในการส่ง Log ไปยัง Centralized Logging System เราสามารถใช้ Monolog Handler ที่เหมาะสม เช่น:
- SyslogHandler: ส่ง Log ไปยัง Syslog Server
- FluentdHandler: ส่ง Log ไปยัง Fluentd
- GelfHandler: ส่ง Log ไปยัง Graylog
ตัวอย่าง: การส่ง Log ไปยัง Syslog Server
use Monolog\Logger;
use Monolog\Handler\SyslogHandler;
// สร้าง Logger
$logger = new Logger('my_app');
// สร้าง SyslogHandler
$syslogHandler = new SyslogHandler('my_app', LOG_USER, Logger::WARNING);
// เพิ่ม Handler ให้กับ Logger
$logger->pushHandler($syslogHandler);
// บันทึก Log
$logger->warning('This is a warning message');
ในตัวอย่างนี้ เราได้สร้าง SyslogHandler และกำหนดให้ส่ง Log ไปยัง Syslog Server โดยใช้ Facility เป็น LOG_USER และ Log Level เป็น WARNING
Trade-off: การส่ง Log ไปยัง Centralized Logging System ทำให้เกิด Overhead เพิ่มขึ้นเล็กน้อย แต่ก็คุ้มค่าเมื่อเทียบกับประโยชน์ที่ได้รับในการติดตามและแก้ไขปัญหา
JSON Format
ในการใช้งาน Monolog กับ Docker การใช้ JSON Format สำหรับ Log Message เป็นสิ่งที่แนะนำ เนื่องจากทำให้ง่ายต่อการ Parse และวิเคราะห์ Log โดยเครื่องมือต่างๆ
Monolog มี Formatter ให้เลือกใช้งานหลายแบบ ซึ่งรวมถึง JsonFormatter ที่สามารถแปลง Log Record ให้เป็น JSON String ได้
ตัวอย่าง: การใช้ JsonFormatter
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Formatter\JsonFormatter;
// สร้าง Logger
$logger = new Logger('my_app');
// สร้าง StreamHandler
$streamHandler = new StreamHandler('php://stdout', Logger::WARNING);
// สร้าง JsonFormatter
$jsonFormatter = new JsonFormatter();
// กำหนด Formatter ให้กับ Handler
$streamHandler->setFormatter($jsonFormatter);
// เพิ่ม Handler ให้กับ Logger
$logger->pushHandler($streamHandler);
// บันทึก Log
$logger->warning('This is a warning message', ['context' => ['user_id' => 123]]);
ในตัวอย่างนี้ เราได้สร้าง JsonFormatter และกำหนดให้กับ StreamHandler ซึ่งจะทำให้ Log ที่ถูกบันทึกออกมาในรูปแบบ JSON
Output:
{"message":"This is a warning message","context":{"user_id":123},"level":300,"level_name":"WARNING","channel":"my_app","datetime":"2023-10-27T10:00:00+00:00","extra":[]}
Trade-off: การใช้ JSON Format อาจจะทำให้ Log มีขนาดใหญ่ขึ้นเล็กน้อย แต่ก็ทำให้ง่ายต่อการ Parse และวิเคราะห์ Log มากขึ้น
สรุป
การใช้งาน Monolog กับ Docker เป็นสิ่งสำคัญเพื่อให้สามารถจัดการ Log ได้อย่างมีประสิทธิภาพ การเลือก Logging Driver ที่เหมาะสม การส่ง Log ไปยัง Centralized Logging System และการใช้ JSON Format เป็นแนวปฏิบัติที่ดีที่ควรนำไปใช้
ในบทต่อไป เราจะมาพูดถึงการจัดการ Secret Keys ด้วย Environment Variables ซึ่งเป็นอีกหนึ่งหัวข้อที่สำคัญในการพัฒนา Application ที่มีความปลอดภัย