Spring MVC 를 사용하여 Web Application 을 개발 할 때에, 통상 Database 와 연동을 해서 개발 한다. 데이터의 시발점이기도 하기 때문에, 문제가 발생 하는 경우 다른 무엇보다 최우선으로 확인 한다. 이 때 필요한 것은 로그 이다. 개발자의 생명줄 이나 다름없다.
log4jdbc 는 로그를 상세하게 출력 한다. 라이브러리를 추가 하자. 0.2.7 이 stable 버전 이다.
<dependency>
<groupId>org.lazyluke</groupId>
<artifactId>log4jdbc-remix</artifactId>
<version>0.2.7</version>
</dependency>
그 다음은 DataSource 이다. driverClassName 을 변경 하면 지원 하는 Database 가 제한적 이기 때문에, 보존 하면서 설정 하는 방법 이다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<!-- ConnectionPool Information -->
<beans:bean id="dataSourceSpied" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<beans:property name="driverClassName" value="#{config['jdbc.driver']}" />
<beans:property name="url" value="#{config['jdbc.url']}" />
<beans:property name="username" value="#{config['jdbc.username']}" />
<beans:property name="password" value="#{config['jdbc.password']}" />
<beans:property name="defaultAutoCommit" value="false"/>
<beans:property name="initialSize" value="1"/>
<beans:property name="maxActive" value="1"/>
<beans:property name="maxIdle" value="1"/>
<beans:property name="maxWait" value="20000"/>
<beans:property name="logAbandoned" value="true"/>
<beans:property name="removeAbandoned" value="true"/>
<beans:property name="removeAbandonedTimeout" value="60"/>
<beans:property name="validationQuery" value="SELECT 1 FROM DUAL" />
<beans:property name="testOnBorrow" value="true" />
<beans:property name="testOnReturn" value="true" />
</beans:bean>
<beans:bean id="dataSource" class="net.sf.log4jdbc.Log4jdbcProxyDataSource">
<beans:constructor-arg ref="dataSourceSpied" />
<beans:property name="logFormatter">
<beans:bean class="net.sf.log4jdbc.tools.Log4JdbcCustomFormatter">
<beans:property name="loggingType" value="MULTI_LINE" />
<beans:property name="margin" value="19" />
<beans:property name="sqlPrefix" value="SQL:::" />
</beans:bean>
</beans:property>
</beans:bean>
</beans>
Database 연결 정보를 가지고 있는 dataSource 는 Proxy 클래스를 생성하여 추가적으로 로그를 처리하는 부분이 구현 되어 있으며, Log4jdbcProxyDataSource 는 DataSource 를 상속 형태로 구현하여 확장되어 있다. CGLIB Proxy 라고 불 수 있다.
<logger name="jdbc.connection">
<level value="info" />
</logger>
<logger name="jdbc.sqltiming">
<level value="debug" />
</logger>
<logger name="jdbc.resultsettable">
<level value="info" />
</logger>
log4j.xml 에 위 내용을 추가 하자. 접속 정보, Query, 응답 데이터에 대한 상세 로그가 출력 된다.
2014-10-23 04:19:39,130 INFO connection - 17. Connection opened
2014-10-23 04:19:39,130 DEBUG getBoardList - ooo Using Connection [net.sf.log4jdbc.ConnectionSpy@378c3efb]
2014-10-23 04:19:39,130 DEBUG getBoardList - ==> Preparing: select no, title, content, create_dt from tb_board
2014-10-23 04:19:39,130 DEBUG getBoardList - ==> Parameters:
2014-10-23 04:19:39,132 DEBUG sqltiming - sun.reflect.GeneratedMethodAccessor36.invoke(null:-1)
17. select no, title, content, create_dt from tb_board {executed in 1 msec}
2014-10-23 04:19:39,135 INFO resultsettable - |-------|--------|---------|----------------------|
2014-10-23 04:19:39,135 INFO resultsettable - |NO |TITLE |CONTENT |CREATE_DT |
2014-10-23 04:19:39,135 INFO resultsettable - |-------|--------|---------|----------------------|
2014-10-23 04:19:39,135 INFO resultsettable - |1 |title1 |ko |2014-10-07 12:04:16.0 |
2014-10-23 04:19:39,136 INFO resultsettable - |2 |title2 |en |2014-10-07 12:04:24.0 |
2014-10-23 04:19:39,136 INFO resultsettable - |3 |title3 |cn |2014-10-07 12:04:31.0 |
2014-10-23 04:19:39,136 INFO resultsettable - |-------|--------|---------|----------------------|
2014-10-23 04:19:39,138 INFO connection - 17. Connection closed
Database 와 연결 되는 시나리오가 상세하게 로그로 출력 되고 있어 개발, 검증 단계에서 편리하게 사용할 수 있다.
실 서버 적용 에는 sqltiming 부분만 사용하면 장애 대응이나 데이터에 대한 문의도 편리하게 대응이 가능 하다.
log4jdbc 를 사용할 수 있는 환경이라면, 주저 말고 사용 해 보자.
참고 사이트