일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- error
- Source
- Thymeleaf
- Spring Boot
- git
- Eclipse
- ubuntu
- SpringBoot
- AJAX
- MSSQL
- Python
- oracle
- STS
- 설정
- MySQL
- JDBC
- Open Source
- maven
- spring
- JavaScript
- 오픈소스
- Core Java
- Exception
- Docker
- IntelliJ
- Tomcat
- 문서
- PostgreSQL
- myBatis
- jpa
- Today
- Total
헤르메스 LIFE
[SpringBoot] JPA 개발 시 p6spy를 이용해서 쿼리 로그 남기기 본문
JPA를 공부하다보니, JPA에서는 Logging 시 p6spy 이라는 걸 사용하는 방법도 있다고 합니다.
SpringBoot 만을 사용할때에는 log4jdbc-log4j2를 주로 사용했는데, JPA를 보다보니 p6spy라는 것도 있네요.
참조가 필요합니다.
// jpa query logging
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.8.1'
src/main/resources/spy.properties
driverlist=org.h2.Driver
appender=com.p6spy.engine.spy.appender.Slf4JLogger
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat
application.yml
spring:
jpa:
open-in-view: false
#show-sql: true # System.out 으로 출력. logging.level.org.hibernate.SQL=debug 로 대체합니다.
hibernate:
# create : entity를 drop cascade 하고 다시 생성
# update : entity가 수정되면 수정된 내용만 반영
# create-drop,validate, none
# 하이버네이트가 자동으로 생성해주는 DDL은 신뢰성이 떨어지기 때문에
# 절대로! 운영DB 환경에서 그대로 사용하면 안되고, 직접 DDL을 작성하는 것을 권장
ddl-auto: none
#generate-ddl: true
#properties: # Additional native properties to set on the JPA provider.
#hibernate:
#show-sql: true # System.out 으로 출력
#format_sql: true # 로그, 콘솔의 SQL을 좀 더 이쁘게 출력합니다.
#highlight_sql: true # SQL 출력을 ANSI escape codes를 사용하여 색을 부여합니다.
#use_sql_comments: true # 보다 쉬운 디버깅을 위해 SQL 내부에 /* */의 주석을 추가합니다.
# Logging
logging:
level: # 각 package 별로 로깅 레벨을 지정할 수 있다.
root : info
octopus: debug
org.springframework: WARN
#org.hibernate.SQL: debug # logger를 통해 하이버네이트 실행 SQL
#org.hibernate.type.descriptor.sql: trace # sql의 ? 값을 Parameter로 보여줌.
# p6spy 를 위한 설정
decorator.datasource.p6spy.enable-logging: true # false : Disable p6spy
#decorator.datasource.enable: true
INFO 23-03-10 23:27:794[http-nio-9090-exec-1] p6spy.logSQL[60]: - #1678458432794 | took 6ms | statement | connection 4| url jdbc:h2:tcp://localhost/~/test
select tcodem0_.p_cd as p_cd1_3_, tcodem0_.p_cd_nm as p_cd_nm11_3_, tcodem0_.rmk as rmk12_3_, tcodem0_.use_yn as use_yn13_3_ from t_code_m tcodem0_ where tcodem0_.p_cd=?
select tcodem0_.p_cd as p_cd1_3_, tcodem0_.p_cd_nm as p_cd_nm11_3_, tcodem0_.rmk as rmk12_3_, tcodem0_.use_yn as use_yn13_3_ from t_code_m tcodem0_ where tcodem0_.p_cd='USE_YN';
INFO 23-03-10 23:27:806[http-nio-9090-exec-1] p6spy.logSQL[60]: - #1678458432806 | took 0ms | commit | connection 4| url jdbc:h2:tcp://localhost/~/test
한줄로 찍힘니다. 아래와 같이 변경할 수 있습니다.
INFO 23-03-10 23:30:378[http-nio-9090-exec-1] p6spy.logSQL[60]: - [statement] | 0 ms |
select
tcodem0_.p_cd as p_cd1_3_,
tcodem0_.p_cd_nm as p_cd_nm11_3_,
tcodem0_.rmk as rmk12_3_,
tcodem0_.use_yn as use_yn13_3_,
from
t_code_m tcodem0_
where
tcodem0_.p_cd='USE_YN'
INFO 23-03-10 23:30:380[http-nio-9090-exec-1] p6spy.logSQL[60]: - [commit] | 0 ms |
P6SpySqlFormatter.java
package octopus.config;
import java.util.Locale;
import java.util.Stack;
import javax.annotation.PostConstruct;
import org.hibernate.engine.jdbc.internal.FormatStyle;
import org.springframework.context.annotation.Configuration;
import com.p6spy.engine.logging.Category;
import com.p6spy.engine.spy.P6SpyOptions;
import com.p6spy.engine.spy.appender.MessageFormattingStrategy;
@Configuration
public class P6SpySqlFormatter implements MessageFormattingStrategy {
@PostConstruct
public void setLogMessageFormat() {
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);
// sql 이 없다면 출력하지 않아도 됨
if (sql.trim().isEmpty()) {
return "";
}
//return String.format("[%s] | %d ms | %s", category, elapsed, formatSql(category, sql));
return String.format("[%s] | %d ms | %s", category, elapsed, sql + createStack(connectionId, elapsed));
}
private String formatSql(String category, String sql) {
if (sql != null && !sql.trim().isEmpty() && Category.STATEMENT.getName().equals(category)) {
String trimmedSQL = sql.trim().toLowerCase(Locale.ROOT);
if (trimmedSQL.startsWith("create") || trimmedSQL.startsWith("alter") || trimmedSQL.startsWith("comment")) {
sql = FormatStyle.DDL.getFormatter().format(sql);
} else {
sql = FormatStyle.BASIC.getFormatter().format(sql);
}
return sql;
}
return sql;
}
// stack 콘솔 표기
private String createStack(int connectionId, long elapsed) {
Stack<String> callStack = new Stack<>();
StackTraceElement[] stackTrace = new Throwable().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
String trace = stackTraceElement.toString();
// trace 항목을 보고 내게 맞는 것만 필터
if(trace.startsWith("octopus.backend")) {
callStack.push(trace);
}
}
StringBuffer sb = new StringBuffer();
int order = 1;
while (callStack.size() != 0) {
sb.append("\n\t\t" + (order++) + "." + callStack.pop());
}
return new StringBuffer().append("\n\n\tConnection ID:").append(connectionId).append(" | Excution Time:")
.append(elapsed).append(" ms\n").append("\n\tExcution Time:").append(elapsed).append(" ms\n")
.append("\n\tCall Stack :").append(sb).append("\n").append("\n--------------------------------------")
.toString();
}
}
https://github.com/gavlyukovskiy/spring-boot-data-source-decorator
GitHub - gavlyukovskiy/spring-boot-data-source-decorator: Spring Boot integration with p6spy, datasource-proxy, flexy-pool and s
Spring Boot integration with p6spy, datasource-proxy, flexy-pool and spring-cloud-sleuth - GitHub - gavlyukovskiy/spring-boot-data-source-decorator: Spring Boot integration with p6spy, datasource-p...
github.com
https://hch4102.tistory.com/147
쿼리 튜닝을 편하게! p6spy 개조하기
🚫 주의! 굉장히 비싼 자원을 사용하므로 운영 환경에선 절대 사용하지 말 것을 권장드립니다. ✅ 개발 환경 모든 소스코드가 보고 싶으시다면 GitHub🎁 를 참고해주세요. Java 11 Gradle 7.0.2 Spring-Bo
hch4102.tistory.com
https://p6spy.readthedocs.io/en/latest/configandusage.html
Configuration and Usage — p6spy 3.9.2-SNAPSHOT documentation
An example spy.properties file follows (please note default values mentioned as these refer to defaults mentioned in section: Configuration and Usage): modulelist modulelist holds the list of p6spy modules activated. A module contains a group of functional
p6spy.readthedocs.io
https://shanepark.tistory.com/415
[Spring Boot JPA] P6Spy 활용해 쿼리 로그 확인하기
Intro 스프링부트와 JPA로 프로젝트를 진행하다 보면 실제 쿼리가 어떻게 나갈지 눈으로 확인을 하고 싶을 때가 참 많습니다. JPA가 참 편하긴 한데 개발자가 직접 쿼리를 작성하지 않았다 보니 실
shanepark.tistory.com
p6spy 로그 두 번 찍히는 이유 - 인프런
=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오) 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 예3. 질문 잘하기 메뉴
www.inflearn.com
'Spring Boot Framework' 카테고리의 다른 글
[Spring Cloud Netflix] Eureka Server 샘플 (2) | 2024.03.10 |
---|---|
[P6Spy] p6spy 설정 시 두 번 찍히는 경우 (0) | 2024.02.01 |
[JPA] Query Modifying 의 사용 (0) | 2023.06.16 |
[Spring Boot] 게시판 #4 - 게시판 + 댓글 (0) | 2023.05.02 |
[Spring Boot] JPA에서 Boolean 처리 ( @Converter, @Convert ) (0) | 2023.04.25 |