混入日志

本文通過應(yīng)用中天天都見得到的日志打印談起,聊聊封裝隱藏拌阴,性能優(yōu)化绍绘,惰性求值,消除重復(fù)的技術(shù)實(shí)踐迟赃。

延遲評估

Eliminate Effects Between Unrelated Things.

遠(yuǎn)古時代

這是早期日志打印的方式陪拘。

if (logger.isLoggable(Level.INFO)) {
  logger.info("problem:" + getDiagnostic());
}

這個實(shí)現(xiàn)存在如下一些問題:

  • 重復(fù)的「樣板代碼」,并且散亂到程序的各個角落捺氢;
  • logger.debug之前藻丢,首先要logger.isLoggableLogger暴露了太多的狀態(tài)邏輯摄乒,違反了LoD(Law of Demeter)悠反。

應(yīng)用LoD

logger.info("unexpect problem: {}", getDiagnostic());

這樣的設(shè)計雖然將狀態(tài)的查詢進(jìn)行了封裝,但依然存在一個嚴(yán)重的性能問題馍佑。即使日志開關(guān)關(guān)閉斋否,getDiagnostic都將被調(diào)用;如果它是一個耗時拭荤、昂貴的操作茵臭,將嚴(yán)重地消耗系統(tǒng)性能。

使用Java8

靈活地應(yīng)用Lambda惰性求值的特性舅世,可以很漂亮地解決這個問題旦委。

public void log(Level level, Supplier<String> supplier) {
  if (isLoggable(level)) {
    log(supplier.get());
  }
}

public void debug(Supplier<String> supplier) {
  log(Level.DEBUG, supplier);
}

public void info(Supplier<String> supplier) {
  log(Level.INFO, supplier);
}

...

用戶的代碼也更加簡潔,省略了那些重復(fù)的樣板代碼雏亚。

logger.info(() -> "problem:" + getDiagnostic());

使用Scala: call-by-name

使用Java8 Lambda時缨硝,() ->的語法顯得有點(diǎn)怪異;如果使用Scala罢低,可以使用by-name機(jī)制進(jìn)一步提高表達(dá)力查辩。

def log(level: Level, msg: => String) {
  if (isLoggable(level)) {
    log(msg)
  }
}

def debug(msg: => String) {
  log(DEBUG, msg)
}

def info(msg: => String) {
  log(INFO, msg)
}
logger.info(s"problem: ${getDiagnostic()}");

s"problem: ${getDiagnostic()}"語句并非在logger.info展開計算,它被延遲直至被apply的時候才真正地被評估和計算。

復(fù)用代碼

DRY: Don't Repeat Youself

用戶空間

再將目光投放到Java應(yīng)用宜岛,當(dāng)每次要使用Logger時长踊,都需要搬遷import語句,并定義logger的靜態(tài)字段萍倡,這樣的重復(fù)結(jié)構(gòu)很容易通過Copy-Paste產(chǎn)生身弊。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Application {
  private static Logger logger = LoggerFactory.getLogger(Application.class);
  
  public void run() {
    logger.trace("start run");
  }
}

消除重復(fù)

使用Scala可以定義Logging的特質(zhì),以便消除重復(fù)遣铝。

import org.slf4j.{Logger, LoggerFactory}

trait Logging {
  val loggerName = this.getClass.getName
  lazy val logger: Logger = LoggerFactory.getLogger(loggerName)

  def trace(msg: => String) {
    if (logger.isTraceEnabled())
      logger.trace(msg)
  }

  def info(msg: => String) {
    if (logger.isTraceEnabled())
      logger.trace(msg)
  }
  
  ...
}

混入特質(zhì)

應(yīng)用程序可以通過混入Logging佑刷,自動得到日志打印的各個接口。

class Main extends App with Logging {
  info("starting...")
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末酿炸,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子涨冀,更是在濱河造成了極大的恐慌填硕,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鹿鳖,死亡現(xiàn)場離奇詭異扁眯,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)翅帜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門姻檀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人涝滴,你說我怎么就攤上這事绣版。” “怎么了歼疮?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵杂抽,是天一觀的道長。 經(jīng)常有香客問我韩脏,道長缩麸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任赡矢,我火速辦了婚禮杭朱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吹散。我一直安慰自己弧械,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布送浊。 她就那樣靜靜地躺著梦谜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上唁桩,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天闭树,我揣著相機(jī)與錄音,去河邊找鬼荒澡。 笑死报辱,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的单山。 我是一名探鬼主播碍现,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼米奸!你這毒婦竟也來了昼接?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤悴晰,失蹤者是張志新(化名)和其女友劉穎慢睡,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體铡溪,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡漂辐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了棕硫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片髓涯。...
    茶點(diǎn)故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖哈扮,靈堂內(nèi)的尸體忽然破棺而出纬纪,到底是詐尸還是另有隱情,我是刑警寧澤灶泵,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布育八,位于F島的核電站,受9級特大地震影響赦邻,放射性物質(zhì)發(fā)生泄漏髓棋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一惶洲、第九天 我趴在偏房一處隱蔽的房頂上張望按声。 院中可真熱鬧,春花似錦恬吕、人聲如沸签则。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽渐裂。三九已至豺旬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間柒凉,已是汗流浹背族阅。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留膝捞,地道東北人坦刀。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像蔬咬,于是被迫代替她去往敵國和親鲤遥。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 本文翻譯自logging howto 基礎(chǔ)教程 日志是跟蹤軟件運(yùn)行時發(fā)生事件的一種手段林艘。Python開發(fā)者在代碼中...
    大蟒傳奇閱讀 4,254評論 0 17
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理盖奈,服務(wù)發(fā)現(xiàn),斷路器北启,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • 在應(yīng)用程序中添加日志記錄總的來說基于三個目的:監(jiān)視代碼中變量的變化情況卜朗,周期性的記錄到文件中供其他應(yīng)用進(jìn)行統(tǒng)計分析...
    時待吾閱讀 4,985評論 0 6
  • 在應(yīng)用程序中添加日志記錄總的來說基于三個目的:監(jiān)視代碼中變量的變化情況,周期性的記錄到文件中供其他應(yīng)用進(jìn)行統(tǒng)計分析...
    時待吾閱讀 5,048評論 1 13
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,811評論 6 342