Conversation
📝 WalkthroughSummary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings. 개요OpenTelemetry 기반 메트릭 수집 기능을 활성화하기 위해 의존성을 추가하고 관리 엔드포인트 및 OTLP 메트릭 내보내기를 구성했습니다. 기존 로직 변경 없이 설정 및 라이브러리 선언만 추가되었습니다. 변경 사항
코드 리뷰 예상 소요 시간🎯 1 (간단함) | ⏱️ ~5분
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
build.gradle (1)
33-34: OpenTelemetry 의존성에 명시적 버전 지정 필요추가된 세 가지 OTEL 의존성이 명시적 버전 번호 없이 선언되었습니다. 이는 전이 의존성 버전 충돌을 초래할 수 있으며, Spring Boot 3.5.7 및 기존 micrometer 스택과의 호환성 확인이 필요합니다.
권장사항:
- Spring Boot의 BOM(Bill of Materials) 버전과 정렬된 명시적 버전 지정
- 예:
io.micrometer:micrometer-tracing-bridge-otel:1.x.x및io.opentelemetry:opentelemetry-exporter-otlp:1.x.xAlso applies to: 52-52
src/main/resources/application.yml (1)
49-52: metrics.tags 설정이 부분적으로만 환경 변수화됨
management.metrics.tags설정에서application태그는 정적 값을 사용하지만, 네임스페이스는 환경 변수를 사용하고 있습니다. 일관성 유지를 위해 다른 태그들도 환경 변수로 제공되는지 확인하거나, 둘 다 정적으로 설정할 것을 권장합니다.현재 설정에서
K8S_NAMESPACE환경 변수가 정의되지 않으면unknown으로 설정되는데, OTEL 수집기 URL이 하드코딩되어 있으므로 두 설정 간의 불일치가 발생할 수 있습니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
build.gradle(2 hunks)src/main/resources/application.yml(1 hunks)
🔇 Additional comments (2)
src/main/resources/application.yml (2)
54-61: Simple 및 Prometheus 메트릭 내보내기 비활성화 확인Simple 및 Prometheus 메트릭 내보내기가 명시적으로 비활성화되었습니다. 이는 OTLP로의 단일 메트릭 내보내기 경로를 보장하는 좋은 설정입니다.
42-42: Actuator 엔드포인트 노출 변경 확인
management.endpoints.web.exposure.include이health에서health,info,metrics로 확장되었습니다. 메트릭 수집을 위한/actuator/metrics엔드포인트를 노출하는 것이 목적으로 보이며, 이는 적절합니다.보안 검토: 프로덕션 환경에서 이러한 엔드포인트 노출이 의도된 것인지, 필요한 인증/권한 설정이 있는지 확인하세요.
| otlp: | ||
| metrics: | ||
| export: | ||
| url: http://ipiece-otel-collector.monitoring:4318/v1/metrics | ||
| step: 5s |
There was a problem hiding this comment.
🧩 Analysis chain
Script executed:
#!/bin/bash
# First, find and read the application.yml file
find . -name "application.yml" -type f | head -20Repository: Woori-FISA-Go/IPiece-server
<shell_result>
Repository: Woori-FISA-Go/IPiece-server
Exit code: 0
stdout:
./src/main/resources/application.yml
./src/test/resources/application.yml
</shell_result>
Script executed:
#!/bin/bash
# Read the main application.yml to see the exact configuration
cat -n ./src/main/resources/application.yml | head -70Repository: Woori-FISA-Go/IPiece-server
<shell_result>
Repository: Woori-FISA-Go/IPiece-server
Exit code: 0
stdout:
1 spring:
2 application:
3 name: IPiece
4 profiles:
5 active: local
6 servlet:
7 multipart:
8 max-file-size: 50MB
9 max-request-size: 50MB
10
11
12 datasource:
13 url: jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}
14 username: ${DB_USER}
15 password: ${DB_PASS}
16
17 data:
18 redis:
19 host: ${REDIS_HOST}
20 port: ${REDIS_PORT}
21
22 jpa:
23 hibernate:
24 ddl-auto: update
25 properties:
26 hibernate:
27 format_sql: true
28 highlight_sql: true # (Spring Boot 3.1+) SQL 색상 강조
29 show-sql: true # SQL 쿼리 출력
30
31
32 server:
33 error:
34 include-message: always
35 include-stacktrace: never
36 include-binding-errors: never
37
38 management:
39 endpoints:
40 web:
41 exposure:
42 include: health,info,metrics
43 otlp:
44 metrics:
45 export:
46 url: http://ipiece-otel-collector.monitoring:4318/v1/metrics
47 step: 5s
48
49 metrics:
50 tags:
51 application: ${spring.application.name}
52 namespace: ${K8S_NAMESPACE:unknown}
53
54 simple:
55 metrics:
56 export:
57 enabled: false
58 prometheus:
59 metrics:
60 export:
61 enabled: false
62
63 jwt:
64 secret: ${JWT_SECRET}
65 expiration-ms: 241920000 # AccessToken 28일 -> 개발 완료 후 조정 필요
66 refresh-expiration-ms: 604800000 # RefreshToken 7일
67
68 krwt:
69 contract:
70 address: ${KRWT_CONTRACT_ADDRESS}
</shell_result>
Script executed:
#!/bin/bash
# Check for Spring profile-specific configuration files
find ./src/main/resources -name "application*.yml" -o -name "application*.yaml" | sortRepository: Woori-FISA-Go/IPiece-server
<shell_result>
Repository: Woori-FISA-Go/IPiece-server
Exit code: 0
stdout:
./src/main/resources/application.yml
</shell_result>
Script executed:
#!/bin/bash
# Search for OTEL or OTLP references in the codebase
rg -i "otel|otlp" --type yaml --type md --type java --type kotlin -C 3 | head -100Repository: Woori-FISA-Go/IPiece-server
<shell_result>
Repository: Woori-FISA-Go/IPiece-server
Exit code: 0
stdout:
src/main/resources/application.yml- web:
src/main/resources/application.yml- exposure:
src/main/resources/application.yml- include: health,info,metrics
src/main/resources/application.yml: otlp:
src/main/resources/application.yml- metrics:
src/main/resources/application.yml- export:
src/main/resources/application.yml: url: http://ipiece-otel-collector.monitoring:4318/v1/metrics
src/main/resources/application.yml- step: 5s
src/main/resources/application.yml-
src/main/resources/application.yml- metrics:
</shell_result>
Script executed:
#!/bin/bash
# Check for README and documentation
find . -maxdepth 2 -type f \( -name "README*" -o -name "*.md" \) | head -20
echo "---"
# Look for docker-compose or k8s files that might reference the monitoring namespace
find . -type f \( -name "docker-compose*" -o -name "*.yaml" -o -name "*.yml" \) | grep -v ".git" | grep -E "(docker|k8s|kube|deployment)" | head -20Repository: Woori-FISA-Go/IPiece-server
<shell_result>
Repository: Woori-FISA-Go/IPiece-server
Exit code: 0
stdout:
./README.md
---
</shell_result>
Script executed:
#!/bin/bash
# Read README.md to understand deployment context
cat ./README.mdRepository: Woori-FISA-Go/IPiece-server
<shell_result>
Repository: Woori-FISA-Go/IPiece-server
Exit code: 0
stdout:
# IPiece
</shell_result>
Script executed:
#!/bin/bash
# Search for Docker, K8s, and build files
find . -type f \( -name "Dockerfile*" -o -name "docker-compose*" -o -name "pom.xml" -o -name "build.gradle*" -o -name "*.yaml" -o -name "*.yml" \) | grep -v ".git" | grep -v "target/" | grep -v "node_modules/" | head -40Repository: Woori-FISA-Go/IPiece-server
<shell_result>
Repository: Woori-FISA-Go/IPiece-server
Exit code: 0
stdout:
./Dockerfile
./src/main/resources/application.yml
./src/test/resources/application.yml
./build.gradle
</shell_result>
Script executed:
#!/bin/bash
# Read Dockerfile
echo "=== DOCKERFILE ==="
cat ./Dockerfile
echo ""
echo "=== BUILD.GRADLE (OTEL-related dependencies) ==="
rg -i "otel|micrometer|observ" ./build.gradle -A 2 -B 2Repository: Woori-FISA-Go/IPiece-server
<shell_result>
Repository: Woori-FISA-Go/IPiece-server
Exit code: 0
stdout:
=== DOCKERFILE ===
# ===========================
# Stage 1: Build Stage
# ===========================
FROM gradle:8.5-jdk17-alpine AS builder
WORKDIR /app
# Gradle 캐시 레이어 (의존성만 먼저)
COPY build.gradle settings.gradle ./
COPY gradle ./gradle
RUN gradle dependencies --no-daemon || true
# 소스 코드 복사 및 빌드
COPY src ./src
RUN gradle clean build -x test --no-daemon --stacktrace
# JAR 파일 확인
RUN ls -la /app/build/libs/ && \
test -f /app/build/libs/IPiece-0.0.1-SNAPSHOT.jar
# ===========================
# Stage 2: Runtime Stage (보안 강화)
# ===========================
FROM eclipse-temurin:17-jre-alpine
# 라벨 추가 (메타데이터)
LABEL maintainer="Woori-FISA-Go Team" \
version="1.0" \
description="IPiece Backend Server"
WORKDIR /app
# 보안: non-root 사용자 생성 및 디렉토리 권한 설정
RUN addgroup -S spring && \
adduser -S spring -G spring && \
chown -R spring:spring /app
# 필요한 패키지만 설치 (보안 업데이트 포함)
RUN apk update && \
apk upgrade && \
apk add --no-cache wget && \
rm -rf /var/cache/apk/*
# JAR 파일 복사 (non-root 소유)
COPY --from=builder --chown=spring:spring /app/build/libs/*.jar app.jar
# 사용자 전환 (non-root로 실행)
USER spring:spring
# Health Check 설정
HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/actuator/health || exit 1
# 환경변수 (기본값)
ENV SPRING_PROFILES_ACTIVE=prod \
JAVA_OPTS="-XX:MaxRAMPercentage=75.0 \
-XX:+UseContainerSupport \
-Djava.security.egd=file:/dev/./urandom \
-Dserver.port=8080" \
TZ=Asia/Seoul
# 포트 노출
EXPOSE 8080
# 실행
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
=== BUILD.GRADLE (OTEL-related dependencies) ===
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-tracing-bridge-otel'
implementation 'io.opentelemetry:opentelemetry-exporter-otlp'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.6'
--
implementation 'org.web3j:core:4.10.0'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
runtimeOnly 'io.micrometer:micrometer-registry-otlp'
}
</shell_result>
OTLP 수집기 URL이 환경 설정으로 외부화되지 않음
OTLP 메트릭 수집기 URL이 http://ipiece-otel-collector.monitoring:4318/v1/metrics로 하드코딩되어 있습니다(line 46). 이는 다음과 같은 문제를 야기합니다:
- 데이터베이스(DB_HOST, DB_PORT, DB_NAME), Redis(REDIS_HOST, REDIS_PORT), JWT 등 다른 설정들은 모두 환경 변수로 외부화되어 있으나 OTLP URL만 하드코딩됨
- Kubernetes 네임스페이스
monitoring이 고정되어 있어 다른 환경에서 배포 불가 - Dockerfile의
SPRING_PROFILES_ACTIVE=prod설정에도 불구하고 profile별 application-*.yml 파일이 없어 환경 간 설정 분리 불가 - 로컬 개발 환경에서 별도의 OTEL 수집기가 없을 경우 실행 불가
권장사항: OTEL 수집기 URL을 환경 변수로 외부화하세요. Spring Boot/Micrometer는 OTEL_EXPORTER_OTLP_ENDPOINT 환경 변수를 기본적으로 지원합니다.
management:
otlp:
metrics:
export:
url: ${OTEL_EXPORTER_OTLP_ENDPOINT:http://localhost:4318/v1/metrics}
step: 5s🤖 Prompt for AI Agents
In src/main/resources/application.yml around lines 43 to 47, the OTLP metrics
exporter URL is hardcoded to
http://ipiece-otel-collector.monitoring:4318/v1/metrics which prevents
environment-specific configuration and breaks non-cluster/local runs; change it
to read from an environment variable (e.g. OTEL_EXPORTER_OTLP_ENDPOINT) with a
sensible default, update the YAML to use property substitution for the URL, and
ensure documentation/README and Docker/K8s manifests reference and pass this env
var (or define profile-specific application-*.yml files) so each deployment can
override the collector endpoint.
📌 Summary
✍️ Description
💡 PR Point
📚 Reference
🔥 Test