sql logging thread 정리 로직 변경

dev
박성영 3 months ago
parent 5a645f151c
commit b43950f660

@ -171,53 +171,59 @@ public class DataSourceProxyConfig {
@Override
public void afterQuery(ExecutionInfo execInfo, List<QueryInfo> queryInfoList) {
// 쿼리 실행 후 파라미터가 바인딩된 SQL 출력
for (QueryInfo queryInfo : queryInfoList) {
String query = queryInfo.getQuery();
List<List<ParameterSetOperation>> parametersList = queryInfo.getParametersList();
// Mapper 경로 및 메서드명 추출
String mapperInfo = extractMapperInfo();
logger.info(" ========================== Mapper: {} ========================== ", mapperInfo);
// 쿼리 실행 시간 및 기본 정보
long executionTime = execInfo.getElapsedTime();
logger.debug("실행 시간: {}ms", executionTime);
// 파라미터 값 추출
List<Object> parameterValues = extractParameterValues(parametersList);
// 파라미터 개수 정보
int questionMarkCount = countQuestionMarks(query);
logger.debug("파라미터 정보: ? 플레이스홀더 {}개, 바인딩 값 {}개", questionMarkCount, parameterValues.size());
// 파라미터 값들 전체 출력 (인덱스 포함)
if (!parameterValues.isEmpty()) {
logger.debug("파라미터 값 목록 (총 {}개):", parameterValues.size());
for (int i = 0; i < parameterValues.size(); i++) {
Object param = parameterValues.get(i);
String paramValue;
if (param == null) {
paramValue = "NULL";
} else if (param instanceof String) {
paramValue = "'" + param.toString() + "'";
} else {
paramValue = param.toString();
try {
// 쿼리 실행 후 파라미터가 바인딩된 SQL 출력
for (QueryInfo queryInfo : queryInfoList) {
String query = queryInfo.getQuery();
List<List<ParameterSetOperation>> parametersList = queryInfo.getParametersList();
// Mapper 경로 및 메서드명 추출
String mapperInfo = extractMapperInfo();
logger.info(" ========================== Mapper: {} ========================== ", mapperInfo);
// 쿼리 실행 시간 및 기본 정보
long executionTime = execInfo.getElapsedTime();
logger.debug("실행 시간: {}ms", executionTime);
// 파라미터 값 추출
List<Object> parameterValues = extractParameterValues(parametersList);
// 파라미터 개수 정보
int questionMarkCount = countQuestionMarks(query);
logger.debug("파라미터 정보: ? 플레이스홀더 {}개, 바인딩 값 {}개", questionMarkCount, parameterValues.size());
// 파라미터 값들 전체 출력 (인덱스 포함)
if (!parameterValues.isEmpty()) {
logger.debug("파라미터 값 목록 (총 {}개):", parameterValues.size());
for (int i = 0; i < parameterValues.size(); i++) {
Object param = parameterValues.get(i);
String paramValue;
if (param == null) {
paramValue = "NULL";
} else if (param instanceof String) {
paramValue = "'" + param.toString() + "'";
} else {
paramValue = param.toString();
}
// 파라미터 인덱스와 함께 출력
logger.debug(" (parameter {}) = {}", i + 1, paramValue);
}
// 파라미터 인덱스와 함께 출력
logger.debug(" (parameter {}) = {}", i + 1, paramValue);
}
}
// 파라미터 바인딩된 SQL 생성
String boundQuery = bindParameters(query, parameterValues);
// SQL 포맷팅 적용 (jsqlparser 사용)
String formattedQuery = formatSql(boundQuery);
logger.info("\n{}\n", formattedQuery);
// 파라미터 바인딩된 SQL 생성
String boundQuery = bindParameters(query, parameterValues);
// SQL 포맷팅 적용 (jsqlparser 사용)
String formattedQuery = formatSql(boundQuery);
logger.info("\n{}\n", formattedQuery);
}
} finally {
// ThreadLocal 정리 (메모리 누수 방지)
// 쿼리 로깅이 완료된 후 반드시 정리
SqlLoggingInterceptor.clearCurrentMapperInfo();
}
}

@ -60,24 +60,23 @@ public class SqlLoggingInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// MappedStatement에서 Mapper 정보 추출
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
String statementId = mappedStatement.getId();
// statementId는 "namespace.methodId" 형태 (예: go.kr.project.login.mapper.LoginMapper.selectMenusByRoleIds)
String mapperInfo = statementId;
// ThreadLocal에 Mapper 정보 저장
setCurrentMapperInfo(mapperInfo);
logger.debug("MyBatis Interceptor - Mapper 정보 설정: {}", mapperInfo);
try {
// MappedStatement에서 Mapper 정보 추출
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
String statementId = mappedStatement.getId();
// statementId는 "namespace.methodId" 형태 (예: go.kr.project.login.mapper.LoginMapper.selectMenusByRoleIds)
String mapperInfo = statementId;
// ThreadLocal에 Mapper 정보 저장
setCurrentMapperInfo(mapperInfo);
logger.debug("MyBatis Interceptor - Mapper 정보 설정: {}", mapperInfo);
// 실제 쿼리 실행
return invocation.proceed();
} catch (Exception e) {
} catch (Exception e) {
MappedStatement ms = (MappedStatement) invocation.getArgs()[0];
Object parameter = invocation.getArgs()[1];
@ -88,28 +87,9 @@ public class SqlLoggingInterceptor implements Interceptor {
logger.error("Error: {}", e.getMessage());
logger.error("Error StackTrace: {}", e.getStackTrace());
throw e;
} finally {
// 쿼리 실행 완료 후 ThreadLocal 정리 (메모리 누수 방지)
// 단, DataSourceProxy에서 사용할 수 있도록 바로 정리하지 않고 약간의 지연 후 정리
scheduleCleanup();
}
}
/**
* ThreadLocal
* DataSourceProxy Mapper
*/
private void scheduleCleanup() {
// 별도 스레드에서 약간의 지연 후 ThreadLocal 정리
new Thread(() -> {
try {
Thread.sleep(100); // 100ms 대기 (DataSourceProxy에서 사용할 시간 제공)
clearCurrentMapperInfo();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
clearCurrentMapperInfo();
}
}).start();
// 주의: ThreadLocal 정리는 DataSourceProxy의 afterQuery에서 수행
// finally 블록에서 정리하면 DataSourceProxy가 Mapper 정보를 사용하기 전에 제거될 수 있음
}
@Override

Loading…
Cancel
Save