-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ts-loader -> esbuild-loader 마이그레이션 (#703)
* Query Counter (aka. N+1 Detector) 를 통한 API별 쿼리 정보 정리 (#572) * feat: N+1 detector 적용 * feat: AOP 스프링 빈 등록 * chore: rebase develop * chore: p6spy 재적용 * refactor: info-appender logging 패턴 수정 * refactor: info-appender logging 패턴 개행 추가 * refactor: 패키지 위치 및 네이밍 변경 --------- Co-authored-by: mcodnjs <[email protected]> * feat: ts-loader -> esbuild-loader 마이그레이션 * refactor: fork-ts-checker-webpack-plugin 동작 문제 수정 --------- Co-authored-by: 신종화 <[email protected]> Co-authored-by: mcodnjs <[email protected]>
- Loading branch information
1 parent
766406d
commit decf270
Showing
8 changed files
with
1,181 additions
and
9 deletions.
There are no files selected for viewing
45 changes: 45 additions & 0 deletions
45
backend/src/main/java/hanglog/global/detector/ConnectionProxyHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package hanglog.global.detector; | ||
|
||
import jakarta.annotation.Nonnull; | ||
import jakarta.annotation.Nullable; | ||
import lombok.RequiredArgsConstructor; | ||
import org.aopalliance.intercept.MethodInterceptor; | ||
import org.aopalliance.intercept.MethodInvocation; | ||
import org.springframework.aop.framework.ProxyFactory; | ||
|
||
@RequiredArgsConstructor | ||
public class ConnectionProxyHandler implements MethodInterceptor { | ||
|
||
private static final String JDBC_PREPARE_STATEMENT_METHOD_NAME = "prepareStatement"; | ||
|
||
private final Object connection; | ||
private final LoggingForm loggingForm; | ||
|
||
@Nullable | ||
@Override | ||
public Object invoke(@Nonnull final MethodInvocation invocation) throws Throwable { | ||
final Object result = invocation.proceed(); | ||
|
||
if (hasConnection(result) && hasPreparedStatementInvoked(invocation)) { | ||
final ProxyFactory proxyFactory = new ProxyFactory(result); | ||
proxyFactory.addAdvice(new PreparedStatementProxyHandler(loggingForm)); | ||
return proxyFactory.getProxy(); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
private boolean hasPreparedStatementInvoked(final MethodInvocation invocation) { | ||
return invocation.getMethod().getName().equals(JDBC_PREPARE_STATEMENT_METHOD_NAME); | ||
} | ||
|
||
private boolean hasConnection(final Object result) { | ||
return result != null; | ||
} | ||
|
||
public Object getProxy() { | ||
final ProxyFactory proxyFactory = new ProxyFactory(connection); | ||
proxyFactory.addAdvice(this); | ||
return proxyFactory.getProxy(); | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
backend/src/main/java/hanglog/global/detector/LoggingForm.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package hanglog.global.detector; | ||
|
||
import lombok.Getter; | ||
import lombok.ToString; | ||
|
||
@Getter | ||
@ToString | ||
public class LoggingForm { | ||
|
||
private String apiUrl; | ||
private String apiMethod; | ||
private Long queryCounts = 0L; | ||
private Long queryTime = 0L; | ||
|
||
public void queryCountUp() { | ||
queryCounts++; | ||
} | ||
|
||
public void addQueryTime(final Long queryTime) { | ||
this.queryTime += queryTime; | ||
} | ||
|
||
public void setApiUrl(final String apiUrl) { | ||
this.apiUrl = apiUrl; | ||
} | ||
|
||
public void setApiMethod(final String apiMethod) { | ||
this.apiMethod = apiMethod; | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
backend/src/main/java/hanglog/global/detector/PreparedStatementProxyHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package hanglog.global.detector; | ||
|
||
import jakarta.annotation.Nonnull; | ||
import jakarta.annotation.Nullable; | ||
import java.lang.reflect.Method; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.aopalliance.intercept.MethodInterceptor; | ||
import org.aopalliance.intercept.MethodInvocation; | ||
|
||
@RequiredArgsConstructor | ||
public class PreparedStatementProxyHandler implements MethodInterceptor { | ||
|
||
private static final List<String> JDBC_QUERY_METHOD = List.of("executeQuery", "execute", "executeUpdate"); | ||
|
||
private final LoggingForm loggingForm; | ||
|
||
@Nullable | ||
@Override | ||
public Object invoke(@Nonnull final MethodInvocation invocation) throws Throwable { | ||
|
||
final Method method = invocation.getMethod(); | ||
|
||
if (JDBC_QUERY_METHOD.contains(method.getName())) { | ||
final long startTime = System.currentTimeMillis(); | ||
final Object result = invocation.proceed(); | ||
final long endTime = System.currentTimeMillis(); | ||
|
||
loggingForm.addQueryTime(endTime - startTime); | ||
loggingForm.queryCountUp(); | ||
|
||
return result; | ||
} | ||
|
||
return invocation.proceed(); | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
backend/src/main/java/hanglog/global/detector/QueryCounterAop.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package hanglog.global.detector; | ||
|
||
import jakarta.servlet.http.HttpServletRequest; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.aspectj.lang.ProceedingJoinPoint; | ||
import org.aspectj.lang.annotation.After; | ||
import org.aspectj.lang.annotation.Around; | ||
import org.aspectj.lang.annotation.Aspect; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.context.request.RequestContextHolder; | ||
import org.springframework.web.context.request.ServletRequestAttributes; | ||
|
||
@Aspect | ||
@Slf4j | ||
@Component | ||
public class QueryCounterAop { | ||
|
||
private final ThreadLocal<LoggingForm> currentLoggingForm; | ||
|
||
public QueryCounterAop() { | ||
this.currentLoggingForm = new ThreadLocal<>(); | ||
} | ||
|
||
@Around("execution( * javax.sql.DataSource.getConnection())") | ||
public Object captureConnection(final ProceedingJoinPoint joinPoint) throws Throwable { | ||
final Object connection = joinPoint.proceed(); | ||
|
||
return new ConnectionProxyHandler(connection, getCurrentLoggingForm()).getProxy(); | ||
} | ||
|
||
private LoggingForm getCurrentLoggingForm() { | ||
if (currentLoggingForm.get() == null) { | ||
currentLoggingForm.set(new LoggingForm()); | ||
} | ||
|
||
return currentLoggingForm.get(); | ||
} | ||
|
||
@After("within(@org.springframework.web.bind.annotation.RestController *)") | ||
public void loggingAfterApiFinish() { | ||
final LoggingForm loggingForm = getCurrentLoggingForm(); | ||
|
||
final ServletRequestAttributes attributes = | ||
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); | ||
|
||
if (isInRequestScope(attributes)) { | ||
final HttpServletRequest request = attributes.getRequest(); | ||
|
||
loggingForm.setApiMethod(request.getMethod()); | ||
loggingForm.setApiUrl(request.getRequestURI()); | ||
} | ||
|
||
log.info("{}", getCurrentLoggingForm()); | ||
currentLoggingForm.remove(); | ||
} | ||
|
||
private boolean isInRequestScope(final ServletRequestAttributes attributes) { | ||
return attributes != null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.