ส่วนหน้าของ SLF4J และตัวบันทึก
บันทึกในระดับที่เหมาะสม
ส่วนหน้าของ SLF4J และตัวบันทึก เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
SLF4J คืออะไร
SLF4J (ส่วนเชื่อมการบันทึกแบบง่ายสำหรับ Java) คือชั้นนามธรรม คุณเขียนโค้ดเรียกใช้ส่วนติดต่อของมัน แล้วระบบเบื้องหลังอย่าง Logback หรือ Log4j2 จะดำเนินการบันทึกล็อกจริง
วิธีนี้ทำให้ไลบรารีบันทึกล็อกได้โดยไม่บังคับให้แอปพลิเคชันใช้การนำไปใช้งานแบบใดแบบหนึ่ง
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
log.info("Application started");
}
}การรับตัวบันทึก
สร้างตัวบันทึกหนึ่งตัวต่อหนึ่งคลาสด้วย LoggerFactory.getLogger(MyClass.class)
ตามธรรมเนียม ฟิลด์จะเป็น private static final และตั้งชื่อเป็น log หรือ logger ชื่อของคลาสจะกลายเป็นชื่อตัวบันทึก ซึ่งจะแสดงในผลลัพธ์
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OrderService {
private static final Logger log = LoggerFactory.getLogger(OrderService.class);
void placeOrder(String id) {
log.info("Placing order {}", id);
}
}ห้าระดับ
ตัวบันทึกของ SLF4J มีเมธอดหนึ่งเมธอดต่อหนึ่งระดับ:
log.trace(...)log.debug(...)log.info(...)log.warn(...)log.error(...)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
log.trace("entering main");
log.debug("args length = {}", args.length);
log.info("service is up");
log.warn("cache miss");
log.error("failed to connect");
}
}การเลือกระดับที่เหมาะสม
แนวทางมีดังนี้:
- ERROR: ความล้มเหลวจริงที่มนุษย์ต้องตรวจสอบ
- WARN: ความผิดปกติที่กู้คืนได้
- INFO: เหตุการณ์สำคัญในวงจรชีวิต
- DEBUG: ข้อมูลวินิจฉัยสำหรับนักพัฒนา ซึ่งปิดใช้งานในระบบจริง
- TRACE: การติดตามที่มีรายละเอียดอย่างมาก
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PaymentService {
private static final Logger log = LoggerFactory.getLogger(PaymentService.class);
void charge(int cents) {
if (cents <= 0) { log.warn("non-positive charge: {}", cents); return; }
log.info("charged {} cents", cents);
}
}ชื่อตัวบันทึกและลำดับชั้น
ชื่อตัวบันทึกมีลำดับชั้นตามแพ็กเกจที่คั่นด้วยจุด ตัวบันทึกชื่อ com.example.svc เป็นรายการย่อยของ com.example
การกำหนดค่าบนรายการหลักจะมีผลกับรายการย่อย เว้นแต่จะถูกกำหนดทับ ดังนั้นคุณจึงตั้งระดับแยกตามแพ็กเกจได้
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
Logger a = LoggerFactory.getLogger("com.example.app");
Logger b = LoggerFactory.getLogger("com.example.app.db");
a.info("parent logger");
b.debug("child inherits parent's level unless overridden");
}
}การป้องกันการเรียกใช้ที่ใช้ทรัพยากรมาก
สำหรับการสร้างข้อความที่ใช้ทรัพยากรมาก ให้ป้องกันด้วย isDebugEnabled() เพื่อให้การประมวลผลทำงานเฉพาะเมื่อระดับนั้นเปิดใช้งานอยู่
เมื่อใช้การบันทึกแบบมีพารามิเตอร์ในบทเรียนถัดไป คุณแทบไม่จำเป็นต้องทำเช่นนี้ แต่การป้องกันนี้จำเป็นเมื่อคุณสร้างสตริงด้วยตนเอง
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
static String heavyDump() { return "...large state..."; }
public static void main(String[] args) {
if (log.isDebugEnabled()) {
log.debug("state: {}", heavyDump());
}
}
}การบันทึกข้อยกเว้น
หากต้องการบันทึกข้อยกเว้นพร้อมการติดตามสแตกทั้งหมด ให้ส่ง Throwable เป็น อาร์กิวเมนต์สุดท้าย
อย่าใส่ข้อยกเว้นไว้ในตัวยึดตำแหน่ง ให้ส่งข้อยกเว้นหลังข้อความ
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
try {
throw new IllegalStateException("boom");
} catch (Exception e) {
log.error("Operation failed for id {}", 42, e);
}
}
}ตัวบันทึกหนึ่งตัวต่อหนึ่งคลาส
ประกาศตัวบันทึกหนึ่งครั้งเป็นฟิลด์แบบ static final อย่าสร้างตัวบันทึกภายในเมธอด เพราะเป็นการเสียการประมวลผลและทำให้สูญเสียประโยชน์จากชื่อคลาส
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UserRepository {
// Good: one shared logger named after the class
private static final Logger log = LoggerFactory.getLogger(UserRepository.class);
void save(String user) { log.debug("saving {}", user); }
}SLF4J กับระบบเบื้องหลัง
SLF4J เป็นเพียงส่วนติดต่อเท่านั้น เมื่อโปรแกรมทำงาน ส่วนติดต่อจะเชื่อมกับระบบเบื้องหลังใดก็ตามที่อยู่ในเส้นทางคลาส
- เพิ่ม
logback-classic: SLF4J จะใช้ Logback - เพิ่ม
log4j-slf4j2-impl: SLF4J จะใช้ Log4j2
โค้ดของคุณไม่ต้องเปลี่ยนแปลง
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
// Same code, different backend depending on classpath
log.info("backend-agnostic logging");
}
}หลีกเลี่ยงการบันทึกข้อมูลที่ละเอียดอ่อน
อย่าบันทึกรหัสผ่าน โทเค็น หรือหมายเลขบัตรเครดิตแบบเต็มลงในล็อก ล็อกมักถูกส่งต่อไปยังหลายระบบและเก็บรักษาไว้เป็นเวลานาน
ให้ปกปิดหรือตัดฟิลด์ที่ละเอียดอ่อนออกก่อนบันทึกล็อก
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
static String mask(String card) { return "****" + card.substring(card.length() - 4); }
public static void main(String[] args) {
log.info("charged card {}", mask("4111111111111234"));
}
}บริการที่สมจริง
เมื่อนำทุกอย่างมารวมกัน: บริการขนาดเล็กที่บันทึกล็อกด้วยระดับที่เหมาะสมและมีเส้นทางจัดการข้อยกเว้น
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EmailService {
private static final Logger log = LoggerFactory.getLogger(EmailService.class);
void send(String to) {
log.debug("preparing email to {}", to);
try {
if (to == null) throw new IllegalArgumentException("null recipient");
log.info("email sent to {}", to);
} catch (Exception e) {
log.error("failed to send email", e);
}
}
}ตรวจสอบความเข้าใจ
ทดสอบความรู้พื้นฐานเกี่ยวกับ SLF4J
ทบทวน
คุณได้เรียนรู้เกี่ยวกับส่วนเชื่อม SLF4J:
- รับ
private static final Loggerหนึ่งตัวต่อหนึ่งคลาส - ใช้เมธอดทั้งห้าระดับให้เหมาะสม
- ชื่อตัวบันทึกมีลำดับชั้นเพื่อควบคุมแยกตามแพ็กเกจ
- ส่ง
Throwableเป็นอาร์กิวเมนต์สุดท้ายเพื่อบันทึกการติดตามสแตก และอย่าบันทึกข้อมูลลับ
ถัดไปคือข้อความแบบมีพารามิเตอร์ที่มีประสิทธิภาพ
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
log.info("SLF4J facade recap complete");
}
}คำถามที่พบบ่อย
บทเรียน “ส่วนหน้าของ SLF4J และตัวบันทึก” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ส่วนหน้าของ SLF4J และตัวบันทึก” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ส่วนหน้าของ SLF4J และตัวบันทึก”
บันทึกในระดับที่เหมาะสม คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “ส่วนหน้าของ SLF4J และตัวบันทึก” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม
ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- เหตุใดจึงควรใช้การบันทึกแบบมีโครงสร้าง
- ส่วนหน้าของ SLF4J และตัวบันทึก
- การบันทึกแบบกำหนดพารามิเตอร์
- การกำหนดค่า Logback