Query 서비스를 통해 수행되는 SQL을 로그로 남기기 위해서는 log4jdbc(http://log4jdbc.sourceforge.net/)라는 오픈소스를 활용할 수 있다.
log4jdbc는 JDBC 호출이나 SQL문에 대해 로그를 남길 수 있는 JDBC Driver로, log4jdbc에서 Driver에 대한 Wrapper는 제공하나, DataSource에 대한 Wrapper를 제공하지 않으므로
첨부 AnyFrameDataSourceSpy.java 와 같이 별도 Wrapper를 사용해야 한다.
다음에서는 DataSurceSpy.java를 사용하여 SQL을 로그로 남기기 위한 절차이다.
보다 자세한 내용은 log4jdbc 사이트(http://log4jdbc.sourceforge.net/)를 참조한다.
SQL문을 로그로 남기기
Step 1 : Log4jdbc 라이브러리 다운로드
다음을 참고하여, 필요한 log4jdbcX-1.1alpha2.jar 파일을 다운로드한 후, [Anyframe Core 설치 폴더]내에 복사한다.
| 파일명 |
설명 |
다운로드 |
| log4jdbc3-1.1alpha2.jar |
If you are using JDK 1.4 or 1.5, you should use the JDBC 3 version of log4jdbc. |
Download |
| log4jdbc4-1.1alpha2.jar |
If you are using JDK 1.6 or 1.7, you should use the JDBC 4 version of log4jdbc
(even if the actual underlying JDBC driver you are using is a JDBC 3 or older driver). |
Download |
Step 2 : Simple Logging Facade for Java 라이브러리 다운로드
log4jdbc는
Simple Logging Facade for Java (SLF4J)를 이용하여 어플리케이션에서 사용하는 Logging 서비스와
유연하게 연동할 수 있도록 하고 있다.
따라서 다음 파일들을 다운로드한 후, [Anyframe Core 설치 폴더] 내에 복사한다.
| 파일명 |
설명 |
다운로드 |
| slf4j-api-1.4.3.jar |
log4jdbc와 logging 서비스 연동을 위한 API 제공 |
Download |
| slf4j-log4j12-1.4.3.jar |
log4jdbc와 Log4j 기반의 Logging 서비스 연동을 위한 구현 라이브러리 제공 |
Download |
Step 3 : AnyFrameDataSourceSpy.java 생성 및 컴파일
다음과 같이 패키지 net.sf.log4jdbc에 속한 클래스
AnyFrameDataSourceSpy.java를 다운로드하고 컴파일한 후,
[Anyframe Core 설치 폴더]classes 내에 저장한다.
컴파일시 log4jdbcX-1.1alpha2.jar 파일이 클래스패스 내에 존재해야 함에 유의하도록 한다.
다음은 AnyFrameDataSourceSpy.java의 코드 일부이다.
package net.sf.log4jdbc;
// 중략
public class AnyFrameDataSourceSpy implements DataSource {
// 중략
public Connection getConnection() throws SQLException {
return getWrappedConnection(dataSource.getConnection());
}
public Connection getConnection(String username, String password) throws SQLException {
return getWrappedConnection(dataSource.getConnection(username, password));
}
public PrintWriter getLogWriter() throws SQLException {
return dataSource.getLogWriter();
}
public int getLoginTimeout() throws SQLException {
return dataSource.getLoginTimeout();
}
public void setLogWriter(PrintWriter out) throws SQLException {
dataSource.setLogWriter(out);
}
public void setLoginTimeout(int seconds) throws SQLException {
dataSource.setLoginTimeout(seconds);
}
private Connection getWrappedConnection(Connection con) {
if (log.isJdbcLoggingEnabled()) {
ConnectionSpy cspy = new ConnectionSpy(con);
cspy.setRdbmsSpecifics(defaultRdbmsSpecifics);
return cspy;
} else {
return con;
}
}
}
Step 4 : DataSource 서비스 속성 정의 파일 정의
앞서 정의한 AnyFrameDataSourceSpy를 통해 DataSource 서비스가 실행될 수 있도록 다음을 참조하여
applicationContext-datasource.xml 파일을 정의한다.
<bean id="common_datasource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:file:/./DATABASE/db/sampledb"/>
<property name="username" value="sa"/>
</bean>
<bean id="dataSource" class="net.sf.log4jdbc.AnyFrameDataSourceSpy">
<property name="dataSource" ref="common_datasource"/>
</bean>
Step 5 : Query 서비스 속성 정의 파일 정의
Query 서비스에서 참조하는 DataSource 서비스를 앞서 정의한 AnyFrameDataSourceSpy 클래스의 Bean Id로 정의한다.
다음은 Query 서비스 속성을 정의한 샘플
applicationContext-query.xml 파일의 일부 내용이다.
<bean name="queryService" class="anyframe.core.query.impl.QueryServiceImpl">
<property name="jdbcTemplate">
<ref bean="jdbcTemplate"/>
</property>
<config:configuration>
<filename>classpath:mappings/emp-user-userservice-mapping.xml</filename>
<nullcheck type="VARCHAR" default-value=""/>
<sqlload dynamic="false" frequency="5"/>
<skiperror>true</skiperror>
</config:configuration>
</bean>
<bean id="jdbcTemplate" class="anyframe.core.query.impl.util.PagingJdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
Step 6 : Logger 정의
lo4jdbc를 사용하여 로그를 남기기 위해서는 log4j.xml 파일 내에 다음을 참고하여,
필요한 Logger를 정의하도록 한다.
- jdbc.sqlonly :
SQL문만을 로그로 남기며, PreparedStatement일 경우 관련된 argument 값으로 대체된 SQL문이 보여진다.
- jdbc.sqltiming :
SQL문과 해당 SQL을 실행시키는데 수행된 시간 정보(milliseconds)를 포함한다.
- jdbc.audit :
ResultSet을 제외한 모든 JDBC 호출 정보를 로그로 남긴다. 많은 양의 로그가 생성되므로 특별히 JDBC 문제를 추적해야 할 필요가 있는 경우를 제외하고는 사용을 권장하지 않는다.
- jdbc.resultset :
ResultSet을 포함한 모든 JDBC 호출 정보를 로그로 남기므로 매우 방대한 양의 로그가 생성된다.
또한, 각 Logger에 대한 로그 레벨은 DEBUG, INFO, ERROR 중 하나를 선택할 수 있다.
- DEBUG - SQL이 실행된 클래스명과 Line 번호를 로그로 남긴다.
- INFO - SQL문을 로그로 남긴다.
- ERROR - SQL 실행 에러가 발생한 경우 stack trace 정보를 로그로 남긴다.