Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -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
MAIL_PASSWORD=your_mail_password

# Tracing
OTLP_TRACING_ENABLED=false
OTLP_TRACING_ENDPOINT=http://localhost:4318/v1/traces
110 changes: 58 additions & 52 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -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()
}
18 changes: 18 additions & 0 deletions docker-compose.prod.yaml
Original file line number Diff line number Diff line change
@@ -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
10 changes: 10 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -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
13 changes: 5 additions & 8 deletions scripts/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ REQUIRED_VARS=(
"MAIL_PORT"
"MAIL_USERNAME"
"MAIL_PASSWORD"

# Tracing
"OTLP_TRACING_ENABLED"
"OTLP_TRACING_ENDPOINT"
)

MISSING=()
Expand All @@ -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
Comment thread
fervovita marked this conversation as resolved.

# === Health Check ===
echo "[5/5] Health Check"
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/ditda/notification/config/RabbitConfig.java
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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;
}
}
34 changes: 33 additions & 1 deletion src/main/resources/application.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
spring:
application:
name: notification-worker
name: ditda-notification-worker
profiles:
active: ${SPRING_PROFILES_ACTIVE:local}

Expand Down Expand Up @@ -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}
39 changes: 39 additions & 0 deletions src/main/resources/logback-spring.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

<springProperty scope="context" name="appName" source="spring.application.name"/>

<!-- [appName,traceId,spanId] LEVEL PID - [thread] logger: message -->
<property name="CONSOLE_LOG_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} %magenta([${appName},%X{traceId:-},%X{spanId:-}]) %highlight(%-5level) %yellow(${PID:-}) --- [%thread] %cyan(%-40logger{39}) : %m%n"/>


<!-- 로컬 환경 -->
<springProfile name="local">
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
</root>
</springProfile>

<!-- 운영 환경 -->
<springProfile name="prod">
<appender name="JSON" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="org.springframework.boot.logging.logback.StructuredLogEncoder">
<format>logstash</format>
</encoder>
</appender>
<appender name="ASYNC_JSON" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="JSON"/>
<queueSize>512</queueSize>
<discardingThreshold>0</discardingThreshold>
</appender>
Comment thread
fervovita marked this conversation as resolved.
<root level="INFO">
<appender-ref ref="ASYNC_JSON"/>
</root>
</springProfile>
</configuration>
8 changes: 7 additions & 1 deletion src/test/resources/application-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,10 @@ spring:
mail:
host: localhost
username: test
password: test
password: test

management:
tracing:
export:
otlp:
enabled: false