slf4j: วิธีบันทึกข้อความที่จัดรูปแบบ, อาร์เรย์วัตถุ, ข้อยกเว้น


275

วิธีการที่ถูกต้องในการบันทึกข้อความที่มีประชากรและการติดตามสแต็กของข้อยกเว้นคืออะไร?

logger.error(
    "\ncontext info one two three: {} {} {}\n",
    new Object[] {"1", "2", "3"},
    new Exception("something went wrong"));

ฉันต้องการที่จะผลิตผลลัพธ์ที่คล้ายกับนี้:

context info one two three: 1 2 3
java.lang.Exception: something went wrong
stacktrace 0
stacktrace 1
stacktrace ...

slf4j เวอร์ชั่น 1.6.1


3
ฉันไม่เข้าใจว่าทำไม slf4j ใช้ไวยากรณ์สตริงรูปแบบของตัวเองแทนที่จะเป็นสไตล์มาตรฐาน% s น่ารำคาญ
Keith Tyler

@ KeithTyler ฉันชอบ{}มากขึ้นเรื่องของการลิ้มรส ...
Betlista

@KeithTyler toString()วิธีการโต้แย้งอาจมีราคาแพง ด้วยไวยากรณ์นี้จะมีการส่งการอ้างอิงไปยังแต่ละวัตถุเท่านั้นและtoString()วิธีการนั้นจะถูกเรียกก็ต่อเมื่อข้อความนั้นได้รับการบันทึกอย่างแท้จริง วัตถุที่อ้างอิงในการinfo()เรียกบันทึกจะไม่มีtoString()วิธีการของพวกเขาเรียกว่าถ้าระดับการบันทึกเป็นWARNหรือสูงกว่า {}ไวยากรณ์การแจ้งเตือนไปยังผู้ใช้ที่นี้ไม่ได้เป็นString.format()การดำเนินงานเหมือนเช่นที่พวกเขาควรจะผ่านวัตถุมากกว่าการแสดงสตริงดังกล่าว
user149408

คำตอบ:


427

ในฐานะของ SLF4J 1.6.0 ต่อหน้าหลายพารามิเตอร์และหากอาร์กิวเมนต์สุดท้ายในคำสั่งการบันทึกเป็นข้อยกเว้น SLF4J จะสันนิษฐานว่าผู้ใช้ต้องการให้อาร์กิวเมนต์สุดท้ายเป็นข้อยกเว้นไม่ใช่พารามิเตอร์ง่ายๆ เห็นแล้วยังรายการคำถามที่พบบ่อยที่เกี่ยวข้อง

ดังนั้นการเขียน (ใน SLF4J เวอร์ชั่น 1.7.x และใหม่กว่า)

 logger.error("one two three: {} {} {}", "a", "b", 
              "c", new Exception("something went wrong"));

หรือการเขียน (ใน SLF4J เวอร์ชั่น 1.6.x)

 logger.error("one two three: {} {} {}", new Object[] {"a", "b", 
              "c", new Exception("something went wrong")});

จะให้ผลผลิต

one two three: a b c
java.lang.Exception: something went wrong
    at Example.main(Example.java:13)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at ...

เอาต์พุตที่แน่นอนจะขึ้นอยู่กับเฟรมเวิร์กพื้นฐาน (เช่น logback, log4j, ฯลฯ ) รวมถึงวิธีการกำหนดค่าเฟรมเวิร์กพื้นฐาน อย่างไรก็ตามหากพารามิเตอร์สุดท้ายเป็นข้อยกเว้นก็จะถูกตีความเช่นนั้นโดยไม่คำนึงถึงกรอบงานพื้นฐาน


4
คุณกำลังใช้เฟรมเวิร์กการบันทึกข้อมูลพื้นฐานใดอยู่ ตามที่กล่าวไว้ในคำตอบของฉันข้างต้นหากพารามิเตอร์สุดท้ายเป็นข้อยกเว้นมันจะถูกตีความเช่นนั้นโดยไม่คำนึงถึงกรอบพื้นฐาน (ทดสอบด้วย logback, slf4j-log4j12, slf4j-jdk14 และ slf4j-simple.)
Ceki

3
ขออภัยฉันไม่รู้จักว่าในตัวอย่างของคุณคุณใช้ตัวยึด n = 3 ในสตริงรูปแบบและองค์ประกอบ n + 1 = 4 ในอาร์เรย์วัตถุ ฉันมีตัวยึดตำแหน่ง n ในสตริงรูปแบบและองค์ประกอบ n ในอาร์เรย์วัตถุบวกด้วยข้อยกเว้นเป็นพารามิเตอร์ที่สาม ความคาดหวังของฉันคือการยกเว้นจะถูกพิมพ์ด้วย stacktrace แต่สิ่งนี้ไม่เคยเกิดขึ้น ใช้งานได้ตามที่ออกแบบไว้หรือไม่ นอกจากนี้ถ้าฉันมีตัวยึดตำแหน่ง n และองค์ประกอบในวัตถุอาร์เรย์ยกเว้นเป็นองค์ประกอบสุดท้ายที่ฉันไม่เห็น stacktrace ใด ๆ บางทีตัวยึดตำแหน่ง n ที่มีวัตถุ n + 1 ในอาเรย์ควรให้ความสำคัญมากกว่านี้
rowe

7
ฉันจะให้ @Ceki ช่วงเวลาที่ยากลำบากเกี่ยวกับเรื่องนี้ไม่ได้อยู่ใน Javadocs แต่อยู่ที่ชั้นบนสุดของLoggerคลาส javadoc: slf4j.org/apidocs/org/slf4j/Logger.html
Adam Gent

1
ฉันสร้างคำขอการปรับปรุงคุณสามารถลงคะแนนถ้าคุณชอบมัน
Betlista

8

นอกจากคำตอบของ @Ceki หากคุณใช้ logback และตั้งค่าไฟล์ config ในโครงการของคุณ (โดยปกติคือ logback.xml) คุณสามารถกำหนดล็อกเพื่อวางแผนการติดตามสแต็กได้เช่นกันโดยใช้

<encoder>
    <pattern>%date |%-5level| [%thread] [%file:%line] - %msg%n%ex{full}</pattern> 
</encoder>

% ex ในรูปแบบคือสิ่งที่สร้างความแตกต่าง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.