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 를 사용할 수 있는 환경이라면, 주저 말고 사용 해 보자.