莊周夢蝶

          生活、程序、未來
             :: 首頁 ::  ::  :: 聚合  :: 管理

          Clojure世界:日志管理——clojure.tools.logging

          Posted on 2012-02-12 20:53 dennis 閱讀(4280) 評論(4)  編輯  收藏 所屬分類: Clojure

              處理日志是任何一個產(chǎn)品級的程序都需要仔細處理的模塊。在Java中,我們經(jīng)常使用的是log4j就是一個日志框架。在clojure里,同樣有一套日志框架——clojure.tools.logging,它不僅提供了常用的日志輸出功能,還屏蔽了Java各種日志框架之間的差異,如slf4j,commons-logging,log4j,java.util.logging等,讓你可以透明地使用這些框架來處理日志。

          名稱:clojure.tools.logging
          主頁:https://github.com/clojure/tools.logging
          依賴:
          [org.clojure/tools.logging "0.2.3"]

          <dependency>
            
          <groupId>org.clojure</groupId>
            
          <artifactId>tools.logging</artifactId>
            
          <version>0.2.3</version>
          </dependency>

          使用:
          (ns example.core
            (:use [clojure.tools.logging :only (info error)]))

          (defn divide [x y]
            (try
              (info "dividing" x "by" y)
              (/ x y)
              (catch Exception ex       (error ex "There was an error in calculation"))))

          常用宏和方法:
          1.除了上面例子的info和error宏,還可以包括warn,trace,debug,fatal等常用宏,分別對應相應的日志級別。這些方法會自動判斷當前l(fā)ogger的級別是否有效,有效的前提下才會輸出日志。也就是說在Java里,你經(jīng)常需要這樣:
          if (logger.isDebugEnabled()) {
              logger.debug(x 
          + " plus " + y + " is " + (x + y));
          }
          在使用 tools.logging的時候是不需要的,因為這些宏幫你做了這個判斷。另外,我們在使用log4j的時候需要指定log的namespace,在tools.logging里不需要,默認會取當前的namespace也就是*ns*。
          最后,info還有個infof的方法,用于輸出格式化日志:
          (infof "%s is %d years old" "kid" 3)
          日志輸出:
          2012-02-12 20:23:07,394 INFO  log: kid is 3 years old
          其他方法也有類似的如warnf,debugf等。
          2.spy宏,同時輸出表達式的form和結(jié)果,例如
          (spy (+1 2))
          輸出日志
          2012-02-12 20:11:47,415 DEBUG log: (+ 1 2)
          => 3

          3.with-logs宏可以在將*out*和*err*流重定向到日志的情況下求值表達式,例如:
          (with-logs *ns* (prn "hello world"))
          輸出日志:
          2012-02-12 20:17:32,592 INFO  log: "hello world"
          with-logs需要明確指定log-ns,默認out的輸出級別是info,而err的級別是error,可以指定輸出級別(with-logs [*ns* :info :error] ......)

          4.事務中(dosync中)的日志輸出,tools.logging做了特殊處理,默認情況下當且僅當事務成功提交的時候并且日志級別是warn或者info會通過agent異步寫入日志。tools.logging定義了一個全局的agent——*logging-agent*。當判斷當前是在事務中調(diào)用log宏,并且日志級別在集合*tx-agent-levels*內(nèi),就會在事務提交成功的時候?qū)⑷罩景l(fā)送給*logging-agent*異步處理。可以通過*tx-agent-levels*改變使用agent輸出日志的級別范圍,默認是#{:info :warn}。還可以通過改變*force*變量來強制使用direct或者agent的方式輸出日志,*force*可以為:agent或者:direct。
          (binding [*force* :agent]
            (log :info 
          "hello world"))
          這里特別使用了log宏,需要明確指定日志級別為info。

          5.默認日志框架的是從classpath查找的,查找的順序是sl4j,commons-logging,log4j,java.util.logging,找到哪個可用就用哪個。如果你的classpath里存在多個日志框架,如同時存在sl4j和commons-logging,那么如果你希望強制使用commons-logging,可以通過改變*logger-factory*變量來使用:
          (ns example
            (:use [clojure.tools.logging.impl :only [cl
          -factory]]))
          (binding [
          *logger-factory* (cl-factory)]
            (info 
          "hello world"))

          *logger-factory*是dynamic變量,可以通過binding改變(前面提到的*force*等變量也一樣),如果不希望每次都用binding,而是全局改變,則需要特殊處理:
          (alter-var-root (var *logger-factory*) (constantly (cl-factory)))
          其他logger factory還包括slf4j-factory,log4j-factory,jul-factory。

          6.每個日志框架的配置跟使用java沒有什么兩樣,比如你用log4j,就需要在classpath下放置一個log4j.properties等。如果你希望用編程的方式配置,可以使用clj-logging-config

          轉(zhuǎn)載請注明出處:http://www.aygfsteel.com/killme2008/archive/2012/02/12/369822.html

          評論

          # re: Clojure世界:日志管理——clojure.tools.logging  回復  更多評論   

          2012-02-13 10:56 by wondery
          又看到博主新文章了,真好。
          想問下你平時用的Clojure開發(fā)環(huán)境和工具是什么?

          # re: Clojure世界:日志管理——clojure.tools.logging[未登錄]  回復  更多評論   

          2012-02-13 11:15 by dennis
          @wondery
          我用的是emacs+swank-clojure

          # re: Clojure世界:日志管理——clojure.tools.logging  回復  更多評論   

          2012-02-13 13:02 by wondery
          @dennis
          謝謝,再問下,你知道維護Storm項目的那些人都用什么開發(fā)環(huán)境和工具嗎?

          # re: Clojure世界:日志管理——clojure.tools.logging[未登錄]  回復  更多評論   

          2012-02-13 13:22 by dennis
          @wondery
          我不知道,我估計也是emacs
          主站蜘蛛池模板: 高阳县| 临沂市| 永寿县| 蒙阴县| 肇源县| 阿勒泰市| 蒙山县| 六安市| 涪陵区| 高雄市| 牙克石市| 泗洪县| 英超| 东莞市| 神池县| 榆树市| 新闻| 陇西县| 望奎县| 东丽区| 改则县| 彝良县| 枣阳市| 张家口市| 通州区| 云安县| 固安县| 淄博市| 嘉义县| 兰考县| 大同县| 宜丰县| 天峨县| 宣武区| 莱阳市| 郑州市| 盐亭县| 乃东县| 中江县| 万宁市| 聊城市|