2017-01-09 53 views
1

在我們正在開發的應用程序中,有很多調試和跟蹤日誌記錄,即使日誌級別關閉它們,創建消息參數數組的唯一開銷也會成爲我們某些時間的問題敏感算法。現在,我們不想完全刪除日誌(因爲它們在開發和測試環境中顯然是有用的),但我們確實想要以某種方式減少它們的運行時間開銷。我們考慮了幾個選項:使用ProGuard刪除調試日誌

  • 開溝Slf4j API和使用Log4j2與惰性日誌記錄需要太多的重構和手工勞動。代碼後處理器可以自動用條件語句包裹所有日誌(因此永遠不會創建參數數組),或者將它們全部刪除。
  • ProGuard可以刪除所有記錄器呼叫。

由於我們還沒有發現任何可以將開箱即用的代碼後置處理器,我們決定採用ProGuard解決方案。這是我們基本的ProGuard設置:

-optimizations code/removal/simple,code/removal/advanced 
-dontobfuscate 
-dontshrink 
-keep class * 
-keepclassmembers class * { 
    *; 
} 
-assumenosideeffects class org.slf4j.Logger { 
    void trace(...); 
    void debug(...); 
} 

該解決方案部分工作。大多數調試日誌確實被刪除,但調試日誌參數上調用的所有方法都不受影響。例如,該行:

log.debug("Evidence {} is unverifiable for product {}", evidence, product.getData().getName()); 

...將被改造成這樣:

product.getData().getName() 

諷刺的是,這也使所有的對象數組灌頂:

log.debug("{} {} {}", first, second, third); 
// ...becomes: 
Object[] var10000 = new Object[]{first, second, third}; 

現在,我知道這類事情應該通過JIT(未使用的變量刪除)進行優化 - 我更擔心第一種情況,所有調用的方法都不會隨着日誌記錄一起被刪除。這些可能範圍從無害(簡單的getter調用)到稍差(併發集合上的size()調用)。

目前的ProGuard解決方案「足夠好」,但我想知道是否可以徹底刪除日誌記錄調用(及其副作用)。我們可以通過ProGuard配置實現嗎?還是有現成的工具可以實現這一點?

回答

0

只是一個瘋狂的想法:如何創建自己的接口&實現與slf4j相同的接口,但與展開可變參數?基本上,你可以分叉slf4j以符合你的要求。

另一個想法是構建一個SLF4J-to-Log4j2遷移工具。如果你的公司同意你可以提出這是對Log4j2項目的貢獻,所以你不必維護它。 :-)

+0

自定義日誌記錄界面正是我們試圖避免的那種事情 - 這可能需要過多的手動重構工作。切換到Log4j2 API將解決我們的一些問題,但我會研究它。 – JustACluelessNewbie

+0

幸運的是,slf4j API很小,我想它主要是導入,代碼用LogManager代替LoggerFactory,用ThreadContext代替MDC。 –

+0

是的,它應該只是使用查找替換的問題,也許重構一些潛在的昂貴的日誌來使用「供應商」。由於ProGuard解決方案已經有效(有點,有點),配對這兩個應該足夠了。我希望。 – JustACluelessNewbie