From dcb2fe21d5a397cf312ec16e1da346dae0833dc0 Mon Sep 17 00:00:00 2001 From: eedo_y Date: Wed, 3 Sep 2025 16:45:09 +0900 Subject: [PATCH 1/6] =?UTF-8?q?=E2=9C=A8=20feat/KIKI-75=20:=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20=EC=8A=A4=ED=83=9C=EC=8B=9C=20=ED=99=9C=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EC=97=AC=20=EB=A1=9C=EC=BB=AC=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 ++- docker/dev-docker-compose.yml | 21 +++++++++++++++ docker/docker-compose.yml | 23 ++++++++++++++++ .../custom/global/logging/LogFilter.java | 6 +++-- .../custom/global/logging/LoggingAspect.java | 27 +++++++++---------- 5 files changed, 63 insertions(+), 17 deletions(-) diff --git a/build.gradle b/build.gradle index 190f23e..446292d 100644 --- a/build.gradle +++ b/build.gradle @@ -51,7 +51,6 @@ dependencies { testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testImplementation 'org.springframework.security:spring-security-test' - // Swagger 관련 implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0' @@ -61,6 +60,8 @@ dependencies { // elasticSearch implementation 'org.springframework.boot:spring-boot-starter-data-elasticsearch' + // Log 관련 + implementation("net.logstash.logback:logstash-logback-encoder:7.4") } diff --git a/docker/dev-docker-compose.yml b/docker/dev-docker-compose.yml index 185da60..dc62d00 100644 --- a/docker/dev-docker-compose.yml +++ b/docker/dev-docker-compose.yml @@ -62,3 +62,24 @@ services: interval: 10s timeout: 10s retries: 120 + + logstash01: + container_name: kkh-logstash + ports: + - "5044:5044" + depends_on: + es01: + condition: service_healthy + kibana: + condition: service_healthy + image: docker.elastic.co/logstash/logstash:${STACK_VERSION} + labels: + co.elastic.logs/module: logstash + user: root + volumes: + - "./logstash/logstash.conf:/usr/share/logstash/pipeline/logstash.conf:ro" + environment: + - xpack.monitoring.enabled=true + - ELASTIC_USER=elastic + - ELASTIC_PASSWORD=${ELASTIC_PASSWORD} + - ELASTIC_HOSTS=http://es01:9200 diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index a10c995..a422502 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -237,6 +237,27 @@ services: timeout: 10s retries: 120 + logstash01: + depends_on: + es01: + condition: service_healthy + kibana: + condition: service_healthy + image: docker.elastic.co/logstash/logstash:${STACK_VERSION} + labels: + co.elastic.logs/module: logstash + user: root + volumes: + - certs:/usr/share/logstash/certs + - logstashdata01:/usr/share/logstash/data + - "./logstash/logstash_ingest_data/:/usr/share/logstash/ingest_data/" + - "./logstash/logstash.conf:/usr/share/logstash/pipeline/logstash.conf:ro" + environment: + - xpack.monitoring.enabled=true + - ELASTIC_USER=elastic + - ELASTIC_PASSWORD=${ELASTIC_PASSWORD} + - ELASTIC_HOSTS=https://es01:9200 + mongodb1: restart: always image: mongo:latest @@ -326,6 +347,8 @@ volumes: driver: local kibanadata: driver: local + logstashdata01: + driver: local networks: monstache-network: diff --git a/src/main/java/site/kikihi/custom/global/logging/LogFilter.java b/src/main/java/site/kikihi/custom/global/logging/LogFilter.java index c69a5ae..baa06d1 100644 --- a/src/main/java/site/kikihi/custom/global/logging/LogFilter.java +++ b/src/main/java/site/kikihi/custom/global/logging/LogFilter.java @@ -25,11 +25,13 @@ public class LogFilter extends OncePerRequestFilter { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { /// 요청 로그 남기기 - String username = request.getUserPrincipal() != null ? request.getUserPrincipal().getName() : "anonymous"; + String ipAddress = request.getRemoteAddr(); String httpMethod = request.getMethod(); String uri = URLDecoder.decode(request.getRequestURI(), StandardCharsets.UTF_8); + String username = request.getUserPrincipal() != null ? request.getUserPrincipal().getName() : "anonymous"; - log.info("[HTTP 요청 로깅]: [{}] {} - 사용자: {}", httpMethod, uri, username); + /// 로그스태시로 넘길 로깅 출력 + log.info("[HTTP 로깅]: {}, [{}], {}, {}", ipAddress, httpMethod, uri, username); /// 로그 남기고 넘기기 filterChain.doFilter(request, response); diff --git a/src/main/java/site/kikihi/custom/global/logging/LoggingAspect.java b/src/main/java/site/kikihi/custom/global/logging/LoggingAspect.java index 78e193a..7fa2291 100644 --- a/src/main/java/site/kikihi/custom/global/logging/LoggingAspect.java +++ b/src/main/java/site/kikihi/custom/global/logging/LoggingAspect.java @@ -3,11 +3,10 @@ import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; -import java.util.Arrays; - @Aspect @Component @Slf4j @@ -17,25 +16,25 @@ public class LoggingAspect { private void applicationLayer() { } - @Before("applicationLayer()") - public void logMethodEntry(JoinPoint joinPoint) { - log.info("[서비스 로깅] 메서드 진입: {}.{}({})", - joinPoint.getSignature().getDeclaringTypeName(), - joinPoint.getSignature().getName(), - Arrays.toString(joinPoint.getArgs())); - } + @Around("applicationLayer()") + public Object logProcessTime(ProceedingJoinPoint joinPoint) throws Throwable { + long start = System.currentTimeMillis(); - @AfterReturning(pointcut = "applicationLayer()", returning = "result") - public void logMethodExit(JoinPoint joinPoint, Object result) { - log.info("[서비스 로깅] 메서드 종료: {}.{} => 반환: {}", + Object proceed = joinPoint.proceed(); // 실제 메서드 실행 + + long executionTime = System.currentTimeMillis() - start; + + log.info("[서비스 로깅] 메서드 실행 시간: {}.{} 실행 시간 = {}ms", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(), - result); + executionTime); + + return proceed; } @AfterThrowing(pointcut = "applicationLayer()") public void logException(JoinPoint joinPoint) { - log.info("[서비스 로깅] 예외 발생: {}.{}", + log.info("[서비스 로깅] 예외 발생: {},{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName()); } From 9a4023823c717a26cce8208402a68136d6cac744 Mon Sep 17 00:00:00 2001 From: eedo_y Date: Wed, 3 Sep 2025 16:55:13 +0900 Subject: [PATCH 2/6] =?UTF-8?q?=E2=9C=A8=20feat/KIKI-75=20:=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20=EC=8A=A4=ED=83=9C=EC=8B=9C=20=ED=99=9C=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EC=97=AC=20=EB=A1=9C=EA=B7=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/logback-spring.xml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/resources/logback-spring.xml diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..a371ab5 --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,25 @@ + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{36}) - %msg%n + + + + + + 127.0.0.1:5044 + + %msg%n + + + + + + + + + + From ecf0b43266398651d9b56247c6c39105757a8045 Mon Sep 17 00:00:00 2001 From: eedo_y Date: Wed, 3 Sep 2025 18:10:28 +0900 Subject: [PATCH 3/6] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor/KIKI-75=20:?= =?UTF-8?q?=20=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/exception/GlobalExceptionHandler.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/site/kikihi/custom/global/exception/GlobalExceptionHandler.java b/src/main/java/site/kikihi/custom/global/exception/GlobalExceptionHandler.java index 1780d79..468a27c 100644 --- a/src/main/java/site/kikihi/custom/global/exception/GlobalExceptionHandler.java +++ b/src/main/java/site/kikihi/custom/global/exception/GlobalExceptionHandler.java @@ -27,9 +27,12 @@ public class GlobalExceptionHandler { /// 공통 처리 메서드 - private ApiResponse handleCustomException(CustomException customException) { + private ApiResponse handleCustomException(CustomException exception) { - return ApiResponse.fail(customException); + /// 로그 발생 + log.error("[ERROR 로깅] : {}", exception.getMessage()); + + return ApiResponse.fail(exception); } /// 예외 처리 @@ -77,9 +80,6 @@ public ApiResponse handleJwtAuthenticationException(Exception e @ExceptionHandler(Exception.class) public ApiResponse handleException(Exception e) { - /// 로그 발생 - log.error(e.getMessage(), e); - /// 500 예외 코드 검색 ErrorCode errorCode = ErrorCode.INTERNAL_SERVER_ERROR; From 429255ce9a0b5bb5f63c61f41d979b2e21cabfb0 Mon Sep 17 00:00:00 2001 From: eedo_y Date: Wed, 3 Sep 2025 21:59:42 +0900 Subject: [PATCH 4/6] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor/KIKI-75=20:?= =?UTF-8?q?=20CI/CD=20=ED=8C=8C=EC=9D=B4=ED=94=84=EB=9D=BC=EC=9D=B8=20?= =?UTF-8?q?=EB=82=B4=EB=B6=80=20=EB=A1=9C=EA=B7=B8=EC=8A=A4=ED=83=9C?= =?UTF-8?q?=EC=8B=9C=20=EB=B3=80=EC=88=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-ci-cd.yml | 1 + .github/workflows/dev-test.yml | 3 +++ docker/docker-compose.yml | 8 +++++--- src/main/resources/logback-spring.xml | 25 ------------------------- 4 files changed, 9 insertions(+), 28 deletions(-) delete mode 100644 src/main/resources/logback-spring.xml diff --git a/.github/workflows/dev-ci-cd.yml b/.github/workflows/dev-ci-cd.yml index b8bdf11..ccfbe00 100644 --- a/.github/workflows/dev-ci-cd.yml +++ b/.github/workflows/dev-ci-cd.yml @@ -72,6 +72,7 @@ jobs: echo "${{ secrets.APPLICATION_YML }}" > ./src/main/resources/application.yml echo "${{ secrets.APPLICATION_PROD_YML }}" > ./src/main/resources/application-prod.yml echo "${{ secrets.APPLICATION_OAUTH2_YML }}" > ./src/main/resources/application-oauth2.yml + echo "${{ secrets.LOGBACK_SPRING_XML }}" > ./src/main/resources/logback-spring.xml mkdir -p src/test/resources echo "${{ secrets.APPLICATION_TEST_YML }}" > ./src/test/resources/application-test.yml diff --git a/.github/workflows/dev-test.yml b/.github/workflows/dev-test.yml index 9c47718..3c96083 100644 --- a/.github/workflows/dev-test.yml +++ b/.github/workflows/dev-test.yml @@ -84,6 +84,9 @@ jobs: - name: application-oauth2.yml 설정 run: echo "${{ secrets.APPLICATION_OAUTH2_YML }}" > ./src/main/resources/application-oauth2.yml + - name: logback-spring.xml 설정 + run: echo "${{ secrets.LOGBACK_SPRING_XML }}" > ./src/main/resources/logback-spring.xml + - name: application-test.yml 설정 run: | mkdir -p src/test/resources diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index a422502..0c15c53 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -150,7 +150,7 @@ services: setup: condition: service_healthy image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION} - container_name: elasticsearch + container_name: kkh-es labels: co.elastic.logs/module: elasticsearch volumes: @@ -207,7 +207,7 @@ services: es01: condition: service_healthy image: docker.elastic.co/kibana/kibana:${STACK_VERSION} - container_name: kibana + container_name: kkh-kibana labels: co.elastic.logs/module: kibana volumes: @@ -238,6 +238,7 @@ services: retries: 120 logstash01: + container_name: kkh-logstash depends_on: es01: condition: service_healthy @@ -247,10 +248,11 @@ services: labels: co.elastic.logs/module: logstash user: root + ports: + - "5044:5044" volumes: - certs:/usr/share/logstash/certs - logstashdata01:/usr/share/logstash/data - - "./logstash/logstash_ingest_data/:/usr/share/logstash/ingest_data/" - "./logstash/logstash.conf:/usr/share/logstash/pipeline/logstash.conf:ro" environment: - xpack.monitoring.enabled=true diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml deleted file mode 100644 index a371ab5..0000000 --- a/src/main/resources/logback-spring.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{36}) - %msg%n - - - - - - 127.0.0.1:5044 - - %msg%n - - - - - - - - - - From fed51b022a5bdbe1b35d63ab1f19cf03e2d210e9 Mon Sep 17 00:00:00 2001 From: eedo_y Date: Wed, 3 Sep 2025 23:48:58 +0900 Subject: [PATCH 5/6] =?UTF-8?q?=F0=9F=94=A8=20chore/KIKI-48=20:=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=B4=ED=94=84=EB=9D=BC=EC=9D=B8=20=EB=82=B4?= =?UTF-8?q?=EB=B6=80=20=EB=A1=9C=EA=B7=B8=EC=8A=A4=ED=83=9C=EC=8B=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-test.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/.github/workflows/dev-test.yml b/.github/workflows/dev-test.yml index 3c96083..73a3fb4 100644 --- a/.github/workflows/dev-test.yml +++ b/.github/workflows/dev-test.yml @@ -52,6 +52,18 @@ jobs: discovery.type: single-node ES_JAVA_OPTS: "-Xms512m -Xmx512m" + logstash: + image: docker.elastic.co/logstash/logstash:7.17.0 + ports: + - 5044:5044 + options: >- + --health-cmd "curl -f http://localhost:5044/_node/pipelines || exit 1" + --health-interval 10s + --health-timeout 5s + --health-retries 10 + env: + LS_JAVA_OPTS: "-Xms256m -Xmx256m" + permissions: contents: write checks: write @@ -92,6 +104,9 @@ jobs: mkdir -p src/test/resources echo "${{ secrets.APPLICATION_TEST_YML }}" > ./src/test/resources/application-test.yml + - name: logback-test.xml 설정 + run: echo "${{ secrets.LOGBACK_TEST_XML }}" > ./src/main/resources/logback-test.xml + # 5. 캐싱 - name: Gradle Caching uses: actions/cache@v3 @@ -132,6 +147,14 @@ jobs: sleep 5 done + - name: Logstash 체크 + run: | + until nc -z localhost 5044; do + echo "Waiting for Logstash..." + sleep 3 + done + + # 5-2. Nori 플러그인 설치 - name: Install Nori plugin run: | From b0e44d2fa681082b3b3b20f7d0e853e3c022867d Mon Sep 17 00:00:00 2001 From: eedo_y Date: Wed, 3 Sep 2025 23:58:04 +0900 Subject: [PATCH 6/6] =?UTF-8?q?=F0=9F=94=A8=20chore/KIKI-48=20:=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=B4=ED=94=84=EB=9D=BC=EC=9D=B8=20=EB=82=B4?= =?UTF-8?q?=EB=B6=80=20=EB=A1=9C=EA=B7=B8=EC=8A=A4=ED=83=9C=EC=8B=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-test.yml | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/.github/workflows/dev-test.yml b/.github/workflows/dev-test.yml index 73a3fb4..1224b28 100644 --- a/.github/workflows/dev-test.yml +++ b/.github/workflows/dev-test.yml @@ -52,18 +52,6 @@ jobs: discovery.type: single-node ES_JAVA_OPTS: "-Xms512m -Xmx512m" - logstash: - image: docker.elastic.co/logstash/logstash:7.17.0 - ports: - - 5044:5044 - options: >- - --health-cmd "curl -f http://localhost:5044/_node/pipelines || exit 1" - --health-interval 10s - --health-timeout 5s - --health-retries 10 - env: - LS_JAVA_OPTS: "-Xms256m -Xmx256m" - permissions: contents: write checks: write @@ -105,7 +93,7 @@ jobs: echo "${{ secrets.APPLICATION_TEST_YML }}" > ./src/test/resources/application-test.yml - name: logback-test.xml 설정 - run: echo "${{ secrets.LOGBACK_TEST_XML }}" > ./src/main/resources/logback-test.xml + run: echo "${{ secrets.LOGBACK_TEST_XML }}" > ./src/test/resources/logback-test.xml # 5. 캐싱 - name: Gradle Caching @@ -147,14 +135,6 @@ jobs: sleep 5 done - - name: Logstash 체크 - run: | - until nc -z localhost 5044; do - echo "Waiting for Logstash..." - sleep 3 - done - - # 5-2. Nori 플러그인 설치 - name: Install Nori plugin run: |