slf4j 记录日志文件_教程:正确的SLF4J日志记录用法以及如何检查它
slf4j 記錄日志文件
SLF4J是一個非常流行的日志記錄外觀,但是,就像我們使用的所有庫一樣,我們有可能以錯誤的方式或至少以一種非最佳方式使用它。
在本教程中,我們將列出常見的日志記錄錯誤以及如何使用FindBugs檢測到它們。 我們還將在相關時提及PMD和Sonar Squid檢查。
我們將使用兩個外部FindBugs插件,它們將日志記錄檢測器添加到FindBugs。
第一個是Kengo Toda的SLF4J only插件 ,其中僅包含SLF4J檢測器。
第二個插件是流行的FB Contrib ,其中包含許多測井儀。
有關如何使用FindBugs插件的信息,請參閱以下文章:
- [Maven]( https://gualtierotesta.wordpress.com/2015/06/14/tutorial-using-findbugs-with-maven/ )
- [NetBeans]( https://gualtierotesta.wordpress.com/2015/06/07/findbugs-plugins/ )
注意:在所有示例中,我們將假定以下導入:
import org.slf4j.Logger; import org.slf4j.LoggerFactory;1.記錄儀定義
錯誤的方法:
W1a. Logger log = LoggerFactory.getLogger(MyClass.class); W1b. private Logger logger = LoggerFactory.getLogger(MyClass.class); W1c. static Logger LOGGER = LoggerFactory.getLogger(AnotherClass.class);正確方法:
C1a. private static final Logger LOGGER = LoggerFactory.getLogger(MyClass.class); C1b. private final Logger logger = LoggerFactory.getLogger(getClass());一般規則 :記錄器應該是最終的且私有的,因為沒有理由與其他課程共享或重新分配記錄器。
相反,對于記錄器是否應該是靜態的,并沒有普遍的共識。 SLF4J插件支持非靜態版本(C1b),而PMD(“ LoggerIsNotStaticFinal”規則)和Sonar(魷魚規則S1312)更喜歡靜態記錄器(C1a),因此這兩個選項均應視為有效。
附加信息:
- [SLF4J常見問題解答]( http://slf4j.org/faq.html#declared_static )
- [Apache Commons靜態日志]( http://wiki.apache.org/commons/Logging/StaticLog )。
請注意:
- 在靜態版本(C1a)中,記錄器名稱通常使用大寫字母作為所有常量字段。 否則,PMD將報告“ VariableNamingConventions”違規行為。
- 在這兩種情況下,建議的名稱都是“ logger / LOGGER”而不是“ log / LOG”,因為某些命名約定會避免使用太短的名稱(少于四個字符)。 而且log是動詞,更適合于方法名。
- W1c是錯誤的,因為我們指的是一個類(AnotherClass),它不是定義記錄器的類。 在99%的情況下,這是由于從一類復制到另一類而導致的。
相關的FindBugs(SLF4J插件)檢查:
- SLF4J_LOGGER_SHOULD_BE_PRIVATE
- SLF4J_LOGGER_SHOULD_BE_NON_STATIC
- SLF4J_LOGGER_SHOULD_BE_FINAL
- SLF4J_ILLEGAL_PASSED_CLASS
2.格式字符串
錯誤的方法:
W2a. LOGGER.info("Obj=" + myObj); W2b. LOGGER.info(String.format(“Obj=%s”, myObj));正確方法:
C2. LOGGER.info("Obj={}",myObj);一般規則 :格式字符串(第一個參數)應為常量,沒有任何字符串串聯。 動態內容(示例中的myObj值)應使用占位符(“ {}”)添加。
動機很簡單:無論是否記錄消息,我們都應在記錄器建立后延遲記錄消息的創建,具體取決于當前的記錄級別。 如果我們使用字符串連接,則無論采用哪種日志記錄級別,都會以任何方式構建消息,這會浪費CPU和內存資源。
相關的FindBugs(SLF4J插件)檢查:
- SLF4J_FORMAT_SHOULD_BE_CONST格式應為常數
- SLF4J_SIGN_ONLY_FORMAT格式字符串不應僅包含占位符
相關的FindBugs(FB Contrib插件)檢查:
- LO_APPENDED_STRING_IN_FORMAT_STRING方法將串聯的字符串傳遞給SLF4J的格式字符串
3.占位符參數
錯誤的方法:
W3a. LOGGER.info("Obj={}",myObj.getSomeBigField()); W3b. LOGGER.info("Obj={}",myObj.toString()); W3c. LOGGER.info("Obj={}",myObj, anotherObj); W3d. LOGGER.info("Obj={} another={}",myObj);正確方法:
C3a. LOGGER.info("Obj={}",myObj); C3b. LOGGER.info("Obj={}",myObj.log());一般規則 :占位符應該是對象(C3a),而不是方法返回值(W3a),以便在記錄級別分析后推遲對其求值(請參見上一段)。 在W3a示例中,無論日志記錄級別如何,都會始終調用方法getSomeBigField()。 出于同樣的原因,我們應該避免在語義上與C3a等效的W3b,但是它總是在toString()方法調用中產生。
解決方案W3c和W3d是錯誤的,因為格式字符串中的占位符數量與占位符參數數量不匹配。
解決方案C3b可能在某種程度上具有誤導性,因為它包含方法調用,但是每當myObj包含多個字段(例如,它是一個大型JPA實體)但我們不想記錄其所有內容時,它就很有用。
例如,讓我們考慮以下類:
public class Person { private String id; private String name; private String fullName; private Date birthDate; private Object address; private Map<String, String> attributes; private List phoneNumbers;它的toString()方法很可能會包含所有字段。 使用解決方案C3a,所有它們的值都將打印在日志文件中。
如果不需要所有這些數據,則定義如下的幫助方法將很有用:
public String log() { return String.format("Person: id=%s name=%s", this.id, this.name); }僅打印相關信息。 此解決方案的CPU和內存也比toString()輕。
有什么關系? 它取決于應用程序和對象類型。 對于JPA實體,我通常在log()方法中包括ID字段(以便在需要所有列數據時讓我在數據庫中找到記錄),并且可能是一個或兩個重要字段。
毫無疑問,應該記錄密碼字段和/或敏感信息(電話號碼,...)。 這是不使用toString()登錄的另一個原因。
相關的FindBugs(SLF4J插件)檢查:
- SLF4J_PLACE_HOLDER_MISMATCH
4.調試消息
重要提示:規則4(請參閱5條規則文章 )指導我們使用受保護的調試日志記錄
if (LOGGER.isDebugEnabled()) { LOGGER.debug(“Obj={}”, myObj); }使用SLF4J,如果占位符參數是對象引用(請參閱解決方案C3a / C3b),則可以使用if來避免代碼混亂。
因此,使用以下內容是安全的:
LOGGER.debug(“Obj={}”, myObj);5.例外
適當的異常日志記錄是問題分析的重要支持,但很容易忽略它的用處。
錯誤的方法:
W5a. catch (SomeException ex) { LOGGER.error(ex);}.. W5b. catch (SomeException ex) { LOGGER.error("Error:" + ex.getMessage());}..正確方法:
C5. catch (SomeException ex) { LOGGER.error("Read operation failed: id={}", idRecord, ex);}..`一般規則 :
C5示例告訴我們,我們正在嘗試讀取具有特定ID的記錄,該ID的值已與消息一起寫入了日志。
請注意,C5在格式字符串中使用一個占位符,但是有兩個附加參數。 這不是錯誤,而是一種特殊的模式,SLF4J將其識別為異常記錄案例:最后一個參數(在C5示例中為ex)被SLF4J視為Throwable(異常),因此不應將其包含在格式字符串中。
相關的FindBugs(SLF4J插件)檢查:
- SLF4J_MANUALLY_PROVIDED_MESSAGE:消息不應基于異常getMessage()
翻譯自: https://www.javacodegeeks.com/2016/02/tutorial-correct-slf4j-logging-usage-check.html
slf4j 記錄日志文件
總結
以上是生活随笔為你收集整理的slf4j 记录日志文件_教程:正确的SLF4J日志记录用法以及如何检查它的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 还能实时了解电脑配置还能实时了解电脑配置
- 下一篇: 英特尔首次展示 14 代酷睿 Rapto