Develop/spring-data

Spring Data JPA, Querydsl 로깅처리. p6spy 원하는 로그만 출력하기

에디개발자 2020. 11. 16. 16:14
반응형

바로 여기로 오셨다면 이전 글을 참조해주세요. 왜 p6spy를 선택했는지와 분석하는 이유에 대해서 정리해놓았습니다.

 

이번 글에서는 p6spy를 사용하는데에 편리한 설정들이 뭐가 있는지 알아보는 과정과 적용하는 것까지 정리하겠습니다.

작성된 글의 소스 코드는 github에 올려두었습니다.

JPA, Querydsl 설정 방법은 아래 링크를 참조해주시면 됩니다!

 

 

JPA에 대해서 궁금하시면?

Querydsl에 대해서 궁금하시면?

나를 닮았다고 한다....

프로젝트를 진행하다보면 원하는 쿼리만 로그출력을 하고 싶을때가 있습니다.

저 같은 경우에는 Spring Batch에서 Batch 관련 테이블이 출력이 안되었으면 좋겠다싶어서 적용하게 되었습니다.

 

크게 2가지에 대해서 알아보겠습니다.

  • 원하는 패턴의 sql문만 출력하고 싶을 경우
  • spring.profiles에 따라서 로그가 출력안되게 하고 싶을 경우

 

원하는 패턴의 sql문만 출력하고 싶을 경우

먼저 p6spy가 어떻게 로그를 출력하는지 알아보겠습니다.

 

Listener에 등록된 클래스를 타고 들어가다보면 P6LogQuery 클래스가 나타납니다.

P6LogQuery 클래스에서 로그출력 여부를 결정짓습니다.

간단하게 관련 소스를 살펴보겠습니다.

  public static void log(Category category, Loggable loggable) {
    if (logger != null && isCategoryOk(category) && isLoggable(loggable.getSql())) {
      doLog(-1, category, loggable.getSql(), loggable.getSqlWithValues());
    }
  }

 

해당 메소드를 호출하고 isLoggable 메소드를 호출합니다.

  static boolean isLoggable(String sql) {
    // empty batches and connection commits/rollbacks
    if (sql == null || sql.isEmpty()) {
      return true;
    }

    final P6LogLoadableOptions opts = P6LogOptions.getActiveInstance();
    
    if (!opts.getFilter()) {
      return true;
    }

    final Pattern sqlExpressionPattern = opts.getSQLExpressionPattern();
    final Pattern includeExcludePattern = opts.getIncludeExcludePattern();
    
    return (sqlExpressionPattern == null || sqlExpressionPattern.matcher(sql).matches())
        && (includeExcludePattern == null || includeExcludePattern.matcher(sql).matches());
  }

 

여기서 원하는 쿼리만 출력할 수 있게 하는 부분은 return의 includeExcludePattern.matcher(sql).matches() 입니다.

그럼 먼저 적용해야할 부분은 opts.getFilter() 조건문을 통과할 수 있도록 P6LogLoadableOptions의 filter값을 설정합니다.

P6LogOptions.getActiveInstance().setFilter(true);

 

그리고 IncludeExcludePattern 값을 설정합니다. 제외하고자 하는 pattern 을 설정합니다. 전 store 테이블을 조회하는 것들을 제외하겠습니다. ( 배치라면 BATCH로 설정하면 모든 테이블이 출력되지 않습니다. )

P6LogOptions.getActiveInstance().setExclude("store");

 

일단 적용하기 전 로그를 살펴보겠습니다. 

store 테이블의 로그가 출력되는 것을 확인할 수 있습니다.

store 테이블 조회 시작
2020-11-16 16:10:30.268  INFO 45534 --- [           main] p6spy                                    : 1605510630266|10ms|statement|connection 2|select store0_.id as col_0_0_, createPrefix(store0_.name) as col_1_0_, store0_.address as col_2_0_ from store store0_ where store0_.name=? limit ?|
HeFormatSql(P6Spy sql,Hibernate format):
    select
        store0_.id as col_0_0_,
        createPrefix(store0_.name) as col_1_0_,
        store0_.address as col_2_0_ 
    from
        store store0_ 
    where
        store0_.name='스토어6' limit 1
store 테이블 조회 완료

 

적용 후 로그를 살펴보겠습니다.

store 테이블 조회 시작
store 테이블 조회 완료

store 테이블 조회 쿼리가 출력되지 않습니다!!

 

최종 소스는 아래와 같습니다

package com.example.querydsl.configuration;

import com.p6spy.engine.logging.P6LogOptions;
import com.p6spy.engine.spy.P6SpyOptions;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

@Configuration
public class P6spyLogMessageFormatConfiguration {

    @PostConstruct
    public void setLogMessageFormat() {
        P6SpyOptions.getActiveInstance().setLogMessageFormat(P6spySqlFormatConfiguration.class.getName());      // pretty

        // exclude sql pattern 
        P6LogOptions.getActiveInstance().setFilter(true);
        P6LogOptions.getActiveInstance().setExclude("store");
    }
}

 

 

spring.profiles에 따라서 로그가 출력안되게 하고 싶을 경우

로컬에서는 로그가 찍히길 원하고 개발서버에서는 로그가 안찍혔으면 좋겠다할 경우 설정하시면 됩니다.

application.yaml에 아래와 같이 설정하시면 로그가 출력되지 않습니다.

디폴트값은 true입니다.

decorator:
  datasource:
    p6spy:
      enable-logging: false

 

 

 

 

반응형