Skip to content

Commit d84a960

Browse files
authored
feat: 로깅 초기 버전 구축 (#9)
# 변경점 👍 1. elk + filebeat를 활용한 로깅 초기 버전 구축 2. `LoggingFilter`를 만들어서 요청/응답 로그를 남기도록 추가함 필터에서 로그를 남기는 이유는 다음과 같음 스프링 MVC의 구조는 아래와 같다. ```java HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러 ``` 커스텀해서 가장 빨리 처리할 수 있는 부분은 필터이다. 하지만 인터셉터가 필터보다 더 많은 기능을 제공하기 때문에 인터셉터를 사용해도되지 않나 싶지만, 인터셉터에서 로깅을 처리할 경우에는 단점이 존재한다. **바로 인터셉터가 `GlobalExceptionHandler`보다 뒤에 위치한다는 것** → 이 때문에 필터에서 로깅을 처리했음. (`GlobalExceptionHandler` 에서 잡히는 예외를 굳이 error로그로 남길필요가 없는 것 같음) → 또한 시큐리티 필터체인에서 처리 못한 예외도 로깅필터를 맨 앞에 위치시킨다면 해당 예외를 로그로 남길 수 있다. # 스크린샷 🖼 <img width="2480" height="1240" alt="image" src="https://github.com/user-attachments/assets/756f2607-c168-46ad-b988-b5ac5d1e5c11" /> <img width="2344" height="936" alt="image" src="https://github.com/user-attachments/assets/213acebf-748a-44ee-a239-0a95485ba272" /> # 작업내용 ✏ 현재는 클라이언트 요청이 정상적으로 반환되었을 때는 `trace` level로 기록하는데 이걸 `info` level로 올려서 정상 요청/응답 로그까지 저장할지 고민
1 parent 93c19e6 commit d84a960

File tree

4 files changed

+82
-2
lines changed

4 files changed

+82
-2
lines changed

.github/workflows/deploy.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,10 @@ jobs:
7171
docker pull ${{ steps.login-ecr.outputs.registry }}/music:${{env.date}}
7272
docker stop music || true
7373
docker rm music || true
74-
docker run -d -e TZ=Asia/Seoul --name music -p 8080:8080 ${{ steps.login-ecr.outputs.registry }}/music:${{env.date}}
74+
docker run -d \
75+
--restart=always \
76+
-e TZ=Asia/Seoul \
77+
--name music \
78+
-p 8080:8080 \
79+
-v /home/ubuntu/logs:/app/logs \
80+
${{ steps.login-ecr.outputs.registry }}/music:${{env.date}}
Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,25 @@
11
package apptive.team5.config;
22

3+
import apptive.team5.filter.LoggingFilter;
4+
import org.springframework.boot.web.servlet.FilterRegistrationBean;
5+
import org.springframework.context.annotation.Bean;
36
import org.springframework.context.annotation.Configuration;
47
import org.springframework.data.web.config.EnableSpringDataWebSupport;
8+
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
59

610
import static org.springframework.data.web.config.EnableSpringDataWebSupport.PageSerializationMode.VIA_DTO;
711

812
@Configuration
913
@EnableSpringDataWebSupport(pageSerializationMode = VIA_DTO)
10-
public class WebConfig {
14+
public class WebConfig implements WebMvcConfigurer {
15+
16+
@Bean
17+
public FilterRegistrationBean loggingFilter() {
18+
FilterRegistrationBean registration = new FilterRegistrationBean();
19+
registration.setFilter(new LoggingFilter());
20+
registration.addUrlPatterns("/*");
21+
registration.setOrder(1);
22+
23+
return registration;
24+
}
1125
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package apptive.team5.filter;
2+
3+
import jakarta.servlet.*;
4+
import jakarta.servlet.http.HttpServletRequest;
5+
import jakarta.servlet.http.HttpServletResponse;
6+
import lombok.extern.slf4j.Slf4j;
7+
8+
import java.io.IOException;
9+
import java.util.UUID;
10+
11+
@Slf4j
12+
public class LoggingFilter implements Filter {
13+
@Override
14+
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
15+
16+
HttpServletRequest request = (HttpServletRequest) servletRequest;
17+
HttpServletResponse response = (HttpServletResponse) servletResponse;
18+
String loggingId = UUID.randomUUID().toString();
19+
20+
try {
21+
long startTime = System.currentTimeMillis();
22+
log.trace("[REQUEST] id:{}, request URI: {}, METHOD:{}", loggingId, request.getRequestURI(), request.getMethod());
23+
filterChain.doFilter(request, response);
24+
long endTime = System.currentTimeMillis();
25+
log.trace("[RESPONSE] id:{}, HTTP STATUS:{}, TIME:{}ms ", loggingId, response.getStatus(), endTime - startTime);
26+
} catch (Exception e) {
27+
log.error("[REQUEST] id:{}, request URI: {}, METHOD:{}", loggingId, request.getRequestURI(), request.getMethod());
28+
log.error("[RESPONSE] id:{}, ERROR:{}", loggingId, e.getMessage(), e);
29+
throw e;
30+
}
31+
}
32+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<configuration>
2+
<property name="LOG_FILE" value="/app/logs/application.log"/>
3+
4+
<!-- 콘솔 출력 -->
5+
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
6+
<encoder>
7+
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} - %msg%n</pattern>
8+
</encoder>
9+
</appender>
10+
11+
<!-- 파일 출력 -->
12+
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
13+
<file>${LOG_FILE}</file>
14+
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
15+
<fileNamePattern>/app/logs/application.%d{yyyy-MM-dd_HH-mm}.log.gz</fileNamePattern>
16+
<maxHistory>5</maxHistory>
17+
</rollingPolicy>
18+
<encoder>
19+
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} - %msg%n</pattern>
20+
</encoder>
21+
</appender>
22+
23+
<!-- Logger 설정 -->
24+
<root level="info">
25+
<appender-ref ref="CONSOLE" />
26+
<appender-ref ref="FILE" />
27+
</root>
28+
</configuration>

0 commit comments

Comments
 (0)