2.1 คนตัดไม้คนแรก - log4j
ดังที่คุณทราบแล้ว ประวัติของบันทึกเริ่มต้นด้วยSystem.err.println()
เอาต์พุตของบันทึกไปยังคอนโซล ยังคงใช้สำหรับการดีบัก เช่น Intellij IDEA ใช้เพื่อแสดงข้อความแสดงข้อผิดพลาดไปยังคอนโซล แต่ตัวเลือกนี้ไม่มีการตั้งค่าใด ๆ ดังนั้นไปกันเลย
คนตัดไม้คนแรกและได้รับความนิยมมากที่สุดถูกเรียกLog4j
ว่า เป็นโซลูชันที่ดีและปรับแต่งได้สูง เนื่องจากสถานการณ์ต่าง ๆ การตัดสินใจนี้จึงไม่ได้รับการพิจารณาจาก JDK ซึ่งทำให้ทั้งชุมชนไม่พอใจอย่างมาก
คนตัดไม้นี้ไม่เพียงแค่สามารถบันทึกได้ แต่ถูกสร้างขึ้นโดยโปรแกรมเมอร์สำหรับโปรแกรมเมอร์และอนุญาตให้พวกเขาแก้ปัญหาที่เกิดขึ้นอย่างต่อเนื่องเกี่ยวกับการบันทึก
ดังที่คุณทราบแล้ว บันทึกจะถูกเขียนในตอนท้ายเพื่อให้บางคนอ่านและพยายามเข้าใจว่าเกิดอะไรขึ้นระหว่างการทำงานของโปรแกรม - อะไรและเมื่อใดที่ผิดพลาดตามที่คาดไว้
มีlog4j
สามสิ่งสำหรับสิ่งนี้:
- การบันทึกแพ็คเกจย่อย
- ชุดของ appenders (ผล);
- การตั้งค่าโหลดร้อน
ประการแรก การตั้งค่าlog4j
สามารถเขียนในลักษณะที่เปิดใช้งานการเข้าสู่ระบบในแพ็คเกจหนึ่งและปิดใช้งานในอีกแพ็คเกจหนึ่ง ตัวอย่างเช่น เป็นไปได้ที่จะเปิดใช้งานการเข้าสู่ระบบในcom.codegym.server
แต่ปิดใช้งานcom.codegym.server.payment
ใน สิ่งนี้ทำให้สามารถลบข้อมูลที่ไม่จำเป็นออกจากบันทึกได้อย่างรวดเร็ว
ประการที่สองlog4j
อนุญาตให้เขียนผลลัพธ์การบันทึกลงในไฟล์บันทึกหลายไฟล์พร้อมกัน และเอาต์พุตสำหรับแต่ละรายการสามารถกำหนดค่าแยกกันได้ ตัวอย่างเช่นในไฟล์หนึ่งคุณสามารถเขียนเฉพาะข้อมูลเกี่ยวกับข้อผิดพลาดร้ายแรงในไฟล์อื่น - บันทึกจากโมดูลเฉพาะและในบันทึกที่สามในช่วงเวลาหนึ่ง
ไฟล์บันทึกแต่ละไฟล์จึงได้รับการปรับให้เข้ากับประเภทปัญหาที่คาดไว้โดยเฉพาะ สิ่งนี้ทำให้ชีวิตของโปรแกรมเมอร์ที่ไม่สนุกกับการดูผ่านไฟล์บันทึกกิกะไบต์ด้วยตนเองง่ายขึ้นอย่างมาก
และประการสุดท้าย ประการที่สามlog4j
อนุญาตให้เปลี่ยนการตั้งค่าบันทึกได้โดยตรงในขณะที่โปรแกรมกำลังทำงาน โดยไม่ต้องรีสตาร์ท สิ่งนี้มีประโยชน์มากเมื่อจำเป็นต้องแก้ไขการทำงานของบันทึกเพื่อค้นหาข้อมูลเพิ่มเติมเกี่ยวกับข้อผิดพลาดเฉพาะ
สำคัญ! บันทึกมีสองเวอร์ชันlog4j
: 1.2.xและ2.xxซึ่งเข้ากันไม่ได้
คุณสามารถเชื่อมต่อคนตัดไม้กับโครงการโดยใช้รหัส:
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.2</version>
</dependency>
</dependencies>
2.2 คนตัดไม้อย่างเป็นทางการคนแรก - JUL: java.util.logging
หลังจากที่ Zoo of loggers ปรากฏขึ้นในชุมชน Java นักพัฒนาJDK
ตัดสินใจที่จะสร้างตัวบันทึกมาตรฐานเดียวที่ทุกคนจะใช้ นี่คือลักษณะของคนตัดไม้: JUL
packagejava.util.logging
อย่างไรก็ตาม ในระหว่างการพัฒนา ผู้สร้างตัวตัดไม้ไม่ได้ยึดเป็นพื้นฐานlog4j
แต่เป็นตัวแปรของตัวตัดไม้จาก IBM ซึ่งมีอิทธิพลต่อการพัฒนา ข่าวดีก็คือมีคนตัดไม้JUL
รวมอยู่ด้วยJDK
ข่าวร้ายคือมีคนใช้ไม่กี่คน
นักพัฒนาไม่เพียงJUL
สร้าง"มาตรฐานสากลอื่น" เท่านั้น แต่พวกเขายังสร้างระดับการบันทึกสำหรับมาตรฐานนี้ด้วย ซึ่งแตกต่างจากมาตรฐานที่ยอมรับโดยนักบันทึกยอดนิยมในขณะนั้น
และนั่นเป็นปัญหาใหญ่ ท้ายที่สุดแล้ว ผลิตภัณฑ์ต่างๆJava
มักจะถูกรวบรวมจากห้องสมุดจำนวนมาก และแต่ละห้องสมุดดังกล่าวก็มีตัวบันทึกของตนเอง ดังนั้นจึงจำเป็นต้องกำหนดค่าตัวบันทึกทั้งหมดที่อยู่ในแอปพลิเคชัน
แม้ว่าคนตัดไม้จะค่อนข้างดี การสร้างคนตัดไม้นั้นเหมือนกันมากหรือน้อย ในการทำเช่นนี้ คุณต้องนำเข้า:
java.util.logging.Logger log = java.util.logging.Logger.getLogger(LoggingJul.class.getName());
ชื่อคลาสจะถูกส่งผ่านเป็นพิเศษเพื่อให้ทราบว่าการบันทึกมาจากที่ใด
เฉพาะกับการเปิดตัวเท่านั้นนักพัฒนาได้แก้ไขปัญหาที่สำคัญหลังจากนั้นจึงJUL
ใช้งานได้สะดวกจริงๆ ก่อนหน้านั้นเป็นคนตัดไม้อัตราที่สอง
คนตัดไม้นี้ยังรองรับการแสดงออกของแลมบ์ดาและการประเมินแบบขี้เกียจ เริ่มต้นด้วยJava 8
คุณสามารถSupplier<String>
ผ่าน สิ่งนี้ช่วยในการอ่านและสร้างสตริงในเวลาที่จำเป็นจริง ๆ เท่านั้น ไม่ใช่ทุกครั้งเหมือนเมื่อก่อน
วิธีการที่มีอาร์กิวเมนต์Supplier<String> msgSupplier
มีลักษณะดังนี้:
public void info(Supplier msgSupplier) {
log(Level.INFO, msgSupplier);
}
2.3 ตัวตัดบันทึกตัวแรก - JCL: จาการ์ตาบันทึกทั่วไป
เป็นเวลานานแล้วที่ไม่มีมาตรฐานเดียวในหมู่คนตัดไม้ มันJUL
ควรจะเป็นหนึ่งเดียว แต่มันแย่กว่าlog4j
นั้น มาตรฐานเดียวไม่เคยปรากฏ แต่คนตัดไม้ทั้งสวนสัตว์ปรากฏขึ้นซึ่งแต่ละคนต้องการที่จะเหมือนกัน
อย่างไรก็ตาม นักพัฒนา Java ทั่วไปไม่ชอบที่ห้องสมุดเกือบทุกแห่งมีตัวบันทึกของตัวเองและจำเป็นต้องกำหนดค่าด้วยวิธีพิเศษ ดังนั้น ชุมชนจึงตัดสินใจสร้าง wrapper พิเศษเหนือคนตัดไม้รายอื่น - นี่คือวิธีการJCL: jakarta commons logging
และอีกครั้งโครงการที่สร้างขึ้นเพื่อเป็นผู้นำไม่ได้กลายเป็นหนึ่งเดียว คุณไม่สามารถสร้างผู้ชนะได้ คุณสามารถเป็นผู้ชนะได้เท่านั้น ฟังก์ชันการทำงานJCL
แย่มากและไม่มีใครอยากใช้ คนตัดไม้ซึ่งออกแบบมาเพื่อแทนที่คนตัดไม้ทั้งหมด ประสบชะตากรรมเดียวกับที่JUL
ไม่ได้ใช้งาน
แม้ว่ามันจะถูกเพิ่มเข้าไปในไลบรารีมากมายที่เผยแพร่โดยชุมชน Apache แต่สวนสัตว์แห่งคนตัดไม้ก็เติบโตขึ้นเท่านั้น
2.4 คนตัดไม้คนสุดท้ายคนแรก - การกลับเข้าระบบ
แต่นั่นไม่ใช่ทั้งหมด นักพัฒนาlog4j
ตัดสินใจว่าเขาฉลาดที่สุด (เพราะคนส่วนใหญ่ใช้คนตัดไม้ของเขา) และตัดสินใจเขียนตัวตัดไม้ที่ได้รับการปรับปรุงใหม่ซึ่งจะรวมเอาข้อดีของlog4j
คนตัดไม้อื่นๆ
คนตัดไม้ใหม่ถูกเรียกLogback
ว่า คนตัดไม้นี้ควรจะกลายเป็นคนตัดไม้คนเดียวในอนาคตที่ทุกคนจะใช้ มันขึ้นอยู่กับแนวคิดเดียวกันกับในlog4j
.
คุณสามารถเชื่อมต่อตัวบันทึกนี้กับโครงการโดยใช้รหัส:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.6</version>
</dependency>
ความแตกต่างอยู่ในLogback
:
- ปรับปรุงประสิทธิภาพ
- เพิ่มการสนับสนุนแบบเนทีฟ
slf4j
; - ตัวเลือกการกรองแบบขยาย
ข้อดีอีกอย่างของตัวบันทึกนี้คือมีการตั้งค่าเริ่มต้นที่ดีมาก และคุณต้องกำหนดค่าคนตัดไม้เฉพาะเมื่อคุณต้องการเปลี่ยนบางอย่างในนั้น นอกจากนี้ ไฟล์การตั้งค่ายังได้รับการปรับให้เข้ากับซอฟต์แวร์ขององค์กรได้ดีขึ้น - การกำหนดค่าทั้งหมดถูกตั้งค่าเป็นxml/
.
ตามค่าเริ่มต้นLogback
ไม่จำเป็นต้องตั้งค่าใดๆ และบันทึกบันทึกทั้งหมดตั้งแต่ระดับDEBUG
ขึ้นไป หากคุณต้องการลักษณะการทำงานที่แตกต่างกัน คุณสามารถกำหนดค่าได้ผ่านxml
การกำหนดค่า:
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>app.log</file>
<encoder>
<pattern>%d{HH:mm:ss,SSS} %-5p [%c] - %m%n</pattern>
</encoder>
</appender>
<logger name="org.hibernate.SQL" level="DEBUG" />
<logger name="org.hibernate.type.descriptor.sql" level="TRACE" />
<root level="info">
<appender-ref ref="FILE" />
</root>
</configuration>
2.5 ตัวบันทึกสากลล่าสุด - SLF4J: Simple Logging Facade สำหรับ Java
อีกนานแค่ไหนกว่าจะหาค่าเฉลี่ยทองได้...
ในปี 2549 ผู้สร้างคนหนึ่งlog4j
ออกจากโครงการและตัดสินใจลองอีกครั้งเพื่อสร้างเครื่องบันทึกสากล แต่คราวนี้ไม่ใช่ตัวตัดไม้ใหม่ แต่เป็นมาตรฐานสากลใหม่ (wrapper) ที่อนุญาตให้คนตัดไม้ที่แตกต่างกันโต้ตอบกันได้
คน ตัดไม้นี้ถูกเรียกslf4j — Simple Logging Facade for Java
ว่า คนตัดไม้นี้แก้ปัญหาที่แท้จริง - การจัดการสวนสัตว์ของคนตัดไม้ ดังนั้นทุกคนจึงเริ่มใช้มันทันทีlog4j
JUL
common-loggins and logback
เราแก้ปัญหาที่เราสร้างขึ้นเองอย่างกล้าหาญ อย่างที่คุณเห็น ความคืบหน้ามาถึงจุดที่เราสร้างกระดาษห่อหุ้มไว้เหนือกระดาษห่อหุ้ม ...
ตัวห่อประกอบด้วยสองส่วน:
API
ซึ่งใช้ในแอปพลิเคชัน- การใช้งานที่เพิ่มเป็นการขึ้นต่อกันแยกต่างหากสำหรับตัวบันทึกแต่ละตัว
คุณสามารถเชื่อมต่อคนตัดไม้กับโครงการโดยใช้รหัส:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.17.2</version>
</dependency>
การเชื่อมต่อกับการใช้งานที่ถูกต้องก็เพียงพอแล้ว: โครงการทั้งหมดจะใช้งานได้
2.6 การเพิ่มประสิทธิภาพใน slf4j
Slf4j
รองรับคุณสมบัติใหม่ทั้งหมด เช่น การจัดรูป แบบสตริงสำหรับการบันทึก ก่อนหน้านี้มีปัญหาดังกล่าว สมมติว่าคุณต้องการพิมพ์ข้อความไปยังบันทึก:
log.debug("User " + user + " connected from " + request.getRemoteAddr());
มีปัญหากับรหัสนี้ สมมติว่าแอปพลิเคชันของคุณทำงานอยู่production
และไม่ได้เขียนใดๆ ลงในบันทึกDEBUG-messages
อย่างไรก็ตาม เมธอดlog.debug()
จะยังคงถูกเรียก และเมื่อถูกเรียกใช้ เมธอดต่อไปนี้จะถูกเรียกด้วย:
user.toString();
request.getRemoteAddr();
การเรียกใช้เมธอดเหล่านี้ทำให้แอปพลิเคชันช้าลง การโทรของพวกเขาจำเป็นในระหว่างการดีบักเท่านั้น แต่พวกเขาจะถูกเรียกอยู่ดี
จากมุมมองของลอจิก ปัญหานี้ต้องได้รับการแก้ไขในไลบรารีการบันทึกเอง และในเวอร์ชันแรกของ log4j วิธีแก้ปัญหาก็ปรากฏขึ้น:
if (log.isDebugEnabled()) {
log.debug("User " + user + " connected from " + request.getRemoteAddr());
}
แทนที่จะเขียนบันทึกหนึ่งบรรทัด ตอนนี้จำเป็นต้องเขียนสามบรรทัด ซึ่งทำให้ความสามารถในการอ่านโค้ดแย่ลงอย่างมาก และลดความนิยมของlog4j
.
คนตัดไม้slf4j
สามารถปรับปรุงสถานการณ์ได้เล็กน้อยโดยนำเสนอการบันทึกแบบอัจฉริยะ ดูเหมือนว่า:
log.debug("User {} connected from {}", user, request.getRemoteAddr());
โดยที่{}
แสดงถึงการแทรกอาร์กิวเมนต์ที่ส่งผ่านในเมธอด นั่นคือ อันแรก{}
ตรงกับผู้ใช้ อันที่สอง{}
ถึงrequest.getRemoteAddr()
พารามิเตอร์เหล่านี้จะเชื่อมต่อกันเป็นข้อความเดียวก็ต่อเมื่อระดับการบันทึกอนุญาตการบันทึก ไม่สมบูรณ์แบบ แต่ดีกว่าตัวเลือกอื่น ๆ ทั้งหมด
หลังจากนั้นSLF4J
ก็เริ่มได้รับความนิยมเพิ่มขึ้นอย่างรวดเร็ว ในขณะนี้เป็นทางออกที่ดีที่สุด
slf4j-log4j12
ดังนั้น เราจะพิจารณา การบันทึกโดยใช้ตัวอย่างของบันเดิล
GO TO FULL VERSION