본문 바로가기

개발

[Java] p6spy 긴 바인딩 로그 치환하기

문제 상황

  1. 이미지 저장 시, p6spy 로그 길이가 너무 길어짐
  2. 운영서버에 적용하지 않은 로그였지만, 개발 서버의 로그 용량이 불필요하게 커졌다.

이 글에서 다루지 않는 부분

  • 성능 이슈
  • 설치법

해결 방법

다음 블로그를 참고했다. p6spy 구조를 잘 정리해놨고, 샘플 코드도 있다.

https://backtony.tistory.com/34

여유가 있다면 글을 정독하는 것도 좋다.

 

 

post 테이블의 image 컬럼에 test란 값을 넣을 때 바인딩 로그는 다음과 같다.

insert into post (image,id) values ('test',default)

우리가 보내는 데이터는 작은따옴표()로 둘러쌓이기 때문에 이 값들만 뽑아내, 길다 싶은 문자열을 잘라내거나 다른 문자로 치환하면 된다.

이 값을 추출하는 작업을 정규표현식으로 처리했다.

([^']*)

전체 코드는 다음과 같다.

import com.p6spy.engine.logging.Category;
import com.p6spy.engine.spy.P6SpyOptions;
import com.p6spy.engine.spy.appender.MessageFormattingStrategy;
import jakarta.annotation.PostConstruct;
import org.hibernate.engine.jdbc.internal.FormatStyle;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@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 = replaceStringLengthMore50(sql); // 긴 값을 대체하는 메소드
        sql = FormatStyle.HIGHLIGHT.getFormatter().format(sql);
        sql = formatSql(category, sql);
        return String.format("[%s] | %d ms | %s", category, elapsed, formatSql(category, sql));
    }
    /**
     * 복붙한 코드
     * reference: https://backtony.tistory.com/34
     */
    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;
    }
    /**
     * sql 내부에서 길이가 50자 이상인 값은 대체 문자열로 치환
     * @param sql 바인딩된 원본 sql
     * @return 치환된 문자열이 있는 sql
     */
    private String replaceStringLengthMore50(String sql) {
        Pattern pattern = Pattern.compile("\'(.*?)\'");
        Matcher matcher = pattern.matcher(sql);

        while (matcher.find()) {
            String value = matcher.group();

            if (StringUtils.hasLength(value) && value.length() > 50) {
                sql = sql.replace(value, "'USE DEBUG MODE'");
            }
        }
        return sql;
    }
}

이렇게 만든 클래스를 p6spy Config에 등록한다.

import com.p6spy.engine.spy.P6SpyOptions;
import jakarta.annotation.PostConstruct;
import org.springframework.context.annotation.Configuration;

@Configuration
public class P6spyConfig {

    @PostConstruct
    public void setLogMessageFormat() {
        P6SpyOptions.getActiveInstance().setLogMessageFormat(P6SpySqlFormatter.class.getName());
    }
}

 

이제 매우 긴 데이터를 보내면 다음과 같이 처리된다.

RequestBody

{
    "image": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
}

 

 

치환 전

insert into post (image,id) values ('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz',default)

 

 

치환 후

insert into post (image,id) values ('USE DEBUG MODE',default)

Reference

https://backtony.tistory.com/34

'개발' 카테고리의 다른 글

ArrayBuffer, Blob  (0) 2024.11.09
단위 테스트 적용하기  (0) 2024.10.26
[python] pandas csv 분할 중 .0 .1 문제  (0) 2024.08.29
proxyBeanMethods=false를 써야 하는지  (0) 2024.07.21
[Java] 토큰 인증 처리에 대한 정리  (0) 2024.05.18