ระบบ 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 ก็ตาม

วิธีการใช้งานเบื้องต้น

  1. เพิ่มไลบรารี่ org.slf4j:slf4j-api ด้วย build tool ที่ถนัด
  2. เลือกไลบรารี่ที่เป็นส่วนเชื่อมต่อกับ implementation โดยทาง SLF4J แนะนำให้ใช้เวอร์ชันเดียวกันกับ slf4j-api เพื่อความเข้ากันได้สูงสุด ซึ่งตรงนี้คือส่วนสำคัญ เพราะจะเลือก implementation ที่นี่ ตัวที่ได้รับความนิยมก็จะมี
    • ch.qos.logback:logback-classic (เป็นตัวยกเว้น เพราะจะมี dependency ไปหา slf4j-api เวอร์ชันที่เหมาะสมเอง)
    • org.slf4j:slf4j-log4j12
    • org.slf4j:slf4j-jdk14 (ชื่ออาจจะเหมือนว่าใช้ได้กับ JDK1.4 แต่ใช้กับ JDK ใดๆก็ได้)
  3. สร้างตัวแปร Logger ผ่าน LoggerFactory
    Logger log = LoggerFactory.getLogger(getClass());
  4. log ข้อความ แต่ระดับผ่าน method (ในวงเล็บ คือระดับใน Java Logging ซึ่งจะเห็นว่าไม่มี finest ถ้าจะใช้ต้องปรับแต่งเพิ่มเติมเอง)
    • error (severe)
    • warn (warning)
    • info
    • debug (fine)
    • trace (finer)

วิธีการใช้งานคือให้เปลี่ยนวิธีการเขียนแบบเดิม

log.debug("Hello " + obj.getName() + ", " + obj.getMessage());

เป็นแบบ parameterized message

log.debug("Hello {}, {}", obj.getName(), obj.getMessage());

ซึ่งทำให้เมื่อตั้งระดับการ log ไว้ที่ info จะไม่มีอ้างถึง obj.getName() และ obj.getMessage() เลย

การเลือกระบุให้เป็นตัวแปร static หรือ instance นั้น มีการถกเถียงกันมาก เพราะแบบ static จะช่วยเรื่องประสิทธิภาพ แต่ไม่ค่อยมีผลเท่าไหร่กับฮาร์ดแวร์สมัยนี้ ส่วนแบบ instance นั้นเหมาะกับการทำเทสต์มากกว่า สามารถเข้าไปยังเว็บไซต์ที่ระบุด้านล่างเพื่อศึกษารายละเอียดเพิ่มเติม

ที่มา:

สแลช (Slash)

Leave a comment