Skip to content

Commit

Permalink
[BE] refactor: 로깅 구체화 하기 (#318)
Browse files Browse the repository at this point in the history
* feat: 로그 필터 구현

* fix: application prod를 local로 수정

* feat: logback gradle 의존성 추가

* feat: 기존 로깅 파일 삭제

* feat: logback xml 파일 설정

* feat: 로그 필터 구현

* feat: mdc 필터 구현

* feat: 필터 빈등록

* feat: exceptionHandler 수정

* feat: 깃허브 설정

* refactor: mdc 이넘 추가

* refactor: info 로그 출력 message추가

* refactor: 추가 메서드 삭제

* refactor: 사용하지 않는 상수 삭제

* chore: 쿼리 튜닝 및 성능 조회를 위한 변경사항

* chore: 쿼리 정보 로그 삭제

* feat: 로깅 추가 (#359)

* feat: 로그 필터 구현

* fix: application prod를 local로 수정

* feat: logback gradle 의존성 추가

* feat: 기존 로깅 파일 삭제

* feat: logback xml 파일 설정

* feat: 로그 필터 구현

* feat: mdc 필터 구현

* feat: 필터 빈등록

* feat: exceptionHandler 수정

* feat: 깃허브 설정

* refactor: mdc 이넘 추가

* refactor: info 로그 출력 message추가

* refactor: 추가 메서드 삭제

* refactor: 사용하지 않는 상수 삭제

* chore: 쿼리 튜닝 및 성능 조회를 위한 변경사항

* chore: 쿼리 정보 로그 삭제

---------

Co-authored-by: chaewon121 <[email protected]>

* fix: 워크플로우 수정

* hotfix: PlayerRepository.findAll() 호출 시 N+1 문제 수정 (#360)

* refactor: Player의 Member 필드 지연로딩으로 변경

* refactor: PlayerRepository.findAll() Fetch Join 진행

* test: 지연 로딩으로 인한 테스트 에러 임시 수정

* refactor: 코드컨벤션 젹용

* refactor: 날짜 수정

* refactor: mdc 필터 제거

* refactor: 사용하지 않는 mdc토큰 제거

* refactor: 로깅 전략 변경에 따른 코드 수정

* refactor: xml파일에서 mdc 출력 삭제

* refactor: 환경분리 및 패턴 수정

* fix: 환경분리 오류 수정

* refactor: mdc 요소 추가

* chore: 워크플로우 수정

* fix: 트렌젝션 테스트에 추가

* fix: 에러로그 출력 오류 수

* refactor: info로그 수정

* refactor: warn로그 수정

* refactor: error로그 수정

* refactor: 사용하지 않는 enum 삭제

* refactor: 주석 제거

* refactor: 패키지 이동

* refactor: 사용하지 않는 코드 제거

* refactor: warn 레벨 info 로 수정

---------

Co-authored-by: dooboocookie <[email protected]>
Co-authored-by: dooboocookie <[email protected]>
  • Loading branch information
3 people authored and kokodak committed Oct 5, 2023
1 parent 573c7e8 commit d03da84
Show file tree
Hide file tree
Showing 28 changed files with 487 additions and 176 deletions.
12 changes: 12 additions & 0 deletions .idea/2023-naaga.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

116 changes: 116 additions & 0 deletions .idea/workspace.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ dependencies {
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'io.jsonwebtoken:jjwt-impl:0.11.5'
implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5'

implementation 'ch.qos.logback.contrib:logback-jackson:0.1.5'
implementation 'ch.qos.logback.contrib:logback-json-classic:0.1.5'
implementation 'net.logstash.logback:logstash-logback-encoder:6.1'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.now.naaga.common.config;

import com.now.naaga.common.presentation.LogFilter;
import com.now.naaga.common.presentation.QueryCounter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {

private final QueryCounter queryCounter;

public FilterConfig(final QueryCounter queryCounter) {
this.queryCounter = queryCounter;
}

@Bean
public FilterRegistrationBean<LogFilter> logFilter() {
final LogFilter logFilter = new LogFilter(queryCounter);
return new FilterRegistrationBean<>(logFilter);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.now.naaga.common.config;

import com.now.naaga.common.presentation.QueryInspector;
import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import static org.hibernate.cfg.AvailableSettings.STATEMENT_INSPECTOR;

@Configuration
public class HibernateConfig {

private final QueryInspector queryInspector;

public HibernateConfig(final QueryInspector queryInspector) {
this.queryInspector = queryInspector;
}

@Bean
public HibernatePropertiesCustomizer hibernatePropertiesCustomizer() {
return hibernateProperties -> hibernateProperties.put(STATEMENT_INSPECTOR, queryInspector);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.now.naaga.common.exception;

import jakarta.persistence.criteria.CriteriaBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
Expand All @@ -20,46 +19,41 @@ public class ControllerExceptionHandler {
public ResponseEntity<ExceptionResponse> handleBaseException(final BaseException e) {
final BaseExceptionType baseExceptionType = e.exceptionType();
final ExceptionResponse exceptionResponse = new ExceptionResponse(baseExceptionType.errorCode(), baseExceptionType.errorMessage());
log.warn("error = {}", exceptionResponse, e);

log.info("error = {}", exceptionResponse);

return ResponseEntity.status(baseExceptionType.httpStatus()).body(exceptionResponse);
}

@ExceptionHandler({
HttpMessageNotReadableException.class,
MethodArgumentNotValidException.class,
HttpMediaTypeNotSupportedException.class
})
HttpMediaTypeNotSupportedException.class})
public ResponseEntity<ExceptionResponse> handleTypeMismatchException(final Exception e) {
final CommonExceptionType commonExceptionType = CommonExceptionType.INVALID_REQUEST_BODY;
final ExceptionResponse exceptionResponse = new ExceptionResponse(commonExceptionType.errorCode(), commonExceptionType.errorMessage());
log.warn("error = {}", exceptionResponse, e);

log.info("error = {}", exceptionResponse);

return ResponseEntity.status(commonExceptionType.httpStatus()).body(exceptionResponse);
}

@ExceptionHandler(InternalException.class)
public ResponseEntity<ExceptionResponse> handleInternalException(final InternalException e){
public ResponseEntity<ExceptionResponse> handleInternalException(final InternalException e) {
final BaseExceptionType internalExceptionType = e.exceptionType();

// log.error("errorCode = {} \n message = {}",
// internalExceptionType.errorCode(),
// internalExceptionType.errorMessage());

log.error("errorCode = {} \n message = {} \n error = {}",
internalExceptionType.errorCode(),
internalExceptionType.errorMessage(),
e.getMessage() , e);
log.error(e.getMessage(), e);

final ExceptionResponse exceptionResponse = new ExceptionResponse(10000, "예기치 못한 오류입니다");
return ResponseEntity.status(internalExceptionType.httpStatus())
.body(exceptionResponse);
}

@ExceptionHandler(Exception.class)
public ResponseEntity<ExceptionResponse> handleException(final Exception e){
log.error("error = {}"+ e.getMessage() , e);
public ResponseEntity<ExceptionResponse> handleException(final Exception e) {
log.error(e.getMessage(), e);

final ExceptionResponse exceptionResponse = new ExceptionResponse(10000, "예기치 못한 오류입니다");
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(exceptionResponse);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.now.naaga.common.presentation;

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import java.io.IOException;
import java.util.UUID;

import static com.now.naaga.common.presentation.MdcToken.*;

public class LogFilter implements Filter {

private static final String LOG_FORMAT = "uri: {}, method: {}, time: {}ms, queryCount: {}";

private final Logger log = LoggerFactory.getLogger(this.getClass().getSimpleName());
private final QueryCounter queryCounter;

public LogFilter(final QueryCounter queryCounter) {
this.queryCounter = queryCounter;
}

@Override
public void doFilter(final ServletRequest request,
final ServletResponse response,
final FilterChain chain)
throws IOException, ServletException {
queryCounter.init();

final long start = System.currentTimeMillis();
final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
MDC.put(REQUEST_ID.getKey(), UUID.randomUUID().toString());

chain.doFilter(request, response);

final int queryCount = queryCounter.count();
log(start, queryCount, httpServletRequest);
queryCounter.close();
MDC.clear();
}

private void log(final long start,
final int queryCount,
final HttpServletRequest httpServletRequest) {
final long end = System.currentTimeMillis();
final long time = end - start;
log.info(LOG_FORMAT, httpServletRequest.getRequestURI(), httpServletRequest.getMethod(), time, queryCount);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.now.naaga.common.presentation;

public enum MdcToken {

REQUEST_ID("request_id")
;

private final String key;

MdcToken(final String key) {
this.key = key;
}

public String getKey() {
return key;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.now.naaga.common.presentation;

import org.springframework.stereotype.Component;

@Component
public class QueryCounter {

private static final int INITIAL_VALUE = 0;

private final ThreadLocal<Integer> count = new ThreadLocal<>();

public void increase() {
if (count.get() == null) {
init();
}
count.set(count.get() + 1);
}

public void init() {
count.set(INITIAL_VALUE);
}

public int count() {
return count.get();
}

public void close() {
count.remove();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.now.naaga.common.presentation;

import org.hibernate.resource.jdbc.spi.StatementInspector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;

import java.util.Objects;

@Component
public class QueryInspector implements StatementInspector {

private final QueryCounter queryCounter;

public QueryInspector(final QueryCounter queryCounter) {
this.queryCounter = queryCounter;
}

@Override
public String inspect(final String sql) {
if (isInRequestScope()) {
queryCounter.increase();
}
return sql;
}

private boolean isInRequestScope() {
return Objects.nonNull(RequestContextHolder.getRequestAttributes());
}
}
Loading

0 comments on commit d03da84

Please sign in to comment.