로그 관련 인터페이스
스프링 부트에서는 기본적으로 LogBack을 구현체로 제공합니다.
build.gradle
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testCompileOnly 'org.projectlombok:lombok' // 테스트 코드에서 사용하려면 추가
testAnnotationProcessor 'org.projectlombok:lombok' // 테스트 코드에서 사용하려면 추가
코드로 불러와 사용할 수 있지만 대부분 Lombok의 어노테이션인 @Slf4j
를 선언하여 사용합니다.
// Lombok의 어노테이션으로 사용하는 방법(클래스 위에 선언해줍니다.)
@Slf4j
// 코드로 불러와 사용하는 방법(잘 사용하지 않습니다.)
private Logger log = LoggerFactory.getLogger(getClass());
private static final Logger log = LoggerFactory.getLogger(Xxx.class)
// 로그 출력(+로 문자열 연산을 하면 쓸데없는 연산이 추가되어 추천하지 않습니다.)
log.trace("trace log={}", name);
log.debug("debug log={}", name);
log.info("info log={}", name);
log.warn("warn log={}", name);
log.error("error log={}", name);
TRACE > DEBUG > INFO > WARN > ERROR 순으로 로깅 출력 레벨을 지정할 수 있습니다.
예를들어 로깅 출력 레벨을 INFO
로 설정하면 INFO
, WARN
, ERROR
이 출력되고
TRACE
로 설정하면 모든 로깅이 출력됩니다.
application.properties
// 전체 로그 레벨 설정
logging.level.root=info
// 특정 패키지 로그 레벨 설정
logging.level.[패키지 명]=info
기존의 로그를 찍으면 로그가 한 줄로 출력되고 있습니다.
하지만 여기에서 필자는 객체의 내용을 빠르게 확인하기 어려워 불편함을 느꼈습니다.
따라서 필자는 json string으로 변환 후에 포맷팅하는 방식으로 커스텀 로그를 만들어 보았습니다.
build.gradle
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
DateTime을 json string으로 변환하기 위해 추가
Log.java
@Slf4j
public class Log {
private static final ObjectMapper objectMapper = new ObjectMapper().registerModule(new JavaTimeModule());
private static final ObjectWriter prettyPrinter = objectMapper.writerWithDefaultPrettyPrinter();
private Log() {
// 유틸리티 클래스이므로 인스턴스 생성을 막기 위해 private 생성자 사용
}
public static <T> void info(T object) {
try {
String jsonString = prettyPrinter.writeValueAsString(object);
log.info("{} as json\n{}", object.getClass().getSimpleName(), jsonString);
} catch (JsonProcessingException e) {
log.error("Error converting object to json", e);
}
}
}
util 패키지 밑에 다음과 같이 추가해 주었습니다.
다른 레벨의 로그 함수도 같은 방식으로 추가하시면 됩니다.
Log.info(xxx);
다음과 같이 로그가 포맷팅되어 찍히는 것을 확인할 수 있습니다.
SQL 쿼리 로그 관련 라이브러리
기존에도 show_sql 과 format_sql 설정으로 쿼리 로그를 확인할 수 있었지만
파라미터가 보이지 않아 불편했던 부분을 해당 라이브러리로 해결할 수 있습니다.
build.gradle
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0'
스프링 부트 3.0 이상을 사용하면 라이브러리 버전을 1.9.0 이상으로 사용.
application.properties
decorator.datasource.p6spy.enable-logging=true
여기까지하고 테스트해보면 쿼리가 한줄로 나오며 파라미터가 보이는 것을 확인할 수 있습니다.
여기에서도 필자는 한줄로 나오는 것에 불편함을 느꼈습니다.
따라서 해당 로그를 포맷팅하여 출력하도록 설정을 추가해 주었습니다.
P6SpyFormatter.java
@Configuration
public class P6SpyFormatter 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);
return String.format("[%s] | %d ms | %s", category, elapsed, formatSql(category, sql));
}
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 쿼리가 포맷팅되어 찍히는 것을 확인할 수 있습니다.