Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
import java.util.UUID;

import org.apache.catalina.connector.ClientAbortException;
import org.slf4j.MDC;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
Expand All @@ -29,14 +30,15 @@
import org.springframework.web.util.WebUtils;

import gg.agit.konect.global.code.ApiResponseCode;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

private static final Logger RUNTIME_ERROR_LOGGER = LoggerFactory.getLogger("runtime.error");

@ExceptionHandler(CustomException.class)
public ResponseEntity<Object> handleCustomException(
HttpServletRequest request,
Expand Down Expand Up @@ -147,20 +149,21 @@ public ResponseEntity<Object> handleException(HttpServletRequest request, Except
StackTraceElement origin = e.getStackTrace()[0];

String uri = String.format("%s %s", request.getMethod(), request.getRequestURI());
String location = String.format(
"%s:%d",
origin.getFileName(),
origin.getLineNumber()
);
String exception = e.getClass().getSimpleName();
String location = String.format("%s:%d", origin.getFileName(), origin.getLineNumber());
String message = e.getMessage();

MDC.put("uri", uri);
MDC.put("location", location);
MDC.put("exception", exception);
MDC.put("message", message);
String slackMessage = String.format(
"""
URI: `%s`
Location: `%s`
Exception: `%s`
```%s```
""",
uri, location, exception, message
);

log.error("URI: {} | Location: {} | Exception: {} | Message: {}", uri, location, exception, message);
RUNTIME_ERROR_LOGGER.error(slackMessage);

return buildErrorResponse(ApiResponseCode.UNEXPECTED_SERVER_ERROR);
}
Expand Down
33 changes: 25 additions & 8 deletions src/main/resources/logback-spring.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,53 @@
</encoder>
</appender>

<appender name="SLACK" class="com.github.maricn.logback.SlackAppender">
<appender name="SLACK_STARTUP" class="com.github.maricn.logback.SlackAppender">
<webhookUri>${SLACK_WEBHOOK_ERROR}</webhookUri>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern><![CDATA[
:rotating_light: *서버에서 에러가 발생했습니다!* :rotating_light:%n
URI: `%mdc{uri}`%n
Location: `%mdc{location}`%n
Exception: `%mdc{exception}`%n
```%mdc{message}```
`%msg`%n
%rootException{1}%n
]]></pattern>
</layout>
<colorCoding>true</colorCoding>
</appender>

<appender name="SLACK_RUNTIME" class="com.github.maricn.logback.SlackAppender">
<webhookUri>${SLACK_WEBHOOK_ERROR}</webhookUri>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern><![CDATA[
:rotating_light: *서버에서 에러가 발생했습니다!* :rotating_light:%n
%msg
]]></pattern>
</layout>
<colorCoding>true</colorCoding>
</appender>

<appender name="ASYNC_SLACK_STARTUP" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="SLACK_STARTUP"/>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<appender name="ASYNC_SLACK" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="SLACK"/>
<appender name="ASYNC_SLACK_RUNTIME" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="SLACK_RUNTIME"/>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<logger name="runtime.error" level="ERROR" additivity="false">
<appender-ref ref="ASYNC_SLACK_RUNTIME"/>
</logger>

<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ASYNC_SLACK"/>
<appender-ref ref="ASYNC_SLACK_STARTUP"/>
</root>
</configuration>