version : 3.3.4
JPA 사용중 로그에 파라미터가 ? 로 나와 확인할 수 없을때 파라미터를 확인할 수 있는 라이브러리이다.
P6Spy는 JDBC 드라이버를 감싸는 오픈 소스 라이브러리로 애플리케이션에서 발생하는 SQL 쿼리 로그를 기록하고 SQL 성능을 모니터링할 수 있는 도구이다.
JDBC 드라이버와 연동하여 SQL 쿼리, 쿼리 실행 시간, PreparedStatement 파라미터 등을 로깅할 수 있으며 이를 통해 개발자가 애플리케이션의 데이터베이스 작업을 쉽게 분석하고 디버깅할 수 있도록 도와준다.
P6Spy의 주요 기능
1. SQL 쿼리 로깅: 애플리케이션에서 실행되는 모든 SQL 쿼리를 기록한다.
2. 쿼리 성능 모니터링: 각 쿼리의 실행 시간을 기록해 성능 분석에 도움을 준다.
3. SQL 포맷팅: 로그로 출력되는 SQL을 읽기 쉽게 포맷해준다.
4. PreparedStatement 파라미터 로깅: PreparedStatement에 전달된 실제 파라미터 값을 로깅하여 쿼리 디버깅에 도움을 준다.
5. 필터링 기능: 특정 쿼리나 조건에 맞는 SQL만 로깅하도록 설정할 수 있다.
6. 다양한 출력 형식 지원: SQL 로그를 파일, 콘솔, 커스텀 로그 포맷으로 출력할 수 있다.
장점
1. 설정이 쉬움 : 의존성 추가 및 기타 설정으로 적용 가능.
2. SQL 디버깅 : 실제 바인딩 파라미터 확인 가능
3. 쿼리 성능분석 : 각 쿼리의 실행시간이 나온다.
4. 쿼리 포맷팅 : 읽기 쉽게 포맷팅이 가능하다.
5. 다양한 로그출력 지원 : 콘솔, 파일, 커스텀 포맷으로 출력 가능하다.
단점
1. 성능 오버헤드 : 추가 로깅 작업을 수행해서 성능에 오버헤드가 있을 수 있다.
로그 파일에 많은 SQL기록시 성능이 안좋다고 한다.
2. 비동기처리시 실행 시간 측정이 어려울 수 있음
3. 제한된 로깅 제어 : 로그를 부분적으로 하거나 제외하려면 별도 설정을 해야함.
권장환경
1. 개발 및 테스트 환경
2. SQL 성능 최적화
3. 로깅이 필요한 어플리케이션
jpa 사용시 보통 이러한 설정을하고 아래처럼 로그가 나온다.
파라미터는 ?로 나오게 된다.
show-sql: true
properties:
hibernate:
format_sql: true
show_sql: true
use_sql_comments: true
# gradle 추가
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.2'
설정후 쿼리 실행시 이런식으로 로그가 나오게 된다.
took 2ms
: 실행시간
statement
: SQL 카테고리
#1729178081997
: 고유 트랜잭션 번호
connection 3
: db 커넥션 id
url jdbc:mysql://localhost:3306/product
: db연결 url
기본 설정만하고 실행하면 기존 하이버네이트 로그와
p6spy에서 파라미터가 ?인 로그와 파라미터가 ?가 아닌 로그가 나온다.
jpa 설정을 제거하고 다시 실행해보면
# 제거
show-sql: true
properties:
hibernate:
format_sql: true
show_sql: true
use_sql_comments: true
이렇게 2개가 나온다.
P6SpyConfiguration.class에서 기본 설정파일이 P6SpyProperties이다.
기본설정이 MultiLineFormat이고 이 안을 들어가보면
이런식으로 기본 포맷이 되어있다.
MessageFormattingStrategy 를 구현받고 커스텀해서 적용시켜주면 로그 형식을 바꿀 수 있다.
@Configuration
public class P6SpyFormatter implements MessageFormattingStrategy {
@PostConstruct
public void init() {
P6SpyOptions.getActiveInstance().setLogMessageFormat(this.getClass().getName());
}
@Override
public String formatMessage(int connectionId, String now, long elapsed, String category, String prepared, String sql, String url) {
sql = formatSql(category, sql);
return String.format("[%s] | %d ms | %s", category, elapsed, formatSql(category, sql));
}
private String formatSql(String category, String sql) {
if (StringUtils.isNotBlank(sql) && Category.STATEMENT.getName().equals(category)) {
String trimmedSQL = sql.trim().toLowerCase(Locale.ROOT);
if (trimmedSQL.startsWith("create") || trimmedSQL.startsWith("alter") || trimmedSQL.startsWith("comment")) {
return FormatStyle.DDL.getFormatter().format(sql);
}
return FormatStyle.BASIC.getFormatter().format(sql);
}
return sql;
}
}
설정을 적용한 뒤 실행하면 로그가 이런식으로 나온다.
그리고 기본적으로는 resources에 spy.properties를 작성해서 옵션을 설정할 수 있다.
예를들어 특정 테이블이나 특정 카테고리(commit, rollback)등을 로깅하지 않으려면 이런식으로 설정할 수 있다.
filter=true
exclude=qrtz_
excludecategories=commit,result, rollback
별도의 설정을 하지 않는다면 이런식으로 여러 로그가 나온다.
p6spy 로깅을 안하려면 다음과같이 선언해줘야 한다.
기본값은 true이다.
decorator:
datasource:
p6spy:
enable-logging: false
참고 : https://github.com/gavlyukovskiy/spring-boot-data-source-decorator
https://p6spy.readthedocs.io/en/latest/configandusage.html