ระบบ Log ใน Java แบบเปลี่ยน implementation ได้ภายหลังด้วย SLF4J

slf4j-logo

จริงๆแล้ว จาวาเองก็มีระบบ log ของตัวเองอยู่แล้ว แต่ถ้าจะใช้งานหนักๆอย่างเช่น การเปลี่ยนรูปแบบข้อความที่จะ log นั้น ต้องสร้างคลาสขึ้นมาเพื่อปรับรูปแบบ เท่าที่สังเกต ส่วนมากจึงเลือกใช้เฟรมเวิร์ก (logging framework) แทน เช่น log4j หรือ jakarta-logging

ปรากฏว่าในเวลาต่อมา log4j ที่ได้รับความนิยมสูงสุดเองก็หยุดพัฒนา โดยผู้เริ่มต้นพัฒนาเองเปลี่ยนไปทำ logback แทน แม้ว่าการใช้งานจะคล้ายๆเดิม แต่ก็มีรายละเอียดบางอย่างที่เปลี่ยนไป

SLF4J เป็นจาวาไลบรารี่ที่ทำหน้าที่เป็นหน้าด่าน (facade) ที่ทำให้นักพัฒนาใช้งานระบบ log ด้วยเอพีไอ (API) เดียวกัน แต่สามารถเปลี่ยน implementation ได้โดยไม่ต้องแก้ไขโปรแกรม เพียงแค่เปลี่ยนไลบรารี่ที่ใช้ พร้อมกับคอนฟิกของแต่ละค่ายเท่านั้น นอกจากนี้ยังสามารถเพิ่มเติมให้รองรับการทำงานมากขึ้นได้ เช่น เพิ่มระดับการ log ได้

จุดเด่นอีกอย่างของ SLF4J คือ parameterized message ซึ่งเป็นเอพีไอที่ช่วยเพิ่มประสิทธิภาพในการทำงาน เพราะไม่ต้องสร้างสตริงจากการต่อสตริงกับออบเจ็กต์ (object) ก่อน แม้ว่าจะไม่ต้อง log ก็ตาม

Continue reading

ใช้ command line จัดการ Application บน Openshift

โอเพ่นชิฟต์ (Openshift) มีระบบจัดการ rhc ที่สามารถติดตั้งบนเครื่องได้ แต่ส่วนตัวรู้สึกว่าคุ้นเคยกับการใช้คอมมานด์ไลน์ (command line) บนเซิร์ฟเวอร์มากกว่า

เมื่อติดตั้งแอพพลิเคชันผ่าน โอเพ่นชิฟต์ เว็บคอนโซล (Web Console) และเชื่อมต่อซอร์สโค้ดกับกิต (git) ก็จะต้องติดตั้ง ssh key แล้วเช่นกัน คีย์นี้สามารถนำไปใช้เข้าถึงเซิร์ฟเวอร์ได้ โดยเข้าไปที่แอพพลิเคชัน บนเว็บคอนโซล จะแสดงคำสั่งที่ใช้เข้าถึงเซิร์ฟเวอร์ในรูปแบบ

ssh <รหัสแอพ>@<ชื่อแอพ>-<โดเมนของเรา>.rhcloud.com

และเนื่องจากใช้คีย์ ssh จึงไม่ต้องกรอกรหัสผ่าน

เมื่อเข้าได้ จะสามารถดูข้อมูลต่างๆในเครื่องได้ทั้งหมด แต่การสร้างไฟล์ใหม่ จะทำได้เฉพาะในไดเรกทอรี app-root/data เท่านั้น พื้นที่เก็บข้อมูลถูกจำกัดไว้ที่เบื้องต้น 1 GB

ส่วนหล็อกไฟล์ (log file) จะอยู่ที่ app-root/logs จะมีหล็อกของ cron, haproxy และแอพพลิเคชัน ในที่นี้ได้ติดตั้ง ทอมแคต (Tomcat) 7 ก็จะมีหล็อกที่นี่เช่นกัน

บางครั้งการพุช (push) ซอร์สโค้ดขึ้นไปเพื่อดีพลอย (deploy) อาจจะเกิดปัญหา ก็จะดูหล็อกได้เบื้องต้นว่าเกิดปัญหาอะไรบ้าง

ในกรณีของเว็บแอพพลิเคชัน

  1. ดูว่า haproxy มีปัญหาหรือไม่ โดยเข้าไปที่ http://<ชื่อแอพ>-<โดเมนของเรา>.rhcloud.com/haproxy-status/ เพราะ haproxy คือหน้าด่านในการเข้าถึงเว็บเบื้องหลัง
  2. ตรวจสอบเว็บแอพพลิเคชันว่าเกิดรันไทม์เอ็กเซ็พชัน (RuntimeException) หรือไม่ เพราะบางครั้งทอมแคตจะอุบเงียบ วิธีการเข้าถึงต้องสังเกตตอนดีพลอย เมเว่น (Maven) จะบอกว่าเว็บเรานั้นถูกดีพลอยไว้ที่ไอพีและพอร์ตอะไร ในตอนท้ายๆของการดีพลอย เช่น remote: Found aaa.bbb.ccc.ddd:8080 listening port
  3. ถ้าอยากลองรีสตาร์ตแอพพลิเคชัน เพื่อดูผลลัพธ์เบื้องต้นให้ใช้คำสั่ง ctl_app restart ระบบจะแจ้งว่ามีระบบอะไรที่สามารถจัดการได้บ้าง ก็ใส่ตัวเลขที่อยู่ด้านหน้าระบบนั้นๆ เครื่องจะทำการรีสตาร์ตระบบนั้นๆให้

ctl_app สามารถใช้จัดการอื่นๆได้ด้วย ดูคำสั่งย่อยได้โดยการใช้คำสั่ง ctl_app โดยไม่ระบุ คำสั่งย่อย

สแลช (SLASH)

Java มี Logging framework ของตัวเองอยู่แล้ว

การพัฒนาระบบ ยังไงก็หนีไม่พ้นการทำหล็อก (log) ซึ่งในจาวา เฟรมเวิร์คที่โด่งดังก็คงเป็นหล็อกโฟร์เจ (Log4j) กับ หล็อกแบ๊ค (Logback) ซึ่งคนทำหล็อกโฟร์เจย้ายไปทำ แต่ถ้าไม่ต้องการความยืดหยุ่นระดับการปรับฟอร์แมตของข้อความด้วยคอนฟิกไฟล์ (config file) หรือการแสดงผลสีที่แตกต่างกันในแต่ละระดับของหล็อก (Log level) ในจาวาเองก็มีระบบหล็อกอยู่แล้ว คือ จาวาหล็อกกิ้ง (Java Logging)

การใช้งานก็จะคล้ายๆกับเฟรมเวิร์คที่กล่าวมา คือ ดึงหล็อกเกอร์ (logger) ออกมาแล้วแสดงผลตามระดับ ซึ่งระดับ ALL, OFF, SEVERE, WARNING, INFO, FINE, FINER และ FINEST คงพอเดาความหมายของแต่ละระดับได้นะ

  • log = Logger.getLogger(<ชื่อหล็อกเกอร์หรือคลาส>)
  • log.<ระดับ>(“ข้อความ”) -> ถ้าไม่ต้องการแสดงผลค่าจากตัวแปร
  • log.log(Level.<ระดับ>, “ข้อความที่จะแสดง {0} …”, <ตัวแปร 1> ) -> แสดงผล 1 ตัวแปร
  • log.log(Level.<ระดับ>, “ข้อความที่จะแสดง {0} {1} …”, new Object[] { <ตัวแปร 1>, <ตัวแปร 2>, … }) -> แสดงผลมากกว่า 1 ตัวแปร

ถ้าไม่พอใจรูปแบบข้อความก็สามารถเขียนตัวจัดรูปแบบได้เอง โดยสร้างคลาสที่ extends Formatter และเม็ทเถิด formatMessage(record) ช่วยในการแสดงผล

โดยค่าเริ่มต้นเจอาร์อี (JRE) จะตั้งไว้ที่ INFO เราสามารถปรับได้โดยสร้างพร็อพเพอร์ตี้ส์ไฟล์ (properties file) และเซ็ตชื่อไฟล์เข้ามาในซิสเท็มพร็อพเพอร์ตี้ -Djava.util.logging.config.file=<ชื่อไฟล์> ได้ ซึ่งเซ็ตได้ทั้งแฮนดเลอร์ (handler) ว่าจะออกคอนโซล (console) ไฟล์ หรือแม้กระทั่งผ่านเครือข่ายไป (stream)

สแลช (SLASH)