相信自己!

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            26 隨筆 :: 3 文章 :: 13 評(píng)論 :: 0 Trackbacks

          1. Log4j 的優(yōu)點(diǎn)


          Log4j
          Apache的一個(gè)開放源代碼項(xiàng)目,通過使用Log4j,我們可以控制日志信息輸送的;我們也可以控制每一條日志的輸出格式;通過定義每一條日志信息的級(jí)別,我們能夠更加細(xì)致地控制日志的生成過程。最令人感興趣的就是,這些可以通過一個(gè)配置文件來靈活地進(jìn)行配置,而不需要修改應(yīng)用的代碼。
          log4j
          的好處在于:
          1)
          通過修改配置文件,就可以決定log信息的目的地——控制臺(tái)、文件、GUI組件、甚至是套接口服務(wù)器、NT的事件記錄器、UNIX Syslog守護(hù)進(jìn)程等
          2)
          通過修改配置文件,可以定義每一條日志信息的級(jí)別,從而控制是否輸出。在系統(tǒng)開發(fā)階段可以打印詳細(xì)的log信息以跟蹤系統(tǒng)運(yùn)行情況,而在系統(tǒng)穩(wěn)定后可以關(guān)閉log輸出,從而在能跟蹤系統(tǒng)運(yùn)行情況的同時(shí),又減少了垃圾代碼(System.out.println(......))
          3)
          使用log4j,需要整個(gè)系統(tǒng)有一個(gè)統(tǒng)一的log機(jī)制,有利于系統(tǒng)的規(guī)劃。

          2. 配置文件


          Log4j
          由三個(gè)重要的組件構(gòu)成:日志信息的優(yōu)先級(jí),日志信息的輸出目的地,日志信息的輸出格式。日志信息的優(yōu)先級(jí)從高到低有FATALERRORWARNINFODEBUG,分別用來指定這條日志信息的重要程度;日志信息的輸出目的地指定了日志將打印到控制臺(tái)還是文件中;而輸出格式則控制了日志信息的顯示內(nèi)容。

          2.1. 日志信息的優(yōu)先級(jí)

          分為OFFFATALERRORWARNINFODEBUGALL或者您定義的級(jí)別。
          Log4j
          建議只使用四個(gè)級(jí)別,優(yōu)先級(jí)從高到低分別是ERRORWARNINFODEBUG。通過在這里定義的級(jí)別,您可以控制到應(yīng)用程序中相應(yīng)級(jí)別的日志信息的開關(guān)。 假如在一個(gè)級(jí)別為qLogger中發(fā)生一個(gè)級(jí)別為p的日志請(qǐng)求,如果p>=q,那么請(qǐng)求將被啟用。這是Log4j的核心原則。 比如在這里定義了INFO級(jí)別,則應(yīng)用程序中所有DEBUG級(jí)別的日志信息將不被打印出來;

          2.2. 輸出源的使用

          有選擇的能用或者禁用日志請(qǐng)求僅僅是Log4j的一部分功能。Log4j允許日志請(qǐng)求被輸出到多個(gè)輸出源。用Log4j的話說,一個(gè)輸出源被稱做一個(gè)Appender
          Appender
          包括console(控制臺(tái)), files(文件), GUI components(圖形的組件), remote socket serverssocket 服務(wù)), JMSjava信息服務(wù)), NT Event LoggersNT的事件日志), and remote UNIX Syslog daemons(遠(yuǎn)程UNIX的后臺(tái)日志服務(wù))。它也可以做到異步記錄。 一個(gè)logger可以設(shè)置超過一個(gè)的appender addAppender 方法添加一個(gè)appender到一個(gè)給定的logger。對(duì)于一個(gè)給定的logger它每個(gè)生效的日志請(qǐng)求都被轉(zhuǎn)發(fā)到該logger所有的appender上和該logger的父輩loggerappender上。

          2.2.1. ConsoleAppender

          如果使用ConsoleAppender,那么log信息將寫到Console。效果等同于直接把信息打印到System.out上了。

          2.2.2. FileAppender

          使用FileAppender,那么log信息將寫到指定的文件中。這應(yīng)該是比較經(jīng)常使用到的情況。 相應(yīng)地,在配置文件中應(yīng)該指定log輸出的文件名。如下配置指定了log文件名為dglog.txt
          log4j.appender.A2.File=dglog.txt
          注意將A2替換為具體配置中Appender的別名。

          2.2.3. DailyRollingAppender

          使用FileAppender可以將log信息輸出到文件中,但是如果文件太大了讀起來就不方便了。這時(shí)就可以使用DailyRollingAppenderDailyRollingAppender可以把Log信息輸出到按照日期來區(qū)分的文件中。配置文件就會(huì)每天產(chǎn)生一個(gè)log文件,每個(gè)log文件只記錄當(dāng)天的log信息:
          log4j.appender.A2=org.apache.log4j.DailyRollingFileAppender
          log4j.appender.A2.file=dglog
          log4j.appender.A2.DatePattern='.'yyyy-MM-dd
          log4j.appender.A2.layout=org.apache.log4j.PatternLayout
          log4j.appender.A2.layout.ConversionPattern= %5r %-5p %c{2} - %m%n

          2.2.4. org.apache.log4j.RollingFileAppender

          文件大小到達(dá)指定尺寸的時(shí)候產(chǎn)生一個(gè)新的文件。
          log4j.appender.R=org.apache.log4j.RollingFileAppender
          log4j.appender.R.File= ../logs/dglog.log
          # Control the maximum log file size
          log4j.appender.R.MaxFileSize=100KB
          # Archive log files (one backup file here)
          log4j.appender.R.MaxBackupIndex=1
          log4j.appender.R.layout=org.apache.log4j.PatternLayout
          log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n
          這個(gè)配置文件指定了輸出源R,是一個(gè)輪轉(zhuǎn)日志文件。最大的文件是100KB,當(dāng)一個(gè)日志文件達(dá)到最大尺寸時(shí),Log4J會(huì)自動(dòng)把example.log重命名為dglog.log.1,然后重建一個(gè)新的dglog.log文件,依次輪轉(zhuǎn)。

          2.2.5. org.apache.log4j.WriterAppender

          將日志信息以流格式發(fā)送到任意指定的地方。

          2.3. Layout的配置


          Layout
          指定了log信息輸出的樣式。

          2.3.1. 布局樣式


          org.apache.log4j.HTMLLayout
          (以HTML表格形式布局),
          org.apache.log4j.PatternLayout
          (可以靈活地指定布局模式),
          org.apache.log4j.SimpleLayout
          (包含日志信息的級(jí)別和信息字符串),
          org.apache.log4j.TTCCLayout
          (包含日志產(chǎn)生的時(shí)間、線程、類別等等信息)

          2.3.2. 格式


          %m
          輸出代碼中指定的消息
          %p
          輸出優(yōu)先級(jí),即DEBUGINFOWARNERRORFATAL
          %r
          輸出自應(yīng)用啟動(dòng)到輸出該log信息耗費(fèi)的毫秒數(shù)
          %c
          輸出所屬的類目,通常就是所在類的全名
          %t
          輸出產(chǎn)生該日志事件的線程名
          %n
          輸出一個(gè)回車換行符,Windows平臺(tái)為"rn"Unix平臺(tái)為"n"
          %d
          輸出日志時(shí)間點(diǎn)的日期或時(shí)間,默認(rèn)格式為ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},輸出類似:2002年10月18日 221028921
          %l
          輸出日志事件的發(fā)生位置,包括類目名、發(fā)生的線程,以及在代碼中的行數(shù)。舉例:Testlog4.main(Test Log4.java:10)

          2.3.3. 例子

          例子1:顯示日期和log信息
          log4j.appender.A2.layout=org.apache.log4j.PatternLayout
          log4j.appender.A2.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %m%n
          打印的信息是:
          2002-11-12 11:49:42,866 SELECT * FROM Role WHERE 1=1 order by createDate desc
          例子2:顯示日期,log發(fā)生地方和log信息
          log4j.appender.A2.layout=org.apache.log4j.PatternLayout
          log4j.appender.A2.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %l "#" %m%n
          2002-11-12 11:51:46,313 cn.net.unet.weboa.system.dao.RoleDAO.select(RoleDAO.java:409) "#"
          SELECT * FROM Role WHERE 1=1 order by createDate desc
          例子3:顯示log級(jí)別,時(shí)間,調(diào)用方法,log信息
          log4j.appender.A2.layout=org.apache.log4j.PatternLayout
          log4j.appender.A2.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS}
          method:%l%n%m%n
          log
          信息:
          [DEBUG] 2002-11-12 12:00:57,376
          method:cn.net.unet.weboa.system.dao.RoleDAO.select(RoleDAO.java:409)
          SELECT * FROM Role WHERE 1=1 order by createDate desc

          2.4. 配置文件的例子:


          log4j.rootLogger=DEBUG
          #
          DAOlog記錄到DAOLog,allLog
          log4j.logger.DAO=DEBUG,A2,A4
          #
          將邏輯層log記錄到BusinessLog,allLog
          log4j.logger.Businesslog=DEBUG,A3,A4

          #A1--
          打印到屏幕上
          log4j.appender.A1=org.apache.log4j.ConsoleAppender
          log4j.appender.A1.layout=org.apache.log4j.PatternLayout
          log4j.appender.A1.layout.ConversionPattern=%-5p [%t] %37c %3x - %m%n

          #A2--
          打印到文件DAOLog--專門為DAO層服務(wù)
          log4j.appender.A2=org.apache.log4j.DailyRollingFileAppender
          log4j.appender.A2.file=DAOLog
          log4j.appender.A2.DatePattern='.'yyyy-MM-dd
          log4j.appender.A2.layout=org.apache.log4j.PatternLayout
          log4j.appender.A2.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS}
          method:%l%n%m%n

          #A3--
          打印到文件BusinessLog--專門記錄邏輯處理層服務(wù)log信息
          log4j.appender.A3=org.apache.log4j.DailyRollingFileAppender
          log4j.appender.A3.file=BusinessLog
          log4j.appender.A3.DatePattern='.'yyyy-MM-dd
          log4j.appender.A3.layout=org.apache.log4j.PatternLayout
          log4j.appender.A3.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS}
          method:%l%n%m%n

          #A4--
          打印到文件alllog--記錄所有log信息
          log4j.appender.A4=org.apache.log4j.DailyRollingFileAppender
          log4j.appender.A4.file=alllog
          log4j.appender.A4.DatePattern='.'yyyy-MM-dd
          log4j.appender.A4.layout=org.apache.log4j.PatternLayout
          log4j.appender.A4.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS}
          method:%l%n%m%n

          3. API使用


          log4j
          使用步驟有3個(gè):

          3.1. 初始化

          3.1.1. Tomcat下的初始化

          默認(rèn)的Log4j initialization典型的應(yīng)用是在web-server 環(huán)境下。在tomcat3.xtomcat4.x下,你應(yīng)該將配置文件Log4j.properties放在你的web應(yīng)用程序的WEB-INF/classes 目錄下。
          Log4j
          將發(fā)現(xiàn)屬性文件,并且以此初始化。這是使它工作的最容易的方法。 你也可以選擇在運(yùn)行tomcat前設(shè)置系統(tǒng)屬性Log4j.configuration 。對(duì)于tomcat 3.xTOMCAT_OPTS 系統(tǒng)變量是用來設(shè)置命令行的選項(xiàng)。對(duì)于tomcat4.0,用系統(tǒng)環(huán)境變量CATALINA_OPTS 代替了TOMCAT_OPTS
          UNIX
          命令行
          export TOMCAT_OPTS="-DLog4j.configuration=foobar.txt"
          告訴Log4j用文件foobar.txt作為默認(rèn)的配置文件。這個(gè)文件應(yīng)該放在WEB-INF/classes 目錄下。這個(gè)文件將被PropertyConfigurator所讀。每個(gè)web-application將用不同的默認(rèn)配置文件,因?yàn)槊總€(gè)文件是和它的web-application 相關(guān)的。
          1. export TOMCAT_OPTS="-DLog4j.debug -DLog4j.configuration=foobar.xml" export TOMCAT_OPTS="-DLog4j.debug -DLog4j.configuration=foobar.xml"
          告訴Log4j輸出Log4j-internal的調(diào)試信息,并且用foobar.xml作為默認(rèn)的配置文件。這個(gè)文件應(yīng)該放在你的web-applicationWEB-INF/classes 目錄下。因?yàn)橛?span lang="EN-US">.xml
          的擴(kuò)展名,它將被DOMConfigurator所讀。每個(gè)web-application將用不同的默認(rèn)配置文件。因?yàn)槊總€(gè)文件都和它所在的web-application 相關(guān)的。
          2. set TOMCAT_OPTS=-DLog4j.configuration=foobar.lcf
          -DLog4j.configuratorClass=com.foo.BarConfigurator
          告訴Log4j用文件foobar.lcf作為默認(rèn)的配置文件。這個(gè)文件應(yīng)該放在你的web-applicationWEB-INF/classes 目錄下。因?yàn)槎x了Log4j.configuratorClass 系統(tǒng)屬性,文件將用自定義的com.foo.barconfigurator類來解析。每個(gè)web-application將用不同的默認(rèn)配置文件。因?yàn)槊總€(gè)文件都和它所在的web-application 相關(guān)的。
          3. set TOMCAT_OPTS=-DLog4j.configuration=file:/c:/foobar.lcf set TOMCAT_OPTS=-DLog4j.configuration=file:/c:/foobar.lcf
          告訴Log4j用文件foobar.lcf作為默認(rèn)的配置文件。這個(gè)配置文件用URL file:/c:/foobar.lcf定義了全路徑名。這樣同樣的配置文件將被所有的web-application所用。 不同的web-application將通過它們自己的類裝載器來裝載Log4j。這樣,每個(gè)Log4j的環(huán)境將獨(dú)立的運(yùn)作,而沒有任何的相互同步。例如:在多個(gè)web-application中定義了完全相同的輸出源的FileAppenders將嘗試寫同樣的文件。結(jié)果好象是缺乏安全性的。你必須確保每個(gè)不同的web-applicationLog4j配置沒有用到同樣的系統(tǒng)資源。

          3.1.2. Servlet 的初始化

          用一個(gè)特別的servlet來做Log4j的初始化也是可以的。如下是一個(gè)例子:
          public class Log4jInit extends HttpServlet {
          public void init() {
          String prefix = getServletContext().getRealPath("/");
          String file = getInitParameter("Log4j-init-file");
          if(file != null) {
          PropertyConfigurator.configure(prefix+file);
          }
          }
          public void doGet(HttpServletRequest req, HttpServletResponse res) {
          }
          }
          web.xml中定義隨后的servlet為你的web-application
          <servlet>
          <servlet-name>Log4j-init</servlet-name>
          <servlet-class>xx.xx.Log4jInit</servlet-class>
          <init-param>
          <param-name>Log4j-init-file</param-name>
          <param-value>WEB-INF/classes/Log4j.properties</param-value>
          </init-param>
          <load-on-startup>1</load-on-startup>
          </servlet>
          寫一個(gè)初始化的servlet是最有彈性的初始化Log4j的方法。代碼中沒有任何限制,你可以在servletinit方法中定義它。

          3.2. 根據(jù)配置文件初始化log4j


          log4j
          可以使用3中配置器來初始化:BasicConfigurator,DOMConfigurator,PropertyConfigurator 其語法為:
          BasicConfigurator.configure ()
          : 自動(dòng)快速地使用缺省Log4j環(huán)境。
          PropertyConfigurator.configure ( String configFilename)
          :讀取使用Java的特性文件編寫的配置文件。
          DOMConfigurator.configure ( String filename )
          :讀取XML形式的配置文件。 這里用的是PropertyConfigurator。使用PropertyConfigurator適用于所有的系統(tǒng)。如下的語句:
          PropertyConfigurator.configure("log4j.properties");
          就以log4j.properties為配置文件初始化好了log4j環(huán)境。 注意一點(diǎn):這個(gè)語句只需要在系統(tǒng)啟動(dòng)的時(shí)候執(zhí)行一次。例如,在ActionServletinit()方法中調(diào)用一次。
          public class ActionServlet extends HttpServlet{
          ...
          /**
          * Initialize global variables
          */
          public void init() throws ServletException {
          //
          初始化Action資源
          try{
          initLog4j();
          ...
          }catch(IOException e){
          throw new ServletException("Load ActionRes is Error");
          }
          }
          ...
          protected void initLog4j(){
          PropertyConfigurator.configure("log4j.properties");
          }
          ...
          }//end class ActionServlet

          3.3. 在需要使用log4j的地方獲取Logger實(shí)例

          使用Log4j,首先就是獲取日志記錄器,這個(gè)記錄器將負(fù)責(zé)控制日志信息。其語法為:
          public static Logger getLogger( String name)
          通過指定的名字獲得記錄器,如果必要的話,則為這個(gè)名字創(chuàng)建一個(gè)新的記錄器。Name一般取本類的名字,比如:
          static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () ) ;
          Log4j
          使得通過軟件組件命名logger很容易。我們可以通過Logger的靜態(tài)的初始化方法在每一個(gè)類里定義一個(gè)logger,令logger的名字等于類名的全局名,而實(shí)現(xiàn)logger的命名。這是一個(gè)實(shí)效的簡單的定義一個(gè)logger的方法。因?yàn)槿罩据敵鰩в挟a(chǎn)生日志的類的名字,這個(gè)命名策略使得我們更容易定位到一個(gè)日志信息的來源。雖然普通,但卻是命名logger的常用策略之一。
          Log4j
          沒有限制定義logger的可能。開發(fā)員可以自由的按照它們的意愿定義logger的名稱。 然而,以類的所在位置來命名Logger好象是目前已知的最好方法。

          3.4. 使用Logger對(duì)象的debug,info,fatal...方法


          log.debug("it is the debug info");

          4. 優(yōu)化

          一個(gè)經(jīng)常引用的依靠于logging的參數(shù)是可以計(jì)算的花費(fèi)。這是一個(gè)合理的概念,一個(gè)適度的應(yīng)用程序可能產(chǎn)生成千上萬個(gè)日志請(qǐng)求。許多努力花在測量和調(diào)試logging的優(yōu)化上。Log4j要求快速和彈性:速度最重要,彈性是其次。

          4.1. 日志為禁用時(shí),日志的優(yōu)化。

          當(dāng)日志被徹底的關(guān)閉,一個(gè)日志請(qǐng)求的花費(fèi)等于一個(gè)方法的調(diào)用加上整數(shù)的比較時(shí)間。在233mhzPentium II 機(jī)器上這個(gè)花費(fèi)通常在5-50納秒之間。 然而,方法調(diào)用包括參數(shù)構(gòu)建的隱藏花費(fèi)。 例如,對(duì)于logger catlogger.debug("Entry number: " + i + " is " + String.valueOf(entry[i])); 引起了構(gòu)建信息參數(shù)的花費(fèi),例如,轉(zhuǎn)化整數(shù)ientry[i]到一個(gè)string,并且連接中間字符串,不管信息是否被輸出。這個(gè)參數(shù)的構(gòu)建花費(fèi)可能是很高,它主要決定于被調(diào)用的參數(shù)的大小。 避免參數(shù)構(gòu)建的花費(fèi)應(yīng)如下,


          if(logger.isDebugEnabled())
          {
          logger.debug("result is" + result );
          }

          如果loggerdebug被關(guān)閉這將不會(huì)招致參數(shù)構(gòu)建的花費(fèi)。另一方面,如果loggerdebug的話,它將產(chǎn)生兩次判斷 logger是否能用的花費(fèi)。一次是在debugenabled,一次是debug。這是無關(guān)緊要的,因?yàn)榕袛嗳罩镜哪苡?只占日志實(shí)際花費(fèi)時(shí)間的約1% Log4j里,日志請(qǐng)求在Logger 類的實(shí)例里。Logger 是一個(gè)類,而不是一個(gè)接口。這大量的減少了在方法調(diào)用上的彈性化的花費(fèi)。 當(dāng)然用戶采用預(yù)處理或編譯時(shí)間技術(shù)去編譯出所有的日志聲明。這將導(dǎo)致完美的執(zhí)行成效。然而因?yàn)槎M(jìn)制應(yīng)用程序不包括任何的日志聲明的結(jié)果,日志不可能對(duì)那個(gè)二進(jìn)制程序開啟。以我的觀點(diǎn),以這種較大的代價(jià)來換取較小的性能優(yōu)化是不值得的。

          4.2. 當(dāng)日志狀態(tài)為啟用時(shí),日志的優(yōu)化。

          這是本質(zhì)上的優(yōu)化logger的層次。當(dāng)日志狀態(tài)為開,Log4j依然需要比較請(qǐng)求的級(jí)別與logger的級(jí)別。然而, logger可能沒有被安排一個(gè)級(jí)別;它們將從它們的father繼承。這樣,在繼承之前,logger可能需要搜索它的ancestor 這里有一個(gè)認(rèn)真的努力使層次的搜索盡可能的快。例如,子logger僅僅連接到它的存在的father logger 在先前展示的BasicConfigurator 例子中,名為com.foo.bar logger是連接到跟根logger,因此繞過了不存在的logger comcom.foo。這將顯著的改善執(zhí)行的速度,特別是解析logger的層結(jié)構(gòu)時(shí)。 典型的層次結(jié)構(gòu)的解析的花費(fèi)是logger徹底關(guān)閉時(shí)的三倍。

          4.3. 日志信息的輸出時(shí),日志的優(yōu)化。

          這是主要花費(fèi)在日志輸出的格式化和發(fā)送它到它的輸出源上。這里我們再一次的付出努力以使格式化執(zhí)行的盡可能快。同appender一樣。實(shí)際上典型的花費(fèi)大約是100-300毫秒。 詳情看org.apache.log4.performance.Logging 雖然Log4j有許多特點(diǎn),但是它的第一個(gè)設(shè)計(jì)目標(biāo)還是速度。一些Log4j的組件已經(jīng)被重寫過很多次以改善性能。不過,投稿者經(jīng)常提出了新的優(yōu)化。你應(yīng)該滿意的知道,以SimpleLayout的配置執(zhí)行測試已經(jīng)展示了Log4j的輸出同System.out.println一樣快。

          posted on 2007-10-20 15:38 北極雪 閱讀(3520) 評(píng)論(0)  編輯  收藏 所屬分類: Log4J

          只有注冊用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 隆德县| 泰安市| 兰西县| 揭东县| 抚州市| 巩留县| 平南县| 图木舒克市| 金川县| 富裕县| 白山市| 永春县| 沂源县| 绵竹市| 衡山县| 万山特区| 久治县| 霍城县| 资阳市| 宜昌市| 都昌县| 长春市| 宜良县| 惠安县| 尼玛县| 永丰县| 军事| 祁阳县| 阜南县| 古浪县| 广东省| 延川县| 乌鲁木齐县| 上蔡县| 东乡族自治县| 沁阳市| 桂平市| 炎陵县| 仪陇县| 垫江县| 固原市|