從問題出發學習slf4j、logback原始碼系列-佔位符「」

問題:log。error(“error has happen, param:{}, error:{}”, “param”, e)還是log。error(“error has happen, param:{}, error:”, “param”, e);

我們用第一種方式除錯一遍;

從問題出發學習slf4j、logback原始碼系列-佔位符「」

按F7進入ch/qos/logback/classic/Logger。java

從問題出發學習slf4j、logback原始碼系列-佔位符「」

往下進入buildLoggingEventAndAppend方法構建,

從問題出發學習slf4j、logback原始碼系列-佔位符「」

從問題出發學習slf4j、logback原始碼系列-佔位符「」

繼續構建throwable,extractThrowableAnRearrangeArguments方法做了兩件事,一是判斷argArray最後一個引數如果是Throwable型別就取出來;二是如果throwable出現,則把argumentArray的值重新整理一次,實際是去掉了原陣列最後索引位置的異常型別的值

從問題出發學習slf4j、logback原始碼系列-佔位符「」

然後把throwable賦給了LoggingEvent的屬性throwableProxy;

然後一直往下除錯,看究竟怎麼處理佔位符{}和引數及e的,一路下來發現LoggingEvent類的getFormattedMessage方法在處理格式化{}相關邏輯(這裡有個關於idea除錯的小注意點最後補充)

從問題出發學習slf4j、logback原始碼系列-佔位符「」

走到arrayFormat方法實際上是遍歷argArray來擷取字串append到sbuf,這裡的argArray是不包含最後一個異常型別的元素的,到這一步走完上面的formattedMessage的最後值為“error has happen, param:param, error:{}”,到這裡還有一個{}和異常引數e未處理

從問題出發學習slf4j、logback原始碼系列-佔位符「」

再往下除錯,會進入ch/qos/logback/core/pattern/PatternLayoutBase。java的方法writeLoopOnConverters,head是個converter連結串列,尾節點是ExtendedThrowableProxyConverter會把異常進行append到buf裡面

從問題出發學習slf4j、logback原始碼系列-佔位符「」

處理完的sub內容為

2021-09-01 17:48:42,364 [main] ERROR c。x。mone。log。agent。bootstrap。MiLogAgentBootstrap:44 - error has happen, param:param, error:{}

java。lang。NullPointerException: null

at com。xiaomi。mone。log。agent。bootstrap。MiLogAgentBootstrap。main(MiLogAgentBootstrap。java:42) ~[classes/:na]

結論:用第一種方式列印日誌,第二個佔位符{}還在,原因是arrayFormat方法實際上是遍歷argArray來擷取字串append到sbuf,這裡的argArray是不包含最後一個異常型別的元素的,正確的列印方式是第二種,log。error(“error has happen, param:{}, error:”, “param”, e);

小插曲:前面提到除錯getFormattedMessage有個注意點,是每次進入時formattedMessage總莫名其妙已經有了值,需要idea改下設定

從問題出發學習slf4j、logback原始碼系列-佔位符「」