Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

로그 설정 #76

Merged
merged 5 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
.idea/
build/
HELP.md
log/warn/
log/error/

# User-specific stuff
.idea/**/workspace.xml
Expand Down
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ dependencies {
asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor'
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'

// logging
implementation 'net.logstash.logback:logstash-logback-encoder:6.1'

// fcm
implementation 'com.google.firebase:firebase-admin:6.8.1'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
import com.backend.blooming.goal.application.exception.ForbiddenGoalToPokeException;
import com.backend.blooming.goal.application.exception.InvalidGoalException;
import com.backend.blooming.goal.application.exception.NotFoundGoalException;
import com.backend.blooming.stamp.application.exception.CreateStampForbiddenException;
import com.backend.blooming.stamp.domain.exception.InvalidStampException;
import com.backend.blooming.goal.application.exception.UpdateGoalForbiddenException;
import com.backend.blooming.notification.application.exception.NotFoundGoalManagerException;
import com.backend.blooming.stamp.application.exception.CreateStampForbiddenException;
import com.backend.blooming.stamp.domain.exception.InvalidStampException;
import com.backend.blooming.themecolor.domain.exception.UnsupportedThemeColorException;
import com.backend.blooming.user.application.exception.DuplicateUserNameException;
import com.backend.blooming.user.application.exception.NotFoundUserException;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.MDC;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
Expand All @@ -37,8 +39,11 @@ public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
private static final int METHOD_ARGUMENT_FIRST_ERROR_INDEX = 0;

@ExceptionHandler(Exception.class)
private ResponseEntity<ExceptionResponse> handleException(Exception exception) {
logger.error(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
private ResponseEntity<ExceptionResponse> handleException(
final Exception exception,
final HttpServletRequest request
) {
logError(exception, request);

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ExceptionResponse("예상치 못한 문제가 발생했습니다."));
Expand All @@ -63,201 +68,230 @@ protected ResponseEntity<Object> handleMethodArgumentNotValid(

@ExceptionHandler(OAuthException.InvalidAuthorizationTokenException.class)
public ResponseEntity<ExceptionResponse> handleInvalidAuthorizationTokenExceptionException(
final OAuthException.InvalidAuthorizationTokenException exception
final OAuthException.InvalidAuthorizationTokenException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(OAuthException.KakaoServerUnavailableException.class)
public ResponseEntity<ExceptionResponse> handleKakaoServerExceptionException(
final OAuthException.KakaoServerUnavailableException exception
final OAuthException.KakaoServerUnavailableException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(InvalidTokenException.class)
public ResponseEntity<ExceptionResponse> handleInvalidTokenExceptionException(
final InvalidTokenException exception
final InvalidTokenException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(UnsupportedOAuthTypeException.class)
public ResponseEntity<ExceptionResponse> handleUnsupportedOAuthTypeException(
final UnsupportedOAuthTypeException exception
final UnsupportedOAuthTypeException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(UnsupportedThemeColorException.class)
public ResponseEntity<ExceptionResponse> handleUnsupportedThemeColorException(
final UnsupportedThemeColorException exception
final UnsupportedThemeColorException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(NotFoundUserException.class)
public ResponseEntity<ExceptionResponse> handleNotFoundUserException(
final NotFoundUserException exception
final NotFoundUserException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(InvalidGoalException.class)
public ResponseEntity<ExceptionResponse> handleInvalidGoalException(
final InvalidGoalException exception
final InvalidGoalException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(NotFoundGoalException.class)
public ResponseEntity<ExceptionResponse> handleNotFoundGoalException(
final NotFoundGoalException exception
final NotFoundGoalException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(FriendRequestNotAllowedException.class)
public ResponseEntity<ExceptionResponse> handleAlreadyRequestedFriendException(
final FriendRequestNotAllowedException exception
final FriendRequestNotAllowedException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(NotFoundFriendRequestException.class)
public ResponseEntity<ExceptionResponse> handleNotFoundFriendRequestException(
final NotFoundFriendRequestException exception
final NotFoundFriendRequestException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(FriendAcceptanceForbiddenException.class)
public ResponseEntity<ExceptionResponse> handleFriendAcceptanceForbiddenException(
final FriendAcceptanceForbiddenException exception
final FriendAcceptanceForbiddenException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(DeleteFriendForbiddenException.class)
public ResponseEntity<ExceptionResponse> handleDeleteFriendForbiddenException(
final DeleteFriendForbiddenException exception
final DeleteFriendForbiddenException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(DeleteGoalForbiddenException.class)
public ResponseEntity<ExceptionResponse> handleDeleteGoalForbiddenException(
final DeleteGoalForbiddenException exception
final DeleteGoalForbiddenException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(UpdateGoalForbiddenException.class)
public ResponseEntity<ExceptionResponse> handleUpdateGoalForbiddenException(
final UpdateGoalForbiddenException exception
final UpdateGoalForbiddenException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(AlreadyRegisterBlackListTokenException.class)
public ResponseEntity<ExceptionResponse> handleAlreadyRegisterBlackListTokenException(
final AlreadyRegisterBlackListTokenException exception
final AlreadyRegisterBlackListTokenException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(ForbiddenGoalToPokeException.class)
public ResponseEntity<ExceptionResponse> handleForbiddenGoalToPokeException(
final ForbiddenGoalToPokeException exception
final ForbiddenGoalToPokeException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(NotFoundGoalManagerException.class)
public ResponseEntity<ExceptionResponse> handleNotFoundGoalManagerException(
final NotFoundGoalManagerException exception
final NotFoundGoalManagerException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(DuplicateUserNameException.class)
public ResponseEntity<ExceptionResponse> handleDuplicateUserNameExcpetion(
final DuplicateUserNameException exception
public ResponseEntity<ExceptionResponse> handleDuplicateUserNameException(
final DuplicateUserNameException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(InvalidStampException.class)
public ResponseEntity<ExceptionResponse> handleInvalidStampException(
final InvalidStampException exception
final InvalidStampException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(new ExceptionResponse(exception.getMessage()));
}

@ExceptionHandler(CreateStampForbiddenException.class)
public ResponseEntity<ExceptionResponse> handleCreateStampForbiddenException(
final CreateStampForbiddenException exception
final CreateStampForbiddenException exception, final HttpServletRequest request
) {
logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
logWarn(exception, request);

return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body(new ExceptionResponse(exception.getMessage()));
}

private void logError(final Exception exception, final HttpServletRequest request) {
setMDC(request);

logger.error(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
}

private void logWarn(final Exception exception, final HttpServletRequest request) {
setMDC(request);

logger.warn(String.format(LOG_MESSAGE_FORMAT, exception.getClass().getSimpleName(), exception.getMessage()));
}

private void setMDC(final HttpServletRequest request) {
MDC.put("version", request.getHeader("X-API-VERSION"));
MDC.put("method", request.getMethod());
MDC.put("uri", getRequestURI(request));
}

private static String getRequestURI(final HttpServletRequest request) {
String requestURI = request.getRequestURI();
final String queryString = request.getQueryString();

if (queryString != null) {
requestURI = requestURI + "?" + queryString;
}

return requestURI;
}
}
9 changes: 9 additions & 0 deletions src/main/resources/log/console-appender.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<included>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
</included>
34 changes: 34 additions & 0 deletions src/main/resources/log/file-error-appender.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<included>
<appender name="FILE-ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp>
<fieldName>timestamp</fieldName>
<timeZone>KST</timeZone>
<pattern>yyyy-MM-dd HH:mm:ss.SSS</pattern>
</timestamp>
<mdc>
<includeMdcKeyName>version</includeMdcKeyName>
<includeMdcKeyName>method</includeMdcKeyName>
<includeMdcKeyName>uri</includeMdcKeyName>
</mdc>
<message/>
<mdc>
<includeMdcKeyName>stacktrace</includeMdcKeyName>
</mdc>
</providers>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>./log/error/%d{yyyy-MM-dd}/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
</appender>
</included>
31 changes: 31 additions & 0 deletions src/main/resources/log/file-warn-appender.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<included>
<appender name="FILE-WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp>
<fieldName>timestamp</fieldName>
<timeZone>KST</timeZone>
<pattern>yyyy-MM-dd HH:mm:ss.SSS</pattern>
</timestamp>
<mdc>
<includeMdcKeyName>version</includeMdcKeyName>
<includeMdcKeyName>method</includeMdcKeyName>
<includeMdcKeyName>uri</includeMdcKeyName>
</mdc>
<message/>
</providers>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>./log/warn/%d{yyyy-MM-dd}/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
</appender>
</included>
Loading
Loading