From fcb0912a1fa24cd03e1fc86a90b61373b727a991 Mon Sep 17 00:00:00 2001 From: fervovita Date: Sun, 26 Jul 2026 20:43:16 +0900 Subject: [PATCH 1/3] =?UTF-8?q?Feat(deploy):=20=EB=B0=B0=ED=8F=AC=EB=A5=BC?= =?UTF-8?q?=20docker=20compose=20=EB=B0=A9=EC=8B=9D=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=A0=84=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.prod.yaml | 18 ++++++++++++++++++ docker-compose.yaml | 10 ++++++++++ 2 files changed, 28 insertions(+) create mode 100644 docker-compose.prod.yaml create mode 100644 docker-compose.yaml diff --git a/docker-compose.prod.yaml b/docker-compose.prod.yaml new file mode 100644 index 0000000..8900b38 --- /dev/null +++ b/docker-compose.prod.yaml @@ -0,0 +1,18 @@ +services: + ditda-notification-worker: + image: ${ECR_REGISTRY}:${IMAGE_TAG:-latest} + container_name: ditda-notification-worker + restart: unless-stopped + labels: + ditda.logs.app: "ditda" + ditda.logs.service: "ditda-notification-worker" + ports: + - "127.0.0.1:8083:8080" + env_file: .env + networks: + - ditda-net + + +networks: + ditda-net: + external: true \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..3fc4f47 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,10 @@ +services: + mailpit: + image: axllent/mailpit:v1.21 + container_name: ditda-mailpit + ports: + - "127.0.0.1:1025:1025" # SMTP + - "127.0.0.1:8025:8025" # 웹 UI + environment: + MP_SMTP_AUTH_ACCEPT_ANY: 1 + MP_SMTP_AUTH_ALLOW_INSECURE: 1 \ No newline at end of file From 33304c1c935ffe9d8b1c01e567d985e79565757d Mon Sep 17 00:00:00 2001 From: fervovita Date: Sun, 26 Jul 2026 20:44:57 +0900 Subject: [PATCH 2/3] =?UTF-8?q?Feat(monitoring):=20=EB=A9=94=ED=8A=B8?= =?UTF-8?q?=EB=A6=AD/=ED=8A=B8=EB=A0=88=EC=9D=B4=EC=8A=A4/=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A7=91=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 6 +- build.gradle | 110 +++++++++--------- scripts/deploy.sh | 13 +-- .../notification/config/RabbitConfig.java | 18 +++ src/main/resources/application.yaml | 34 +++++- src/main/resources/logback-spring.xml | 39 +++++++ src/test/resources/application-test.yaml | 8 +- 7 files changed, 165 insertions(+), 63 deletions(-) create mode 100644 src/main/resources/logback-spring.xml diff --git a/.env.example b/.env.example index 2f5da66..65b593a 100644 --- a/.env.example +++ b/.env.example @@ -8,4 +8,8 @@ RABBITMQ_PASSWORD=your_password MAIL_HOST=smtp.gmail.com MAIL_PORT=587 MAIL_USERNAME=your_mail -MAIL_PASSWORD=your_mail_password \ No newline at end of file +MAIL_PASSWORD=your_mail_password + +# Tracing +OTLP_TRACING_ENABLED=false +OTLP_TRACING_ENDPOINT=http://ditda-alloy:4318/v1/traces \ No newline at end of file diff --git a/build.gradle b/build.gradle index 0fc49e9..045ca3e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,84 +1,90 @@ plugins { - id 'java' - id 'org.springframework.boot' version '4.0.6' - id 'io.spring.dependency-management' version '1.1.7' - id 'com.google.cloud.tools.jib' version '3.5.3' - id 'checkstyle' + id 'java' + id 'org.springframework.boot' version '4.0.6' + id 'io.spring.dependency-management' version '1.1.7' + id 'com.google.cloud.tools.jib' version '3.5.3' + id 'checkstyle' } group = 'ditda' version = '0.0.1-SNAPSHOT' java { - toolchain { - languageVersion = JavaLanguageVersion.of(21) - } + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } } repositories { - mavenCentral() + mavenCentral() } dependencies { - // web - implementation 'org.springframework.boot:spring-boot-starter-webmvc' + // web + implementation 'org.springframework.boot:spring-boot-starter-webmvc' - // rabbitMQ - implementation 'org.springframework.boot:spring-boot-starter-amqp' + // rabbitMQ + implementation 'org.springframework.boot:spring-boot-starter-amqp' - // email - implementation 'org.springframework.boot:spring-boot-starter-mail' - implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + // email + implementation 'org.springframework.boot:spring-boot-starter-mail' + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' - // actuator - implementation 'org.springframework.boot:spring-boot-starter-actuator' + // monitoring + implementation 'org.springframework.boot:spring-boot-starter-actuator' + runtimeOnly 'io.micrometer:micrometer-registry-prometheus' - // lombok - compileOnly 'org.projectlombok:lombok' - annotationProcessor 'org.projectlombok:lombok' - testCompileOnly 'org.projectlombok:lombok' - testAnnotationProcessor 'org.projectlombok:lombok' + // tracing + implementation 'org.springframework.boot:spring-boot-micrometer-tracing-opentelemetry' + implementation 'io.micrometer:micrometer-tracing-bridge-otel' + implementation 'io.opentelemetry:opentelemetry-exporter-otlp' - // test - testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test' - testImplementation 'org.springframework.boot:spring-boot-starter-amqp-test' - testImplementation 'org.springframework.boot:spring-boot-starter-thymeleaf-test' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + // lombok + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + testCompileOnly 'org.projectlombok:lombok' + testAnnotationProcessor 'org.projectlombok:lombok' + + // test + testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test' + testImplementation 'org.springframework.boot:spring-boot-starter-amqp-test' + testImplementation 'org.springframework.boot:spring-boot-starter-thymeleaf-test' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } // CheckStyle checkstyle { - toolVersion = '13.4.1' - configFile = file("${rootDir}/config/checkstyle/checkstyle-rules.xml") - configProperties = [ - 'suppressionFile': "${rootDir}/config/checkstyle/checkstyle-suppressions.xml" - ] - maxWarnings = 0 + toolVersion = '13.4.1' + configFile = file("${rootDir}/config/checkstyle/checkstyle-rules.xml") + configProperties = [ + 'suppressionFile': "${rootDir}/config/checkstyle/checkstyle-suppressions.xml" + ] + maxWarnings = 0 } // Jib jib { - from { - image = 'eclipse-temurin:21-jre-alpine' - platforms { - platform { - architecture = 'amd64' - os = 'linux' - } - } - } - container { - ports = ['8080'] - environment = [ - 'TZ': 'Asia/Seoul' - ] - jvmFlags = ['-Xms256m', '-Xmx256m', '-XX:+UseG1GC'] - creationTime = 'USE_CURRENT_TIMESTAMP' - } + from { + image = 'eclipse-temurin:21-jre-alpine' + platforms { + platform { + architecture = 'amd64' + os = 'linux' + } + } + } + container { + ports = ['8080'] + environment = [ + 'TZ': 'Asia/Seoul' + ] + jvmFlags = ['-Xms256m', '-Xmx256m', '-XX:+UseG1GC'] + creationTime = 'USE_CURRENT_TIMESTAMP' + } } tasks.named('test') { - useJUnitPlatform() + useJUnitPlatform() } \ No newline at end of file diff --git a/scripts/deploy.sh b/scripts/deploy.sh index f21eb7f..3bdd007 100644 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -60,6 +60,10 @@ REQUIRED_VARS=( "MAIL_PORT" "MAIL_USERNAME" "MAIL_PASSWORD" + +# Tracing +"OTLP_TRACING_ENABLED" +"OTLP_TRACING_ENDPOINT" ) MISSING=() @@ -81,14 +85,7 @@ echo " 필수 환경변수 ${#REQUIRED_VARS[@]}개 모두 존재 확인" # === 컨테이너 교체 === echo "[4/5] 컨테이너 교체" -docker rm -f ditda-notification-worker 2>/dev/null || true -docker run -d --name ditda-notification-worker \ - --network ditda-net \ - --restart unless-stopped \ - --env-file .env \ - -p 127.0.0.1:8083:8080 \ - "${ECR_REGISTRY}:${IMAGE_TAG}" - +docker compose -f docker-compose.prod.yaml up -d # === Health Check === echo "[5/5] Health Check" diff --git a/src/main/java/ditda/notification/config/RabbitConfig.java b/src/main/java/ditda/notification/config/RabbitConfig.java index db50920..0bf9b12 100644 --- a/src/main/java/ditda/notification/config/RabbitConfig.java +++ b/src/main/java/ditda/notification/config/RabbitConfig.java @@ -1,8 +1,11 @@ package ditda.notification.config; +import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.support.converter.JacksonJavaTypeMapper; import org.springframework.amqp.support.converter.JacksonJsonMessageConverter; import org.springframework.amqp.support.converter.MessageConverter; +import org.springframework.boot.amqp.autoconfigure.SimpleRabbitListenerContainerFactoryConfigurer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -16,4 +19,19 @@ public MessageConverter messageConverter() { return converter; } + + @Bean + public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory( + SimpleRabbitListenerContainerFactoryConfigurer configurer, + ConnectionFactory connectionFactory, + MessageConverter messageConverter + ) { + SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); + + configurer.configure(factory, connectionFactory); + factory.setMessageConverter(messageConverter); + factory.setObservationEnabled(true); + + return factory; + } } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 677d1da..350edb7 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,6 +1,6 @@ spring: application: - name: notification-worker + name: ditda-notification-worker profiles: active: ${SPRING_PROFILES_ACTIVE:local} @@ -36,3 +36,35 @@ spring: connectiontimeout: 5000 timeout: 10000 writetimeout: 10000 + +management: + endpoints: + web: + exposure: + include: health, prometheus + + endpoint: + health: + show-details: never + + otlp: + metrics: + export: + enabled: false + + opentelemetry: + tracing: + export: + otlp: + endpoint: ${OTLP_TRACING_ENDPOINT:http://localhost:4318/v1/traces} + + tracing: + sampling: + probability: 1.0 + export: + otlp: + enabled: ${OTLP_TRACING_ENABLED} + + metrics: + tags: + application: ${spring.application.name} \ No newline at end of file diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..23cc779 --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + ${CONSOLE_LOG_PATTERN} + + + + + + + + + + + + logstash + + + + + 512 + 0 + + + + + + \ No newline at end of file diff --git a/src/test/resources/application-test.yaml b/src/test/resources/application-test.yaml index d505587..9505946 100644 --- a/src/test/resources/application-test.yaml +++ b/src/test/resources/application-test.yaml @@ -7,4 +7,10 @@ spring: mail: host: localhost username: test - password: test \ No newline at end of file + password: test + +management: + tracing: + export: + otlp: + enabled: false \ No newline at end of file From ba6a26dcc67de77e7ad7a00bc6496de115236099 Mon Sep 17 00:00:00 2001 From: fervovita Date: Sun, 26 Jul 2026 20:55:07 +0900 Subject: [PATCH 3/3] =?UTF-8?q?Chore:=20.env.example=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=EC=9D=98=20OTLP=5FTRACING=5FENDPOINT=20=EA=B8=B0=EB=B3=B8?= =?UTF-8?q?=EA=B0=92=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 65b593a..f861a0e 100644 --- a/.env.example +++ b/.env.example @@ -12,4 +12,4 @@ MAIL_PASSWORD=your_mail_password # Tracing OTLP_TRACING_ENABLED=false -OTLP_TRACING_ENDPOINT=http://ditda-alloy:4318/v1/traces \ No newline at end of file +OTLP_TRACING_ENDPOINT=http://localhost:4318/v1/traces \ No newline at end of file