1.1 บทนำ
มันน่าอายที่จะพูด เมื่อเร็ว ๆ นี้ บริษัท ถูกส่งไปยัง บริษัท ลูกค้าเพื่อสัมภาษณ์ตำแหน่งการพัฒนา เดิมทีฉันได้เตรียมคำถามสัมภาษณ์ที่เกี่ยวข้องสำหรับ Redis, RabbitMQ, SSM Frameworks และบทวิจารณ์โครงการบางอย่างที่ฉันทำ ฉันไปสัมภาษณ์ด้วยความมั่นใจ เป็นผลให้มีคนถามว่าระบบบันทึกที่ใช้ในโครงการล่าสุดคืออะไรทันทีที่ฉันขึ้นมา? ระดับการบันทึกได้รับการกำหนดค่าอย่างไร? ฉันสับสนในเวลานั้น ฉันมักจะดูแลโดยผู้จัดการโครงการ ฉันเพิ่งค้นหาอินเทอร์เน็ตและวางมันและมันก็โอเค หลังจากพูดจบผู้สัมภาษณ์ก็ทำให้ฉันดูลึกซึ้ง ในเวลานั้นฉันรู้สึกละอาย ...
1.2 บอกฉันน้อยลงเกี่ยวกับการนินทาและบอกเล่าเรื่องราวของการพัฒนาบันทึก (ถ้าคุณรู้อยู่แล้วคุณสามารถข้ามมันและดูการกำหนดค่าบันทึก 1.3)
เพื่อให้มีความเข้าใจในเชิงลึกเกี่ยวกับการใช้เทคโนโลยีบันทึกฉันแนะนำให้อ่าน: logback + SLF4J เป็นการส่วนตัว สำหรับการกำหนดค่าบันทึกจะดีกว่าที่จะเข้าใจ log4j เนื่องจากโครงการส่วนใหญ่ใช้ log4j ในปัจจุบัน โอเคเริ่มต้นด้วยเรื่องราวการพัฒนาของบันทึก:
ในปี 1999 ชุมชน Apache Open Source เปิดตัว Log4J ซึ่งทำให้เกิดความรู้สึกในโลกของโปรแกรมทั้งหมด ตั้งแต่นั้นมามันได้กลายเป็นมาตรฐานสำหรับการบันทึกและถูกใช้อย่างกว้างขวางโดยโปรแกรมเมอร์ Java ต่อมาซันยังปล่อยกลไกการบันทึก (java.util.logging ต่อไปนี้จะเรียกว่า Jul) ใน JDK เวอร์ชัน 1.4 แต่กลไกไม่ได้รับการยอมรับจากสาธารณชนซึ่งน่าสมเพชจริงๆ ในไม่ช้า Apache ได้เปิดตัวกรอบบันทึกการบันทึกคอมมอนส์ (ซึ่งช่วยให้นักพัฒนาสามารถใช้วิธีการใช้งานบันทึกเชิงนามธรรมโดยไม่ต้องใส่ใจกับเทคโนโลยีบันทึกที่ใช้ในเงื่อนไขของคนธรรมดาคุณต้องการโทรหา Didi บนโทรศัพท์มือถือของคุณหากคุณอยู่ในปักกิ่ง เฟรมเวิร์กนี้ดูเหมือนจะเป็นการดูหมิ่นดวงอาทิตย์ สามารถค้นหาและโทรไปที่เทคโนโลยีบันทึกในสภาพแวดล้อมปัจจุบันสำหรับเอาต์พุตบันทึก เฟรมเวิร์กบันทึกสามารถรองรับ log4j หรือ ก.ค. Commons-Logging+Log4j กลายเป็นการผสมผสานแบบคลาสสิกของบันทึก Java เป็นเวลานานหลังจากนั้น อย่างไรก็ตามการบันทึกคอมมอนส์ยังไม่ได้รับการอัปเดตในขณะที่ ฉันสงสัยว่าการออกแบบการบันทึกคอมมอนส์ไม่ดีพอและมันก็ยากกว่าที่จะปรับให้เหมาะสม ทำไมคุณถึงพูดแบบนั้น? เนื่องจากกรอบการบันทึกที่ยอดเยี่ยมครั้งต่อไป SLF4J เกิดผู้เขียน (Ceki Gülcü) เป็นหนึ่งในผู้เขียนของ Log4J SLF4J ของเขามีความสง่างามมากขึ้นในการออกแบบและเขายังใช้เทคโนโลยี logback ซึ่งเป็นสิ่งที่ทันสมัยกว่า log4j เมื่อมาถึงจุดนี้สถานการณ์ที่ระบบบันทึกถูกครอบงำโดยคอมมอนส์-ล็อก+log4j ได้เริ่มสั่นคลอนและมีการบันทึกคอมมอนส์+log4j หลากหลาย? slf4j+log4j? SLF4J+logback? การรวมกันเป็นเรื่องที่ทำให้ปวดใจจริงๆ สิ่งที่น่ากลัวยิ่งกว่านั้นคือ Ceki Gülcü Boss ช่วยเพิ่มประสิทธิภาพ log4j และตั้งแต่นั้นมามีเทคโนโลยีการบันทึกอีกอย่างหนึ่งในโลก - log4j2 นี่จะเรียนรู้จาก Tencent เพื่อทำ WeChat และ QQ หรือไม่? มันเป็น 666 จริง ๆ ดังนั้นหากคุณต้องการมีความเข้าใจอย่างลึกซึ้งเกี่ยวกับเทคโนโลยีการบันทึกคุณสามารถค้นหาข้อมูลที่เกี่ยวข้องเกี่ยวกับ logback + SLF4J สำหรับไฟล์การกำหนดค่าฉันคิดว่าคุณสามารถเข้าใจคำอธิบายโดยละเอียดของการกำหนดค่า log4j ที่ฉันเขียนด้านล่าง ท้ายที่สุดตอนนี้ บริษัท หลายแห่งใช้เฟรมเวิร์ก Log4J
1.3 ไปที่หัวข้อการกำหนดค่าบันทึกพื้นฐาน
1. สร้างไฟล์ log4j.properties ใหม่ภายใต้ classpath หรือแพ็คเกจทรัพยากร (โครงการ Maven) พารามิเตอร์ต่อไปนี้เพียงพอสำหรับการกำหนดค่าโครงการเริ่มต้น สำหรับการกำหนดค่าโดยละเอียดเพิ่มเติม
ดำเนินการต่อเพื่อดูการกำหนดค่าระดับบันทึก 1.4 log4j;
#specify ระดับบันทึกและแหล่งเอาท์พุทผ่านรูทตัวบันทึก#ลำดับความสำคัญของเอาต์พุตบันทึก: การดีบัก <info <warn <ข้อผิดพลาด <fatal#กำหนดระดับบันทึก (ข้อมูล) ของบันทึกรูทและนามแฝงของแหล่งเอาต์พุต (คอนโซล, myFile)# log4j.rootlogger = ข้อมูล, คอนโซล, myFile ###### การกำหนดค่าการใช้งานเฉพาะของคอนโซลแหล่งที่มาเป็นคอนโซลเอาท์พุท ########### นิติยางการกำหนดแหล่งที่มา log4j.appender.console = org.apache.log4j.consoleAppender #ตัวแปลงรูปแบบสำหรับการระบุรูปแบบเอาต์พุตบันทึกคือคลาสการใช้งานรูปแบบการใช้งาน log4j.appender.console.layout = org.apache.log4j.patternlayout #define รูปแบบเฉพาะ %-5p [%c.%m ()] -%m%n ####### การกำหนดค่าแหล่งเอาต์พุต myfile การใช้งานเฉพาะเป็นไฟล์เอาต์พุต ########### นิติยางแหล่งที่มา log4j.appender.myfile = org.apache.log4j.rollingFileAppender#กำหนดเส้นทางการจัดเก็บของไฟล์บันทึก log4j.appender.myfile.file = src/log/logproperties/log4j.log#กำหนดขนาดของไฟล์บันทึก (คำนวณ 1 จาก 0 นั่นคือมากถึง 3 ไฟล์ที่นี่) #absent ขนาดนี้ไฟล์ที่สร้างขึ้นก่อนจะถูกเขียนทับ log4j.appender.myfile.maxbackupIndex = 2#ระบุรูปแบบของเอาต์พุตบันทึกไปยังคลาสการใช้งานรูปแบบการใช้งาน log4j.appender.console.layout.conversionPattern =%d%-5p [%c.%m ()] -%m%n ######### รูปแบบเอาต์พุตคำอธิบาย ########%d: จุดเวลาสำหรับการพิมพ์บันทึกรูปแบบเริ่มต้นคือ ISO8601 #definition มีดังนี้:%d {yyy ปี mm เดือน dd วัน hh ชั่วโมงมม. นาที ss วินาที sss} และเอาท์พุทจะเป็น: #january 6, 2018 14: 47: 45: 590 #%p: ระดับการส่งออก "-" เครื่องหมายอยู่ทางขวา) คุณสามารถเรียนรู้ได้จากหนึ่งตัวอย่าง #%c: ชื่อเต็มของคลาสที่บันทึกอยู่ที่ #%m: ชื่อของวิธีการที่บันทึกอยู่ที่ #%m: ข้อมูลบันทึก #%n: เอาท์พุทบรรทัดส่งคืนสายการบิน #%l: หมายเลขบรรทัดเอาต์พุตในรหัสรหัสในรหัส2. บันทึกการโทรไปยังผลการทดสอบการกำหนดค่า
นำเข้า org.apache.log4j.logManager; นำเข้า org.apache.log4j.logger; นำเข้า org.apache.log4j.propertyconfigurator; คลาสสาธารณะ logpropertiestest {public Static Main (String [] args) { /* log4jpath = system.getProperty ("user.dir")+"// src // log // logproperties // log4j.properties"; PropertyConfigurator.configure (log4jpath);*/ logger log = logManager.getLogger (logProperTiestest.class); log.debug ("debug"); log.info ("ข้อมูล"); log.warn ("คำเตือน"); log.error ("ข้อผิดพลาด"); log.fatal ("ข้อผิดพลาดร้ายแรง"); -1.4 การกำหนดค่าระดับบันทึก
การกำหนดค่าระดับบันทึกสามารถแบ่งออกเป็นสามหมวดหมู่ การกำหนดค่าข้างต้นคือการกำหนดค่าระดับการบันทึกของตัวบันทึกหลักหมวดหมู่ที่สองคือการกำหนดค่าระดับบันทึกของตัวบันทึกชั้นย่อยและหมวดที่สามคือการกำหนดค่าระดับบันทึกของแหล่งที่มา (คอนโซลไฟล์ ฯลฯ ) ลำดับความสำคัญของการแยกวิเคราะห์ระดับบันทึกของพวกเขาถูกจัดเรียงจากต่ำถึงสูง ฉันขอโทษที่ไม่ได้อธิบายคำสั่งเฉพาะอย่างชัดเจน ฉันควรจะเข้าใจกรณีโดยตรง!
1. หากระดับการบันทึกของตัวบันทึกหลัก (rootlogger) (สมมติว่าเป็นระดับข้อมูล) ระดับบันทึกของตัวบันทึก subclass จะไม่ถูกกำหนดค่าและระดับบันทึกของแหล่งที่มาของเอาต์พุตไม่ได้รับการกำหนดค่าแหล่งเอาต์พุตสามารถส่งออกระดับข้อมูลหรือสูงกว่าเท่านั้น
2. หากระดับการบันทึกของตัวบันทึกหลัก (rootlogger) (สมมติว่าเป็นระดับข้อมูล) ระดับบันทึกของตัวบันทึกย่อยย่อย (สมมติว่าเป็นระดับการดีบัก) และระดับบันทึกของแหล่งที่มาไม่ได้รับการกำหนดค่า
3. หากระดับการบันทึกของตัวบันทึกหลัก (rootlogger) (สมมติว่าเป็นระดับข้อมูล) ระดับบันทึกของเครื่องบันทึก subclass (สมมติว่าเป็นระดับการดีบัก) และระดับการบันทึกของแหล่งเอาท์พุท (สมมติว่าเป็นระดับข้อมูล)
4. หากระดับการบันทึกของตัวบันทึกหลัก (rootlogger) (สมมติว่าเป็นระดับข้อมูล) ระดับบันทึกของตัวบันทึกย่อยจะไม่ได้รับการกำหนดค่าและระดับบันทึกของตัวบันทึก subclass ถูกกำหนดค่า
ระดับบันทึกของแหล่งที่มา (สมมติว่าเป็นระดับการดีบัก) จากนั้นแหล่งข้อมูลเอาต์พุตเอาต์พุตระดับข้อมูลหรือสูงกว่า;
ดังนั้นจากกรณีข้างต้นเราสามารถรู้ได้ว่ามี 2 ความสัมพันธ์เชิงตรรกะระหว่างตัวบันทึกและระดับบันทึกเอาต์พุตแหล่งเอาต์พุต:
1. หากแหล่งเอาท์พุทไม่ได้กำหนดระดับบันทึกมันจะสืบทอดระดับบันทึกที่ใกล้เคียงที่สุดกับตัวบันทึก subclass; หากตัวบันทึก subclass ไม่ได้กำหนดระดับบันทึกมันจะสืบทอดตัวบันทึกหลักที่ใกล้เคียงกับตัวบันทึกหลักมากที่สุด
2. เมื่อพิมพ์บันทึกแหล่งเอาต์พุตจะเปรียบเทียบกับระดับบันทึกที่กำหนดโดยเครื่องบันทึก subclass ที่ใกล้เคียงที่สุด หากระดับที่กำหนดโดยแหล่งเอาท์พุทสูงกว่าตัวบันทึก subclass บันทึกจะเป็นเอาต์พุตตามระดับบันทึกที่กำหนดโดยแหล่งเอาต์พุตและในทางกลับกัน
ดังนั้นในโครงการคุณสามารถกำหนดค่าระดับบันทึกตามวิธีการกำหนดค่ารายวัน:
#Control ระดับบันทึกของตัวบันทึกหลักคือข้อมูล โดยค่าเริ่มต้นจะมีการบันทึกเหนือระดับข้อมูลเท่านั้นที่จะส่งออกภายใต้โมดูลทั้งหมด log4j.rootlogger = ข้อมูลคอนโซล#คอนโซล#ควบคุมระดับบันทึกของโมดูลแยกต่างหากเป็นข้อผิดพลาดและบันทึกจะถูกส่งออกเฉพาะเมื่อข้อยกเว้นเกิดขึ้น log4j.logger.log.logproperties.logpropertiestest = debug ######################################################################################################### - - - #specify ระดับบันทึกของแหล่งเอาต์พุตปัจจุบัน ด้วยการกำหนดค่าก่อนหน้านี้คุณไม่จำเป็นต้องกำหนดค่ารายการนี้ #log4j.appender.console.threshold = ข้อมูล #ระบุรูปแบบของเอาต์พุตบันทึก: รูปแบบที่ยืดหยุ่น log4j.appender.console.layout = org.apache.log4j.patternlayout #content [%c.%m ()] -%m%n
1.5 บทสรุป
ณ จุดนี้ฉันเชื่อว่าคุณมีความเข้าใจพื้นฐานเกี่ยวกับการกำหนดค่าบันทึก มีหลายสิ่งหลายอย่างในบทความที่อาจผิดและฮีโร่ทุกคนยินดีที่จะชี้ให้พวกเขาเห็น ฉันเขียนบทความเพื่อสรุปเพื่อให้สามารถเข้าใจการกำหนดค่าของเทคโนโลยีนี้อย่างลึกซึ้งเพื่อที่ฉันจะได้มีความเข้าใจที่ลึกซึ้งยิ่งขึ้น