星期四, 1月 25, 2007

Log4j 筆記 (二)


上一篇介紹了 Log4J 的一些基本元素,這篇寫如何使用 Log4J 的三大組成元素,logger、appender 以及 layout 如何搭配 Tomcat 使用。


我最近有一個需求 - 把使用者的操作紀錄記錄下來。因此我第一個想到的方法是使用 Log4J 幫我記錄一些使用者操作系統的 log,並且把這些紀錄存到資料庫去。所以我需要的 appender 就是 JDBCAppender,layout 就看我需要什麼樣的資訊。

雖然 Log4J 也可以在程式裡面去設定 Log4J 的一些 property,但是一般來說,使用 Log4J 都會搭配一個 Log4J 的設定檔案,因為這樣子可以讓程式跟設定分開,若是要更改設定,也不需要重新變動程式部分,只要直接更改設定檔就可以了。

因為 logger 的設定,我希望只設定一次,其他的 JSP 或 Servlet 程式只要建構自己的 logger 而不用每次都重新設定一次,因此需要在 Tomcat 一開始 startup 的時候,就將 logger 設定資訊設定好。在 Tomcat 可以透過 web.xml 設定一開始 startup 的時候就載入的 servlet,因此可以在 web.xml 檔案內做如下的設定:



主要是設定該 Servlet 的 load-on-startup property 為 1,讓 Tomcat startup 的時候就載入該 servlet。另外在 init-param property 部分,設定了 log4j 設定檔放置的位置。

先從最簡單的方式來設定 Log4J 的 logger、appender 以及 layout,那就是直接使用 BasicConfigurator.configure(),不使用設定檔的方是。使用 BasicConfigurator 的效果就如同底下的設定檔:


# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1

# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n


上面的設定檔指定了 rootLogger 的 logger level 以及使用 ConsoleAppender 做輸出,另外也定義了輸出的格式為 %-4r [%t] %-5p %c %x - %m%n。

LoggerSetupServlet 的程式碼如下:




public class LoggerSetupServlet extends HttpServlet {

public void init(ServletConfig config) throws ServletException{
super.init(config);

BasicConfigurator.configure();
Logger logger = Logger.getLogger(LoggerSetupServlet.class);

logger.info("Logger Init successfully!");
}

}



重新啟動 Tomcat 的時候,就會看到底下的訊息


0 [main] INFO com.pg.LoggerSetupServlet - Logger Init successfully!


因為我的目的是把 log 記錄到 Database,所以我需要使用 JDBCAppender,把設定檔設定為:


#
# This defines the logging level for the rootLogger. It is not required
# if you are going to keep the level at debug as the rootLogger by default
# is at the debug level. The value after the comma is the appender for the
# root and we have given it the name R
#
log4j.rootLogger=debug, R

#
# Since we plan to log to a database, we tell log4j that we will use the
# JDBCAppender. To complete the configuration for this, we need to tell
# some basic things to this appender. Database, Username, password and the
# actual values to log. %m represents the message that will be generated by
# our log statements.
#
log4j.appender.R=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.R.URL= JDBC_Driver_URL
log4j.appender.R.user= Databae_User_Account
log4j.appender.R.password= Database_User_Password
log4j.appender.R.sql=INSERT INTO LOG (CreateDate, Logger, Priority,Message) VALUES ('%d{yyy-MM-dd HH:mm:ss }', '%c', '%p', '%m')

#
# These definea the layout to be used.
#
log4j.appender.R.layout=org.apache.log4j.PatternLayout



上面的設定檔指定使用 JDBCAppender,另外也設定了 JDBC Driver URL 以及 Database 的 account/password 等等。另外 Log 的資訊使用

INSERT INTO LOG (CreateDate, Logger, Priority,Message) VALUES ('%d{yyy-MM-dd HH:mm:ss }', '%c', '%p', '%m')

%d : 日期時間,另外也指定了使用 yyy-MM-dd HH:mm:ss 的格式來輸出以方便可以輸入到 Database 的 datatime 欄位

%c : logger class name

%p : Priority (DEBUG、INFO 等等)

%m : Message

除此之外,在原本的 Logger 也要做些改變,例如載入 JDBC Driver class 以及 log4J 設定檔資訊:




public void init(ServletConfig config) throws ServletException{
super.init(config);

try {
Driver driver = (Driver)Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();

DriverManager.registerDriver(driver);
} catch (Exception e){
System.err.println(e);
}

String props = config.getInitParameter("props");
PropertyConfigurator.configure(props);

if(props == null || props.length() == 0 ||
!(new File(props)).isFile()){

System.err.println(
"ERROR: Cannot read the configuration file. " +
"Please check the path of the config init param in web.xml");
throw new ServletException();
}

BasicConfigurator.configure();
Logger logger = Logger.getLogger(LoggerSetupServlet.class);

logger.info("Logger Init successfully!");
}




重開 Tomcat,應該會在 Log table 看到 logger 的資訊。其他程式如果需要記載 log 的,也可以直接使用 logger 輸出,就會直接進入到 Database 了。

沒有留言: