diff --git a/src/main/java/com/aolda/itda/config/LoggingFilter.java b/src/main/java/com/aolda/itda/config/LoggingFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..0dd73b1b546e2f8f11829424f62d6783681a187e --- /dev/null +++ b/src/main/java/com/aolda/itda/config/LoggingFilter.java @@ -0,0 +1,51 @@ +package com.aolda.itda.config; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; +import org.springframework.web.util.ContentCachingRequestWrapper; + +import java.io.IOException; + +@Component +public class LoggingFilter extends OncePerRequestFilter { + + private static final Logger logger = LoggerFactory.getLogger(LoggingFilter.class); + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) + throws ServletException, IOException { + + // Request Body를 읽을 수 있도록 래핑 + ContentCachingRequestWrapper cachingRequest = new ContentCachingRequestWrapper(request); + System.out.println("필터 적용"); + filterChain.doFilter(cachingRequest, response); + + // 로그 기록 + logRequest(cachingRequest); + System.out.println("왜 안돼ㅐ"); + } + + private void logRequest(ContentCachingRequestWrapper request) { + System.out.println("되는거 맞아?"); + String ip = request.getRemoteAddr(); + String method = request.getMethod(); + String uri = request.getRequestURI(); + String queryString = request.getQueryString(); + String body = getRequestBody(request); + + logger.info("IP: {}, Method: {}, URI: {}, Query Params: {}, Request Body: {}", + ip, method, uri, (queryString != null ? queryString : "None"), + (!body.isEmpty() ? body : "None")); + } + + private String getRequestBody(ContentCachingRequestWrapper request) { + byte[] buf = request.getContentAsByteArray(); + return (buf.length > 0) ? new String(buf) : ""; + } +} diff --git a/src/main/java/com/aolda/itda/entity/user/User.java b/src/main/java/com/aolda/itda/entity/user/User.java index df006b22353175fd2cab784d624d096315547ca9..682a50e9004d3849bc795b1cd98dc0b392eefb02 100644 --- a/src/main/java/com/aolda/itda/entity/user/User.java +++ b/src/main/java/com/aolda/itda/entity/user/User.java @@ -21,4 +21,8 @@ public class User { private String keystoneUsername; private String keystoneId; + + public void changeUsername(String username) { + this.keystoneUsername = username; + } } diff --git a/src/main/java/com/aolda/itda/exception/ApiExceptionHandler.java b/src/main/java/com/aolda/itda/exception/ApiExceptionHandler.java index 4d1f3600c420d9d31b17e2b3faa8b399a6d5043f..8dbb993591fffcf8b4ddc45f01bc085d56eca41d 100644 --- a/src/main/java/com/aolda/itda/exception/ApiExceptionHandler.java +++ b/src/main/java/com/aolda/itda/exception/ApiExceptionHandler.java @@ -11,7 +11,7 @@ public class ApiExceptionHandler { @ExceptionHandler(value = CustomException.class) public ResponseEntity<ErrorResponse> handleCustomException(CustomException e) { - log.error("[handleCustomException] {} : {}", e.getErrorCode().name(), e.getErrorCode().getMessage()); + log.error("[handleCustomException] {} : {}, {}", e.getErrorCode().name(), e.getErrorCode().getMessage(), e.getStackTrace()); return ErrorResponse.fromException(e); } } diff --git a/src/main/java/com/aolda/itda/service/AuthService.java b/src/main/java/com/aolda/itda/service/AuthService.java index 80c53d38568e4cd09d752bf2b8cbb11e788af23b..6a25ebc9aba5f91ec4159eb77b75ccf2998ff098 100644 --- a/src/main/java/com/aolda/itda/service/AuthService.java +++ b/src/main/java/com/aolda/itda/service/AuthService.java @@ -48,11 +48,15 @@ public class AuthService { } - User entity = userRepository.findByKeystoneUsername(userId).orElse(null); + User entity = userRepository.findByKeystoneId(userId).orElse(null); if (entity == null) { - userRepository.save(User.builder().keystoneId(validateTokenAndGetUserId(token)). + userRepository.save(User.builder().keystoneId(userId). keystoneUsername(loginRequestDTO.getId()).build()); } + else if (!entity.getKeystoneUsername().equals(loginRequestDTO.getId())) { + entity.changeUsername(loginRequestDTO.getId()); + userRepository.save(entity); + } response.addHeader("X-Subject-Token", systemToken != null ? systemToken : token); return LoginResponseDTO.builder() diff --git a/src/main/java/com/aolda/itda/service/forwarding/ForwardingService.java b/src/main/java/com/aolda/itda/service/forwarding/ForwardingService.java index 85c1ec3eb5450c7adae76f06f22724397f1e09f1..cae38c3229e0d8d221136c726f4452d315dbe8ec 100644 --- a/src/main/java/com/aolda/itda/service/forwarding/ForwardingService.java +++ b/src/main/java/com/aolda/itda/service/forwarding/ForwardingService.java @@ -102,7 +102,6 @@ public class ForwardingService { throw new CustomException(ErrorCode.FAIL_CREATE_CONF, "중복된 포트포워딩 Conf 파일이 존재합니다"); } } catch (IOException e) { - e.printStackTrace(); throw new CustomException(ErrorCode.FAIL_CREATE_CONF); } @@ -113,7 +112,6 @@ public class ForwardingService { bw.flush(); bw.close(); } catch (Exception e) { - e.printStackTrace(); if (file.delete()) { throw new CustomException(ErrorCode.FAIL_DELETE_CONF); } @@ -131,7 +129,6 @@ public class ForwardingService { } throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST); } catch (Exception e) { - log.error("[RestClientException] {} : {}", "Nginx Conf Test (forwarding)", e.getMessage()); if (file.delete()) { throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST, "(롤백 실패)"); } @@ -149,7 +146,6 @@ public class ForwardingService { } throw new CustomException(ErrorCode.FAIL_NGINX_CONF_RELOAD); } catch (Exception e) { - log.error("[RestClientException] {} : {}", "Nginx Conf Reload (forwarding)", e.getMessage()); if (file.delete()) { throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST, "(롤백 실패)"); } @@ -168,8 +164,6 @@ public class ForwardingService { /* 중복 검증 */ if (dto.getServerPort() != null && forwardingRepository.existsByServerPortAndIsDeleted(dto.getServerPort(), false)) { - System.out.println(dto.getServerPort()); - System.out.println(forwarding.getServerPort()); forwardingRepository.existsByServerPortAndIsDeleted(dto.getServerPort(), false); throw new CustomException(ErrorCode.DUPLICATED_SERVER_PORT); } @@ -179,12 +173,6 @@ public class ForwardingService { dto.getInstanceIp() == null ? forwarding.getInstanceIp() : dto.getInstanceIp() , dto.getInstancePort() == null ? forwarding.getInstancePort() : dto.getInstancePort() , false)) { - System.out.println(dto.getInstanceIp()); - System.out.println(forwarding.getInstanceIp()); - System.out.println(forwardingRepository.existsByInstanceIpAndInstancePortAndIsDeleted( - dto.getInstanceIp() == null ? forwarding.getInstanceIp() : dto.getInstanceIp() - , dto.getInstancePort() == null ? forwarding.getInstancePort() : dto.getInstancePort() - , false)); throw new CustomException(ErrorCode.DUPLICATED_INSTANCE_INFO); } @@ -211,7 +199,6 @@ public class ForwardingService { bw.flush(); bw.close(); } catch (Exception e) { - e.printStackTrace(); throw new CustomException(ErrorCode.FAIL_UPDATE_CONF, "포트포워딩 Conf 파일을 수정하지 못했습니다"); } @@ -219,19 +206,8 @@ public class ForwardingService { String url = "http://nginx:8081/nginx-api/test"; try { restTemplate.getForEntity(url, String.class); - } catch (HttpServerErrorException.InternalServerError e) { - log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage()); - try { - Files.copy(backup, Paths.get(confPath), StandardCopyOption.REPLACE_EXISTING - , StandardCopyOption.COPY_ATTRIBUTES); - Files.delete(backup); - } catch (IOException e1) { - throw new CustomException(ErrorCode.FAIL_UPDATE_CONF, "(포트포워딩 Conf 파일 수정)"); - } - - throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST); } catch (RuntimeException e) { - log.error("[RestClientException] {} : {}", "Nginx Conf Test (forwarding)", e.getMessage()); + try { Files.copy(backup, Paths.get(confPath), StandardCopyOption.REPLACE_EXISTING , StandardCopyOption.COPY_ATTRIBUTES); @@ -246,18 +222,7 @@ public class ForwardingService { url = "http://nginx:8081/nginx-api/reload"; try { restTemplate.getForEntity(url, String.class); - } catch (HttpServerErrorException.InternalServerError e) { - log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage()); - try { - Files.copy(backup, Paths.get(confPath), StandardCopyOption.REPLACE_EXISTING - , StandardCopyOption.COPY_ATTRIBUTES); - Files.delete(backup); - } catch (IOException e1) { - throw new CustomException(ErrorCode.FAIL_UPDATE_CONF, "(포트포워딩 Conf 파일 수정)"); - } - throw new CustomException(ErrorCode.FAIL_NGINX_CONF_RELOAD); } catch (RuntimeException e) { - log.error("[RestClientException] {} : {}", "Nginx Conf Reload (forwarding)", e.getMessage()); try { Files.copy(backup, Paths.get(confPath), StandardCopyOption.REPLACE_EXISTING , StandardCopyOption.COPY_ATTRIBUTES); @@ -293,16 +258,7 @@ public class ForwardingService { String url = "http://nginx:8081/nginx-api/test"; try { restTemplate.getForEntity(url, String.class); - } catch (HttpServerErrorException.InternalServerError e) { - log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage()); - try { - Files.move(Paths.get(deletePath), Paths.get(confPath)); - } catch (IOException e1) { - throw new CustomException(ErrorCode.FAIL_ROLL_BACK, "(포트포워딩 Conf 삭제)"); - } - throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST); } catch (Exception e) { - log.error("[RestClientException] {} : {}", "Nginx Conf Test (forwarding)", e.getMessage()); try { Files.move(Paths.get(deletePath), Paths.get(confPath)); } catch (IOException e1) { @@ -315,16 +271,7 @@ public class ForwardingService { url = "http://nginx:8081/nginx-api/reload"; try { restTemplate.getForEntity(url, String.class); - } catch (HttpServerErrorException.InternalServerError e) { - log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage()); - try { - Files.move(Paths.get(deletePath), Paths.get(confPath)); - } catch (IOException e1) { - throw new CustomException(ErrorCode.FAIL_ROLL_BACK, "(포트포워딩 Conf 삭제)"); - } - throw new CustomException(ErrorCode.FAIL_NGINX_CONF_RELOAD); } catch (Exception e) { - log.error("[RestClientException] {} : {}", "Nginx Conf Reload (forwarding)", e.getMessage()); try { Files.move(Paths.get(deletePath), Paths.get(confPath)); } catch (IOException e1) { diff --git a/src/main/java/com/aolda/itda/service/routing/RoutingService.java b/src/main/java/com/aolda/itda/service/routing/RoutingService.java index 7b30c9127796b6dda07d65207a0bc37abbdb9b92..769278d2c6aca1a1f7e4f7afb11a3281e8e7fd07 100644 --- a/src/main/java/com/aolda/itda/service/routing/RoutingService.java +++ b/src/main/java/com/aolda/itda/service/routing/RoutingService.java @@ -102,7 +102,6 @@ public class RoutingService { throw new CustomException(ErrorCode.FAIL_CREATE_CONF, "중복된 라우팅 Conf 파일이 존재합니다"); } } catch (IOException e) { - e.printStackTrace(); throw new CustomException(ErrorCode.FAIL_CREATE_CONF); } @@ -113,7 +112,6 @@ public class RoutingService { bw.flush(); bw.close(); } catch (Exception e) { - e.printStackTrace(); if (file.delete()) { throw new CustomException(ErrorCode.FAIL_DELETE_CONF); } @@ -124,14 +122,7 @@ public class RoutingService { String url = "http://nginx:8081/nginx-api/test"; try { restTemplate.getForEntity(url, String.class); - } catch (HttpServerErrorException.InternalServerError e) { - log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage()); - if (file.delete()) { - throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST, "(롤백 실패)"); - } - throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST); } catch (Exception e) { - log.error("[RestClientException] {} : {}", "Nginx Conf Test (forwarding)", e.getMessage()); if (file.delete()) { throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST, "(롤백 실패)"); } @@ -142,14 +133,7 @@ public class RoutingService { url = "http://nginx:8081/nginx-api/reload"; try { restTemplate.getForEntity(url, String.class); - } catch (HttpServerErrorException.InternalServerError e) { - log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage()); - if (file.delete()) { - throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST, "(롤백 실패)"); - } - throw new CustomException(ErrorCode.FAIL_NGINX_CONF_RELOAD); } catch (Exception e) { - log.error("[RestClientException] {} : {}", "Nginx Conf Reload (forwarding)", e.getMessage()); if (file.delete()) { throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST, "(롤백 실패)"); } @@ -199,7 +183,6 @@ public class RoutingService { bw.flush(); bw.close(); } catch (Exception e) { - e.printStackTrace(); throw new CustomException(ErrorCode.FAIL_UPDATE_CONF, "라우팅 Conf 파일을 수정하지 못했습니다"); } @@ -207,19 +190,7 @@ public class RoutingService { String url = "http://nginx:8081/nginx-api/test"; try { restTemplate.getForEntity(url, String.class); - } catch (HttpServerErrorException.InternalServerError e) { - log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage()); - try { - Files.copy(backup, Paths.get(confPath), StandardCopyOption.REPLACE_EXISTING - , StandardCopyOption.COPY_ATTRIBUTES); - Files.delete(backup); - } catch (IOException e1) { - throw new CustomException(ErrorCode.FAIL_UPDATE_CONF, "(라우팅 Conf 파일 수정)"); - } - - throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST); } catch (RuntimeException e) { - log.error("[RestClientException] {} : {}", "Nginx Conf Test (forwarding)", e.getMessage()); try { Files.copy(backup, Paths.get(confPath), StandardCopyOption.REPLACE_EXISTING , StandardCopyOption.COPY_ATTRIBUTES); @@ -234,18 +205,7 @@ public class RoutingService { url = "http://nginx:8081/nginx-api/reload"; try { restTemplate.getForEntity(url, String.class); - } catch (HttpServerErrorException.InternalServerError e) { - log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage()); - try { - Files.copy(backup, Paths.get(confPath), StandardCopyOption.REPLACE_EXISTING - , StandardCopyOption.COPY_ATTRIBUTES); - Files.delete(backup); - } catch (IOException e1) { - throw new CustomException(ErrorCode.FAIL_UPDATE_CONF, "(라우팅 Conf 파일 수정)"); - } - throw new CustomException(ErrorCode.FAIL_NGINX_CONF_RELOAD); } catch (RuntimeException e) { - log.error("[RestClientException] {} : {}", "Nginx Conf Reload (forwarding)", e.getMessage()); try { Files.copy(backup, Paths.get(confPath), StandardCopyOption.REPLACE_EXISTING , StandardCopyOption.COPY_ATTRIBUTES); @@ -281,16 +241,7 @@ public class RoutingService { String url = "http://nginx:8081/nginx-api/test"; try { restTemplate.getForEntity(url, String.class); - } catch (HttpServerErrorException.InternalServerError e) { - log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage()); - try { - Files.move(Paths.get(deletePath), Paths.get(confPath)); - } catch (IOException e1) { - throw new CustomException(ErrorCode.FAIL_ROLL_BACK, "(라우팅 Conf 삭제)"); - } - throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST); } catch (Exception e) { - log.error("[RestClientException] {} : {}", "Nginx Conf Test (forwarding)", e.getMessage()); try { Files.move(Paths.get(deletePath), Paths.get(confPath)); } catch (IOException e1) { @@ -303,16 +254,7 @@ public class RoutingService { url = "http://nginx:8081/nginx-api/reload"; try { restTemplate.getForEntity(url, String.class); - } catch (HttpServerErrorException.InternalServerError e) { - log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage()); - try { - Files.move(Paths.get(deletePath), Paths.get(confPath)); - } catch (IOException e1) { - throw new CustomException(ErrorCode.FAIL_ROLL_BACK, "(라우팅 Conf 삭제)"); - } - throw new CustomException(ErrorCode.FAIL_NGINX_CONF_RELOAD); } catch (Exception e) { - log.error("[RestClientException] {} : {}", "Nginx Conf Reload (forwarding)", e.getMessage()); try { Files.move(Paths.get(deletePath), Paths.get(confPath)); } catch (IOException e1) { diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000000000000000000000000000000000000..a8acbeebcfc82e73b691923bbf927ec007d9648e --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration> + + <property name="MAX_FILE_SIZE" value="10MB" /> + <property name="TOTAL_SIZE" value="1GB" /> + <property name="MAX_HISTORY" value="30" /> + + <!-- 콘솔에 출력할 로그 형식 --> + <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern>[%d{yyyy-MM-dd HH:mm:ss}] [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + </appender> + + <!-- INFO 로그 파일 저장 (1개당 10MB, 5개까지 유지, 이후 압축) --> + <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>/data/logs/info.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>/data/logs/info.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern> + <maxHistory>${MAX_HISTORY}</maxHistory> + <totalSizeCap>${TOTAL_SIZE}</totalSizeCap> + <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> + <maxFileSize>${MAX_FILE_SIZE}</maxFileSize> + </timeBasedFileNamingAndTriggeringPolicy> + </rollingPolicy> + <encoder> + <pattern>[%d{yyyy-MM-dd HH:mm:ss}] [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + <!-- INFO 레벨만 허용 --> + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>INFO</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + </appender> + + <!-- WARN 로그 파일 저장 --> + <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>/data/logs/warn.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>/data/logs/warn.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern> + <maxHistory>${MAX_HISTORY}</maxHistory> + <totalSizeCap>${TOTAL_SIZE}</totalSizeCap> + <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> + <maxFileSize>${MAX_FILE_SIZE}</maxFileSize> + </timeBasedFileNamingAndTriggeringPolicy> + </rollingPolicy> + <encoder> + <pattern>[%d{yyyy-MM-dd HH:mm:ss}] [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + <!-- WARN 레벨만 허용 --> + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>WARN</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + </appender> + + <!-- ERROR 로그 파일 저장 --> + <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>/data/logs/error.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>/data/logs/error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern> + <maxHistory>${MAX_HISTORY}</maxHistory> + <totalSizeCap>${TOTAL_SIZE}</totalSizeCap> + <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> + <maxFileSize>${MAX_FILE_SIZE}</maxFileSize> + </timeBasedFileNamingAndTriggeringPolicy> + </rollingPolicy> + <encoder> + <pattern>[%d{yyyy-MM-dd HH:mm:ss}] [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + <!-- ERROR 레벨만 허용 --> + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>ERROR</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + </appender> + + <logger name="com.aolda.itda" additivity="false"> + <!-- 각 Appender 참조 (필터는 Appender 내부에 정의됨) --> + <appender-ref ref="INFO_FILE"/> + <appender-ref ref="WARN_FILE"/> + <appender-ref ref="ERROR_FILE"/> + <!-- 콘솔 출력 --> + <appender-ref ref="CONSOLE"/> + </logger> + +</configuration> \ No newline at end of file