2012-11-02 43 views
8

下面是似乎普遍接受的兩種說法,但我真的不能克服:slf4j中的參數化日誌記錄 - 它與scala的by-name參數相比如何?

1)Scala的按姓名PARAMS優雅取代以往那麼煩人log4j的使用模式:

if (l.isDebugEnabled()) { 
     logger.debug("expensive string representation, eg: godObject.toString()") 
    } 

,因爲名稱參數(斯卡拉特定語言功能)在方法調用之前未得到評估。

2)但是,這個問題可以通過參數化的日誌記錄在slf4f解決:

logger.debug("expensive string representation, eg {}:", godObject[.toString()]); 

那麼,如何工作的呢? 在「調試」方法執行之前,slf4j庫中是否存在一些低級別的魔法來阻止對參數的評估? (這是甚至可能的嗎?是否影響語言的基本方面?)

或者它只是一個簡單的事實,一個對象傳遞給方法 - 而不是一個字符串? (如果可以的話,可能在debug()方法本身中調用該對象的toString())。

但是,那麼對於log4j也不是這樣嗎? (它確實有Object Params的方法)。 這是不是意味着如果你傳遞一個字符串 - 就像在上面的代碼中那樣 - 它的行爲與log4j相同?

我真的很想在這個問題上有一些光芒。

謝謝!

回答

24

slf4j沒有魔法。有記錄的問題曾經是,如果你想登錄假設

logger.debug("expensive string representation: " + godObject) 

那麼無論是否調試級別是在記錄器啓用與否,你總是評估godObject.toString()它可以是一個昂貴的操作,然後也是字符串連接。這是因爲Java(和大多數語言)參數在傳遞給函數之前進行了評估。

這就是爲什麼slf4j引入logger.debug(String msg, Object arg)(和其他變體的更多參數)。整個想法是,您將便宜的參數傳遞給debug函數,並在它們上調用toString,並且只有在調試級別打開時纔將它們組合成消息。

注意,通過調用

logger.debug("expensive string representation, eg: {}", godObject.toString()); 

你大大減少這種優勢,因爲這樣你轉換godObject所有的時間,你把它傳遞給debug之前,無論水平上什麼調試。你只

logger.debug("expensive string representation, eg: {}", godObject); 

應該用然而,這仍然不理想。它只保留調用toString和字符串連接。但是,如果您的日誌消息需要其他昂貴的處理來創建消息,它將無濟於事。就像如果你需要調用一些expensiveMethod創建消息:

logger.debug("expensive method, eg: {}", 
    godObject.expensiveMethod()); 

然後expensiveMethod被傳遞到logger之前總是被判斷。爲了使這項工作有效地與SLF4J,你仍然不得不求助於回

if (logger.isDebugEnabled()) 
    logger.debug("expensive method, eg: {}", 
     godObject.expensiveMethod()); 

Scala的呼叫按姓名有很大幫助,在這個問題上,因爲它可以讓你的代碼中的任意一塊封裝成函數對象和僅在需要時才評估該代碼。這正是我們需要的。例如,讓我們看看slf4s。該庫公開像

def debug(msg: => String) { ... } 

方法爲什麼沒有參數像SLF4J的Logger?因爲我們不再需要它們了。我們可以只寫

logger.debug("expensive representation, eg: " + 
    godObject.expensiveMethod()) 

我們沒有傳遞消息及其參數,我們直接傳遞了一條評估消息的代碼。但只有在記錄儀決定這麼做的時候。如果調試級別沒有打開,那麼logger.debug(...)內的任何內容都不會被評估,整個事情就會被忽略。既不調用expensiveMethod也不調用任何toString調用或字符串串聯。所以這種方法是最一般和最靈活的。無論它有多複雜,您都可以將任何表達式的值計算爲Stringdebug

+1

晶瑩剔透,非常感謝。我想你的徹底解釋彌補了我所期待的並沒有得到的魔法。 :) – teo