คำนำ
เมื่อขนาดโครงการมีขนาดใหญ่ขึ้นและใหญ่ขึ้นโมดูลใหม่จะถูกนำมาใช้อย่างต่อเนื่อง โมดูลที่แตกต่างกันจะพิมพ์บันทึกของตัวเองซึ่งในที่สุดจะนำไปสู่บันทึกที่ไม่สามารถดูได้ ตัวอย่างเช่นในโครงการของฉันเองบันทึกต่อไปนี้มีอยู่:
ในหมู่พวกเขาจำนวนข้อมูลบันทึกของบันทึกข้อความและเธรดพื้นหลังมีขนาดใหญ่มาก หากบันทึกทั้งหมดถูกพิมพ์ในไฟล์เดียวและใช้ไฟล์ tail -f log.log คุณจะพบว่าบันทึกการเลื่อนอย่างรวดเร็วและคุณไม่สามารถดูหรือค้นหา SQL หรือบันทึกการเข้าถึงบริการเฉพาะ
วิธีแก้ปัญหาคือการจำแนกและส่งออกบันทึกที่แตกต่างกันเพื่อให้บันทึกซึ่งกันและกันไม่ส่งผลต่อกันและกัน การเข้าถึงบันทึกโดยอินเทอร์เฟซที่สำคัญเป็นพิเศษสามารถค้นหาและแก้ไขปัญหาได้อย่างง่ายดาย
ขั้นตอนที่ 1: กำหนดค่าใน log4j.properties
ก่อนโพสต์การกำหนดค่า log4j.properties ทั้งหมดของฉันเอง:
log4j.rootlogger = ข้อมูล, คอนโซล, ไฟล์ log4j.appender.console = net.czt.log.asyncconsoleapenderlog4j.appender.console.layout = org.apache.log4j.patternlayoutlog4j.appender.console.layaUt %-17c {2} (%13f:%l)%x {user_id} |%x {user_ip} |%x {server_address} |%x {server_name} |%x {request_uri} |%x {session_id} - %m %nlog4j.appender.console.buffersize = 10log4j.appender.console.encoding = UTF-8 log4j.appender.file = org.apache.log4j.rollingFileAppenderLog4j.appender.file.file =/home/work/apache-tomcat-6.0.39/logs/crazyant.loglog4j.appender.file.maxb ackupIndex = 5log4j.appender.file.MaxFilesize = 1GBLOG4J.Appender.file.layout = org.apache.log4j.patternlayoutlog4j.appender.file.layout.conversionpattern = [-5p] Crazyant-Web%d {yyyy-mm-dd hh: mm: ss, sss}%x {user_id} |%x {user_ip} |%x {server_address} |%x {server_name} |%x {request_uri} |%x {session_id} วิธีการ:%l%n%m%nlog4j.appender.file.buffersize = 10000log4j.appender.file.encoding = UTF-8 log4j.logger.net.czt.crazyant.msg = debug messagelog4j.additivity.net.czt.crazyant.msg = falselog4j.appender.message = org.apache.log4j.rollingFilePenderlog4j.appender.message.file =/home/work/apache-tomcat- age.append = truelog4j.appender.message.maxFilesize = 1gblog4j.appender.message.maxbackupindex = 5log4j.appender.message.layout = org.apache.log4j.patternlayoutlog4j.appender.message hh: mm: ss} [%-5p] [%c {1}] [%t]-%m%nlog4j.appender.message.encoding = utf-8 log4j.logger.net.czt.czzyant.async.service = debug asynclog4j.additivity.net.czt.crazyant.async.service = falselog4j.appender.async = org.apache.log4j.rollingFilePenderLog4j.appender.async.file =/home/work/apache-tomcat-6.0.0.39 r.async.append = truelog4j.appender.async.maxfilesize = 1gblog4j.appender.async.maxbackupindex = 5log4j.appender.async.layout = org.apache.log4j.patternlayoutlog4j.apync. HH: MM: SS} [%-5P] [%C {1}] [%T]-%M%NLOG4J.Appender.async.encoding = UTF-8 log4j.logger.net.czt.orm.mybatis.sqlmonitormanager = debug sweetQllog4j.additivity.net.czt.orm.mybatis.sqlmonitormanager = falselog4j.logger.net.czt.transaction.interceptor.smartTransactionInterceptor = debug sweetQllog4j.additivity.net.czt.transaction.interceptor.SmartTransactionInterceptor = Falselog4j.appender.showsql = org.apache.log4j.rollingFilePenderlog4j.appender.showsql.file =/home/work/apache-tomcat- og4j.appender.showsql.append = truelog4j.appender.showsql.maxfilesize = 1gblog4j.appender.showsql.maxbackupindex = 5log4j .appender.showsql.layout = org.apache.log4j.patternlayoutlog4j.appender.showsql.layout.conversionPattern =%d {yyyy-mm-dd hh: mm: ss} [%-5p] [%c {1}] [%t]-%m%nlog4j.appender.showsql.encoding = utf-8 log4j.logger.net.czt.czzyant.service = debug servicelog4j.additivity.net.czt.crazyant.service = falselog4j.appender.service = org.apache.log4j.rollingFilePenderlog4j.appender.service.file =/home/work/apache-tomcat- rvice.append = truelog4j.appender.service.maxFilesize = 1gblog4j.appender.service.maxbackupindex = 5log4j.appender.service.layout = org.apache.log4j.patternlayoutlog4j.appender HH: MM: SS} [%-5P] [%C {1}] [%T]-%M%NLOG4J.Appender.Service.encoding = UTF-8ด้านล่างของไฟล์การกำหนดค่าคุณสามารถเห็นได้อย่างง่ายดายว่าข้อความเอาต์พุต I (ข้อความ), async (เธรดแบ็กเอนด์), showsQl (บันทึกฐานข้อมูล) และบริการ (การเรียกอินเตอร์เฟส) ไปยังไฟล์บันทึกที่แตกต่างกันตามลำดับ
คำอธิบายเหล่านี้บางส่วน:
log4j.rootLogger=INFO, console, file
log4j มีแนวคิดของ rootlogger และ logger สามัญ โดยค่าเริ่มต้นเราต้องใช้ Rootlogger เท่านั้นนั่นคือบันทึกทั้งหมดจะถูกส่งไปยังไฟล์บันทึกนี้เท่านั้น
ดูการกำหนดค่าของตัวบันทึกปกติ (ใช้บริการบันทึกอินเตอร์เฟสเป็นตัวอย่าง):
1. log4j.logger.net.czt.crazyant.service=DEBUG, service
" net.czt.crazyant.service " ในประโยคนี้หมายถึงเส้นทางเต็มของแพ็คเกจที่มีผลในการกำหนดค่าบันทึกบันทึกปกติ
บริการสีระบุชื่อของตัวบันทึกสามัญ
2. log4j.additivity.net.czt.crazyant.service=false
" net.czt.crazyant.service " ในนั้นเหมือนกับด้านบนซึ่งระบุแพ็คเกจที่กำหนดเป้าหมายโดยรายการการกำหนดค่า
ความหมายของการกำหนดค่าในประโยคนี้คือไม่ส่งออกบันทึกของแพ็คเกจไปยังบันทึก rootlogger แต่จะส่งออกไปยังบันทึกที่คุณกำหนดค่าเท่านั้น
3. log4j.appender.service=org.apache.log4j.RollingFileAppender และรายการการกำหนดค่าด้านล่างส่วนการกำหนดค่านี้
สตริง "บริการ" ที่นี่เหมือนกับ "บริการ" ของรายการการกำหนดค่าแรกด้านบนซึ่งระบุการกำหนดค่าของตัวบันทึกสามัญ
รายการการกำหนดค่าด้านล่างนั้นเหมือนกับ Rootlogger ซึ่งระบุไฟล์เอาต์พุตทุกวันการเข้ารหัส UTF8 กฎการจัดทำโหมดเอาต์พุตสำหรับแต่ละบรรทัด ฯลฯ
ปัญหาที่ฉันพบคือหลังจากที่ log4j.properties ด้านบนได้รับการกำหนดค่าฉันพบว่าแต่ละไฟล์บันทึกถูกสร้างขึ้น แต่ไม่มีเนื้อหาอยู่ในนั้น ทำไมถึงเป็นเช่นนี้? มาดูสิ่งที่สองที่คุณใส่ใจด้านล่าง
ขั้นตอนที่ 2: เมื่อส่งออกบันทึกคุณต้องตั้งค่าคลาสเฉพาะที่สอดคล้องกับวัตถุบันทึก
หมายความว่าอย่างไร? ในรายการการกำหนดค่าข้างต้นมีสตริงแพ็คเกจ " net.czt.crazyant.service " ลองคิดดูด้วยตัวเอง Log4J เอาต์พุตบันทึกการบันทึกในแพ็คเกจต่าง ๆ ไปยังไฟล์ต่าง ๆ อย่างไร คิดเกี่ยวกับมันมีสองวิธี:
1. ใช้วิธี intercepter หรือ AOP, log4j ตรวจจับเอาต์พุตบันทึกด้วยตัวเอง เมื่อตรวจพบแพ็คเกจที่สร้างบันทึกจะถูกส่งออกไปยังไฟล์ที่เกี่ยวข้อง
2. ผู้ใช้ผ่านพารามิเตอร์คลาส Log4j ได้รับแพ็คเกจที่สอดคล้องกันของคลาสและใช้สิ่งนี้เป็นพื้นฐานในการค้นหาไฟล์บันทึกที่แตกต่างกัน
เมื่อดูที่รหัสเป็นที่ชัดเจนว่า log4j ใช้วิธีการง่ายและโดยตรงหลัง:
นำเข้า org.apache.commons.logging.log; นำเข้า org.apache.commons.logging.logfactory; คลาสสาธารณะ MyClassimpl ใช้ myclass { / ** * loger * / logger logger สุดท้ายคงที่ = logfactory.getLog (myclassimpl.class); / ** * func */ สาธารณะโมฆะ myfunc () {logger.info ("วิธีการโทร myfunc."); - ใน logger = LogFactory.getLog(MyClassImpl.class) พารามิเตอร์คลาสโดยใช้ตัวบันทึกจะถูกส่งผ่านและที่อยู่แพ็คเกจที่คลาสสะท้อนให้เห็นคือที่อยู่แพ็คเกจที่ใช้โดย log4j เพื่อส่งออกบันทึก
วิธีการนี้ยังมีคุณสมบัติที่ทรงพลังซึ่งอำนวยความสะดวกในการจำแนกบันทึกลอจิคัล ตัวอย่างเช่นรหัสจำนวนมากไม่ได้อยู่ในแพ็คเกจ แต่พวกเขาอยู่ด้วยกันอย่างมีเหตุผล ตัวอย่างเช่นการประมวลผลข้อความไม่ได้เป็นเพียงแค่อินเทอร์เฟซที่เรียกแพ็คเกจบริการ แต่ยังอาจเรียกการทำงานของการส่งผงชูรส หากคุณต้องการส่งออกบันทึกบางอย่างในแพ็คเกจผงชูรสไปยังบริการจากนั้นเมื่อเครื่องบันทึกผงชูรสเริ่มต้นการเริ่มต้นคลาสบริการจะผ่านไป
หรือสำหรับบันทึกทั้งหมดของคลาสที่แน่นอนวัตถุ Logger ทั้งหมดของพวกเขาทั้งหมดสามารถมาจากอินสแตนซ์วัตถุที่ห่อหุ้มตัวเดียวและมีพารามิเตอร์เดียวที่ส่งผ่านในอินสแตนซ์วัตถุเดียวนี้ซึ่งสามารถใช้เพื่อระบุการจำแนกแบบลอจิคัลนี้
สรุป
ใน Log4j.properties ให้รองรับเอาต์พุตแยกต่างหากของบันทึกของแพ็คเกจหรือคลาสเฉพาะได้รับการสนับสนุน แต่ก็ต้องการให้การเริ่มต้นของ Logger ในรหัสสามารถสอดคล้องกับแพ็คเกจในการกำหนดค่าบันทึก
โอเคข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่าเนื้อหาของบทความนี้จะช่วยในการศึกษาหรือทำงานของทุกคน หากคุณมีคำถามใด ๆ คุณสามารถฝากข้อความไว้เพื่อสื่อสาร