From a4e3601022c8f28427a6f16a4ddc09223dbeadda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B6=8C=EC=98=81=ED=83=9C?= <56019823+dudxo@users.noreply.github.com> Date: Sun, 22 Jun 2025 00:08:30 +0900 Subject: [PATCH 1/3] =?UTF-8?q?chore:=20=EB=AA=A8=EB=8B=88=ED=84=B0?= =?UTF-8?q?=EB=A7=81=20=EC=8B=9C=EC=8A=A4=ED=85=9C=20(#115)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: prometheus, actuator 의존 추가 * chore: 모니터링 시스템 관련 스크립트 추가 * feat: JwtFilter WHITELIST actuator 관련 경로 추가 * fix: 모니터링 시스템 로컬 테스트 관련 파일 제거 --- build.gradle | 4 +++- prometheus.yml | 8 ++++++++ .../java/com/ureca/ufit/global/auth/filter/JwtFilter.java | 5 ++++- 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 prometheus.yml diff --git a/build.gradle b/build.gradle index a441712..23b241e 100644 --- a/build.gradle +++ b/build.gradle @@ -110,12 +110,14 @@ dependencies { //ahocorasick implementation 'org.ahocorasick:ahocorasick:0.6.3' + implementation("org.springframework.boot:spring-boot-starter-actuator") + runtimeOnly("io.micrometer:micrometer-registry-prometheus") + compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testCompileOnly 'org.projectlombok:lombok:1.18.22' testAnnotationProcessor 'org.projectlombok:lombok:1.18.22' - testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation "org.junit.jupiter:junit-jupiter:5.8.1" testImplementation 'org.springframework.security:spring-security-test' diff --git a/prometheus.yml b/prometheus.yml new file mode 100644 index 0000000..9e4634f --- /dev/null +++ b/prometheus.yml @@ -0,0 +1,8 @@ +global: + scrape_interval: 15s + +scrape_configs: + - job_name: prometheus + metrics_path: '/actuator/prometheus' + static_configs: + - targets: [ 'host.docker.internal:8080' ] \ No newline at end of file diff --git a/src/main/java/com/ureca/ufit/global/auth/filter/JwtFilter.java b/src/main/java/com/ureca/ufit/global/auth/filter/JwtFilter.java index 95eb567..b44560f 100644 --- a/src/main/java/com/ureca/ufit/global/auth/filter/JwtFilter.java +++ b/src/main/java/com/ureca/ufit/global/auth/filter/JwtFilter.java @@ -40,7 +40,10 @@ public class JwtFilter extends OncePerRequestFilter { "/api/rateplans/storages", "/api/rateplans/storages/{rateplanId}", "/api/auth/reissue/token", - "/api/auth/logout" + "/api/auth/logout", + "/actuator/health/**", + "/actuator/prometheus", + "/actuator/info" ); // 비회원이면 JWT검증 필요X, 회원이면 JWT검증 필요 From c5e9565f631f3a9b70f1e4413d4d3de747888544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B6=8C=EC=98=81=ED=83=9C?= <56019823+dudxo@users.noreply.github.com> Date: Sun, 22 Jun 2025 02:34:32 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20RestTemplate=20+=20Async=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#119)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Async Config 추가 * feat: RestTemplate + Async 추가 --- .../domain/chatbot/service/ChatBotMessageService.java | 2 ++ .../java/com/ureca/ufit/global/config/AsyncConfig.java | 9 +++++++++ 2 files changed, 11 insertions(+) create mode 100644 src/main/java/com/ureca/ufit/global/config/AsyncConfig.java diff --git a/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotMessageService.java b/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotMessageService.java index ffe3cfc..d250ce8 100644 --- a/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotMessageService.java +++ b/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotMessageService.java @@ -6,6 +6,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Pageable; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @@ -43,6 +44,7 @@ public CursorPageResponse getChatMessages(Long chatRoomId, Pagea return chatBotMessageRepository.findMessagesPage(findChatRoom, pageable, lastMessageId); } + @Async public CreateChatBotMessageResponse createChatBotMessage(CreateChatBotMessageRequest request, Long userId) { Set policies = Set.of(NUMBERS, WHITESPACES); diff --git a/src/main/java/com/ureca/ufit/global/config/AsyncConfig.java b/src/main/java/com/ureca/ufit/global/config/AsyncConfig.java new file mode 100644 index 0000000..a5230ea --- /dev/null +++ b/src/main/java/com/ureca/ufit/global/config/AsyncConfig.java @@ -0,0 +1,9 @@ +package com.ureca.ufit.global.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; + +@Configuration +@EnableAsync +public class AsyncConfig { +} From 0e66a4262a40e846ed991bc4dbfe4914e1a52357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B6=8C=EC=98=81=ED=83=9C?= <56019823+dudxo@users.noreply.github.com> Date: Sun, 22 Jun 2025 03:55:55 +0900 Subject: [PATCH 3/3] =?UTF-8?q?Fix:=20Async=20Return=20=ED=83=80=EC=9E=85?= =?UTF-8?q?=20=EC=9D=BC=EC=B9=98=20(#123)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Async Config 추가 * feat: RestTemplate + Async 추가 * fix: async 반환 타입에 맞게 CompletableFuture 변경 --- .../ufit/domain/chatbot/controller/ChatBotController.java | 8 ++++++-- .../chatbot/controller/ChatBotControllerApiSpec.java | 4 +++- .../domain/chatbot/service/ChatBotMessageService.java | 8 ++++++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/ureca/ufit/domain/chatbot/controller/ChatBotController.java b/src/main/java/com/ureca/ufit/domain/chatbot/controller/ChatBotController.java index 2f25906..bcae2f2 100644 --- a/src/main/java/com/ureca/ufit/domain/chatbot/controller/ChatBotController.java +++ b/src/main/java/com/ureca/ufit/domain/chatbot/controller/ChatBotController.java @@ -1,5 +1,7 @@ package com.ureca.ufit.domain.chatbot.controller; +import java.util.concurrent.CompletableFuture; + import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -50,12 +52,14 @@ public ResponseEntity createChatBotReview(CreateCha } @Override - public ResponseEntity createChatBotMessage(CustomUserDetails userDetails, + public ResponseEntity> createChatBotMessage( + CustomUserDetails userDetails, CreateChatBotMessageRequest request) { Long userId = (userDetails != null) ? userDetails.userId() : nonUserId; - CreateChatBotMessageResponse response = chatBotMessageService.createChatBotMessage(request, userId); + CompletableFuture response = chatBotMessageService.createChatBotMessage(request, + userId); return ResponseEntity.status(HttpStatus.CREATED).body(response); } diff --git a/src/main/java/com/ureca/ufit/domain/chatbot/controller/ChatBotControllerApiSpec.java b/src/main/java/com/ureca/ufit/domain/chatbot/controller/ChatBotControllerApiSpec.java index 7e0787a..97269c4 100644 --- a/src/main/java/com/ureca/ufit/domain/chatbot/controller/ChatBotControllerApiSpec.java +++ b/src/main/java/com/ureca/ufit/domain/chatbot/controller/ChatBotControllerApiSpec.java @@ -1,5 +1,7 @@ package com.ureca.ufit.domain.chatbot.controller; +import java.util.concurrent.CompletableFuture; + import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; import org.springframework.http.ResponseEntity; @@ -107,7 +109,7 @@ public ResponseEntity createChatBotReview( content = @Content(schema = @Schema(implementation = CreateChatBotMessageResponse.class)) )) @PostMapping("/message") - public ResponseEntity createChatBotMessage( + public ResponseEntity> createChatBotMessage( @Parameter(hidden = true) @AuthenticationPrincipal CustomUserDetails userDetails, @RequestBody @Valid CreateChatBotMessageRequest request diff --git a/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotMessageService.java b/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotMessageService.java index d250ce8..5b9dcf9 100644 --- a/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotMessageService.java +++ b/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotMessageService.java @@ -3,6 +3,7 @@ import static com.ureca.ufit.global.profanity.BanwordFilterPolicy.*; import java.util.Set; +import java.util.concurrent.CompletableFuture; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Pageable; @@ -45,7 +46,9 @@ public CursorPageResponse getChatMessages(Long chatRoomId, Pagea } @Async - public CreateChatBotMessageResponse createChatBotMessage(CreateChatBotMessageRequest request, Long userId) { + public CompletableFuture createChatBotMessage(CreateChatBotMessageRequest request, + Long userId) { + Set policies = Set.of(NUMBERS, WHITESPACES); @@ -58,11 +61,12 @@ public CreateChatBotMessageResponse createChatBotMessage(CreateChatBotMessageReq CreateAIAnswerRequest createAIAnswerRequest = ChatMessageMapper.toCreateAIAnswerRequest(request, userId); try { - return restTemplate.postForObject( + CreateChatBotMessageResponse response = restTemplate.postForObject( fastApiUrl, createAIAnswerRequest, CreateChatBotMessageResponse.class ); + return CompletableFuture.completedFuture(response); } catch (Exception e) { throw new RestApiException(ChatBotErrorCode.LLM_TIMEOUT);