本文爲轉載學習java
原文連接:http://hi.baidu.com/boyyf/item/cec95635dbd50e169dc65e26mysql
認識Log4j程序員
在你開發項目的過程過,是否時常使用System.out.println()?考慮是否須要記錄程序運行過程當中出現的錯誤?是否須要記錄用戶的行爲?Apache Log4j項目將幫助咱們逃脫硬編碼寫輸出的痛苦,獨立的日誌輸出程序將使得程序員能夠便利的分級輸出日誌信息。更爲重要的是,Log4j靈活的配置功能使得咱們徹底不須要修改程序,而僅僅修改配置文件便可完全改變日誌輸出的格式、目標等屬性,而且Log4j還爲咱們提供了各類便利的日誌目的地,如「一天一個日誌文件」、套接字、數據庫、電子郵箱,甚至Unix的守護進程和Nt的事件服務。web
Log4j的三大組建sql
Log4j有三個主要的組件:Loggers,Appenders和Layouts,這裏可簡單理解爲日誌記錄器,日誌要輸出的地方和日誌以何種形式輸出。數據庫
Loggersapache
組件在此係統中被分爲五個級別:DEBUG、INFO、WARN、ERROR和FATAL。這五個級別是有順序的,DEBUG < INFO < WARN < ERROR < FATAL,明白這一點很重要,這裏Log4j有一個規則:假設Loggers級別爲P,若是在Loggers中發生了一個級別Q比P高的日誌輸出事件,則會輸出,不然屏蔽掉。服務器
Appendersapp
禁用與使用日誌請求只是Log4j其中的一個小小的地方,Log4j日誌系統容許把日誌輸出到不一樣的地方,如控制檯(Console)、文件(Files)、根據天數或者文件大小產生新的文件、以流的形式發送到其它地方等等。webapp
常見的Appender有:
org.apache.log4j.ConsoleAppender(控制檯)
org.apache.log4j.FileAppender(文件)
org.apache.log4j.DailyRollingFileAppender(天天產生一個日誌文件),
org.apache.log4j.RollingFileAppender(文件大小到達指定尺寸的時候產生一個新的文件)
org.apache.log4j.WriterAppender(將日誌信息以流格式發送到任意指定的地方)
org.apache.log4j.net.SMTPAppender(發送到郵箱)
org.apache.log4j.jdbc.JDBCAppender(儲存到數據庫)
Layouts
有時用戶但願根據本身的喜愛格式化本身的日誌輸出。Log4j能夠在Appenders的後面附加Layouts來完成這個功能。Layouts提供了四種日誌輸出樣式,如根據HTML樣式、自由指定樣式、包含日誌級別與信息的樣式和包含日誌時間、線程、類別等信息的樣式等等。
常見的Layout有:
org.apache.log4j.HTMLLayout(以HTML表格形式佈局),
org.apache.log4j.PatternLayout(能夠靈活地指定佈局模式),
org.apache.log4j.SimpleLayout(包含日誌信息的級別和信息字符串),
org.apache.log4j.TTCCLayout(包含日誌產生的時間、線程、類別等等信息)
Layouts有如下各經常使用的佔位符:
%p 輸出優先級,即DEBUG,INFO,WARN,ERROR,FATAL
%r 輸出自應用啓動到輸出該log信息耗費的毫秒數
%c 輸出所屬的類目,一般就是所在類的全名
%t 輸出產生該日誌事件的線程名
%n 輸出一個回車換行符,Windows平臺爲"\r\n",Unix平臺爲"\n"
%d 輸出日誌時間點的日期或時間,默認格式爲ISO8601,也能夠在其後指定格式,好比:%d{yyy MMM dd HH:mm:ss,SSS},輸出相似:2002年10月18日 22:10:28,921
%l 輸出日誌事件的發生位置,包括類目名、發生的線程,以及在代碼中的行數。舉例:Testlog4.main(TestLog4.java:10)
Log4j的配置文件
就本人看來,Log4j的便利之處就在於他的配置很是靈活的依賴於配置文件,能夠說在程序中只須要寫出在哪裏須要輸出日誌,日誌的級別,以及日誌的內容(這些一般都是固定不變的),而對於常須要改變的內容,好比日誌的格式、輸出到哪裏、怎麼儲存,甚至須要那些記錄器都只須要修改配置文件,而無需修改程序。但同時,這也決定了Log4j的使用核心就在配置文件的編寫。
Log4j的配置文件能夠擁有兩種形式,一是properties文件,另外一種是xml文件,在此,只探討properties文件形式。
首先請看一段配置文件(因爲properties並不支持中文,複製使用時請將中文註釋刪掉,或者下載源程序包中的配置文件):
#下面是Logger的定義
#定義根logger,其他全部的logger都是它的子logger
log4j.rootLogger=DEBUG
#logger的定義策略1:根據類名定義logger
#這裏就定義了兩個logger,一個名爲"com.ins1000.log4j.servlets",另外一個名
#爲"com.ins1000.log4j.servlets"。#logger的命名是具備層次性和隸屬性的,跟
#類的全名同樣,能夠說"com.ins1000.log4j.servlets.Test"這個logger是"com.
#ins1000.log4j.servlets"這個的子logger。
log4j.logger.com.ins1000.log4j.servlets=DEBUG,CONSOLE
log4j.logger.com.ins1000.log4j.servlets.Test=DEBUG,CONSOLE,DailyRollingFile
#logger的定義策略2:根據用途定義logger
#定義了一個名爲sa(system action)的logger,用於記錄程序的系統行爲,如程
#序啓動,初始化完成等
log4j.logger.sa=DEBUG,CONSOLE_SA
#定義了一個名爲us(users action)的logger,用於記錄用戶的通常行爲,如註冊
#發佈文章、發佈做品等
log4j.logger.ua=DEBUG,DailyRollingFile_UA
#定義了一個名爲e(Errors或Exceptions)的logger,用於記錄程序運行中出現的
#錯誤和異常
log4j.logger.e=DEBUG,CONSOLE_E,ROLLING_FILE_E
#以上各個定義的等號右方DEBUG的表示該logger的日誌輸出起始級別,接着後面是
#這個logger要輸#出的Appender,能夠有多個,用逗號隔開。
#其次,這裏提到了兩種logger的命名策略,雖然互聯網上幾乎全部的教程皆稱以類
#的全名是最簡單也最好的命名策略,由於其層次結構跟咱們的項目徹底一致,可是
#本人處於應用須要,仍是提出了另外一種根據用途命名的策略,即把全部須要記錄的
#日誌信息分爲3中(系統行爲、用戶行爲、異常),分別輸出到不一樣的地方。
#下面定義各個層次是否繼承父輩的屬性(初始級別和Appenders)
log4j.additivity.com.ins1000.log4j=true
log4j.additivity.com.ins1000.log4j.Test=true
log4j.additivity.e=false
log4j.additivity.sa=false
log4j.additivity.ua=false
log4j.addivity.org.apache=true
#下面定義各個Appenders
###################################
# Console Appender
###################################
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.Threshold=DEBUG
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[ins1000]%p: %m [%c]%n
###################################
# Console Appender For SystemAction
###################################
log4j.appender.CONSOLE_SA=org.apache.log4j.ConsoleAppender
log4j.appender.Threshold=DEBUG
log4j.appender.CONSOLE_SA.Target=System.out
log4j.appender.CONSOLE_SA.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE_SA.layout.ConversionPattern=[ins1000]\u7cfb\u7edf\u4fe1\u606f: %m%n
###################################
# Console Appender For Errors and Exceptions
###################################
log4j.appender.CONSOLE_E=org.apache.log4j.ConsoleAppender
log4j.appender.Threshold=DEBUG
log4j.appender.CONSOLE_E.Target=System.out
log4j.appender.CONSOLE_E.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE_E.layout.ConversionPattern=[ins1000]\u7cfb\u7edf\u5f02\u5e38: %m [%l]%n
#上面的Appender都是輸出到控制檯,多個項目的信息均可能被輸出到控制檯,因此
#通常都會加上項目名稱,如[ins1000]
########################
# Rolling File For Errors and Exceptions
########################
log4j.appender.ROLLING_FILE_E=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLING_FILE_E.Threshold=ERROR
log4j.appender.ROLLING_FILE_E.File=${webappHome}/WEB-INF/log/errors/ins1000.log
#日誌文件的位置,其中${webappHome}表明環境變量中webappHome的值,Log4j會在
#初始化的死後自動期待,因此咱們能夠在Log4j初始化的時候將webapp的絕對路徑存
#入系統環境標量中,從而解決要手動修改日誌文件的問題
log4j.appender.ROLLING_FILE_E.Append=true
log4j.appender.ROLLING_FILE_E.MaxFileSize=5120KB
#一個文件的大小(當超過這個大小時,自動更換一個文件)
log4j.appender.ROLLING_FILE_E.MaxBackupIndex=1
log4j.appender.ROLLING_FILE_E.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLING_FILE_E.layout.ConversionPattern=%n%n[%d{yyyy-MM-dd HH:mm:ss}]%m [%l]%n
########################
# DailyRollingFile Appender
#######################
log4j.appender.DailyRollingFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DailyRollingFile.DatePattern=yyyy-MM-dd'.log'
#日期戳後綴的格式
log4j.appender.DailyRollingFile.File=${webappHome}/WEB-INF/log/ins1000_
log4j.appender.DailyRollingFile.Append=true
log4j.appender.DailyRollingFile.layout=org.apache.log4j.PatternLayout
log4j.appender.DailyRollingFile.layout.ConversionPattern=[%-5p]%m [%c][%d{yyyy-MM-dd HH:mm:ss}]%n
#這個Appender的工做機理是先將日誌寫在/WEB-INF/log/ins1000_,待到了次日,自動將其改名爲
#ins1000_yyyy-MM-dd.log(其中yyyy-MM-dd是第一天的日期)。而後仍將次日的日誌先記錄在在
#ins1000_中,第三天再更名,以此類推。
########################
# DailyRollingFile Appender For Users Action
#######################
log4j.appender.DailyRollingFile_UA=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DailyRollingFile_UA.DatePattern=yyyy-MM-dd'.log'
log4j.appender.DailyRollingFile_UA.File=${webappHome}/WEB-INF/log/users_action/ins1000_
#${webappHome} is an enviorment variable which is setted in Log4jInit
#it refers to the absolute path of the webapp
log4j.appender.DailyRollingFile_UA.Append=true
log4j.appender.DailyRollingFile_UA.layout=org.apache.log4j.PatternLayout
log4j.appender.DailyRollingFile_UA.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss}] %m%n
本人在網上到處尋覓,都沒有發現有對Log4j配置文件詳細介紹的文檔,若是你們English不錯的話,建議你們須要的時候能夠看看Log4j的API,應該有比較詳細的介紹。在此,本人只再介紹幾個經常使用的Appender的配置:
#####################
# File Appender
#####################
log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.File=file.log
log4j.appender.FILE.Append=false
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
# Use this layout for LogFactor 5 analysis
########################
# Rolling File
########################
log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLING_FILE.Threshold=ERROR
log4j.appender.ROLLING_FILE.File=rolling.log
log4j.appender.ROLLING_FILE.Append=true
log4j.appender.ROLLING_FILE.MaxFileSize=10KB
log4j.appender.ROLLING_FILE.MaxBackupIndex=1
log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
####################
# Socket Appender
####################
log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender
log4j.appender.SOCKET.RemoteHost=localhost
log4j.appender.SOCKET.Port=5001
log4j.appender.SOCKET.LocationInfo=true
# Set up for Log Facter 5
log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout
log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n
########################
# Log Factor 5 Appender
########################
log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000
########################
# SMTP Appender
#######################
log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
log4j.appender.MAIL.Threshold=FATAL
log4j.appender.MAIL.BufferSize=10
log4j.appender.MAIL.SMTPHost=mail.hollycrm.com
log4j.appender.MAIL.Subject=Log4J Message
log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
########################
# JDBC Appender
#######################
log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test
log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
log4j.appender.DATABASE.user=root
log4j.appender.DATABASE.password=
log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES (’[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n’)
log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.File=SampleMessages.log4j
log4j.appender.A1.DatePattern=yyyyMMdd-HH’.log4j’
log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout
自動初始化Log4j的Servlet
package com.ins1000.log4j.servlets; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import org.apache.log4j.PropertyConfigurator; public class Log4jInit extends HttpServlet { public void init(ServletConfig config) throws ServletException { //獲取本webapp所在的絕對路徑 String prefix = config.getServletContext().getRealPath("/"); //從web.xml讀取配置文件名 String file = config.getInitParameter("Log4j-init-file"); //對絕對路徑進行修飾 String editedPrefix = prefix.substring(0,prefix.length()-1).replace("\\", "/"); //將修飾後的絕對路徑存入系統環境變量 System.setProperty("webappHome", editedPrefix); //執行Log4j的初始化 PropertyConfigurator.configure(prefix + file); } }
爲了讓這個Servlet在Web服務器啓動時自動運行,還須要在項目的web.xml寫入:
<servlet> <description>Log4jInit</description> <display-name>Log4jInit</display-name> <servlet-name>Log4jInit</servlet-name> <servlet-class>com.ins1000.log4j.servlets.Log4jInit</servlet-class> <init-param> <param-name>Log4j-init-file</param-name> <param-value>WEB-INF/config/Log4j.properties</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
在程序中使用Log4j
在程序中使用Log4j,也就是要輸出日誌信息,通常分爲兩個步驟:首先得到一個Logger實例,而後調用此實例的debug()、info()、warn()、error()、fatal()等進行日誌的輸出。
在上面的配置文件中,講到了兩種命名策略,一種是直接根據類的全名命名,另外一種是根據用途命名,那麼在實例化和使用的時候,就會稍微有些不一樣。
根據類全命命名:
Logger logger = Logger.getLogger(this.getClass());
//實例化一個logger,這裏this.getClass()將返回這個類的全名,若是這個名字在配置文件中定義了,則這個logger有其相關定義了的屬性,若是沒有,則看是否認義了其父類和時候設置了繼承。若是都沒有,則擁有rootLogger的屬性。
//固然,logger的實例化能夠任意取名,好比Logger logger = Logger.getLogger("myLogger"),但一句相關的策略,將會更加便於管理。
logger.debug("按類取名測試:DEBUG"); logger.info("按類取名測試:INFO"); logger.warn("按類取名測試:WARN"); logger.error("按類取名測試:ERROR"); logger.error("按類取名測試:ERROR", Exception e); logger.fatal("按類取名測試:FATAL");
//這就是條用logger的各類方法輸出日誌信息。其中logger.error("按類取名測試:ERROR", Exception e)也會將異常堆棧e的相關信息也輸出到相應的Appender
根據用途命名:
Logger logger_sa = Logger.getLogger("sa"); logger_sa.info("Log4j演示程序啓動成功"); Logger logger_ua = Logger.getLogger("ua"); logger_ua.info("用戶boyyf註冊成功"); Logger logger_e = Logger.getLogger("e"); try { Integer.parseInt("a"); } catch (Exception e) { logger_e.error("出現數值轉換異常",e); //這樣會在日誌中記錄異常堆棧 }