Skip to content
3 changes: 3 additions & 0 deletions admin/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ springdoc:
enabled: true
override-with-generic-response: false

app:
module-name: admin

---
spring:
config:
Expand Down
3 changes: 2 additions & 1 deletion apis/src/main/kotlin/org/yapp/apis/config/InfraConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import org.yapp.infra.InfraBaseConfigGroup
InfraBaseConfigGroup.REST_CLIENT,
InfraBaseConfigGroup.QUERY_DSL,
InfraBaseConfigGroup.PAGE,
InfraBaseConfigGroup.AOP
InfraBaseConfigGroup.AOP,
InfraBaseConfigGroup.SENTRY
]
)
class InfraConfig
3 changes: 3 additions & 0 deletions apis/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ springdoc:
enabled: true
override-with-generic-response: false

app:
module-name: apis

---
spring:
config:
Expand Down
3 changes: 3 additions & 0 deletions batch/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ spring:
max-file-size: 10MB
max-request-size: 30MB

app:
module-name: batch

---
spring:
config:
Expand Down
5 changes: 5 additions & 0 deletions buildSrc/src/main/kotlin/Dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,9 @@ object Dependencies {
object Prometheus {
const val MICROMETER_PROMETHEUS_REGISTRY = "io.micrometer:micrometer-registry-prometheus"
}

object Sentry {
const val SPRING_BOOT_STARTER = "io.sentry:sentry-spring-boot-starter-jakarta:8.22.0"
const val LOG4J2 = "io.sentry:sentry-log4j2:8.22.0"
}
}
3 changes: 3 additions & 0 deletions infra/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ dependencies {

implementation(Dependencies.QueryDsl.JPA)

implementation(Dependencies.Sentry.SPRING_BOOT_STARTER)
implementation(Dependencies.Sentry.LOG4J2)

kapt(Dependencies.QueryDsl.APT)

testImplementation(Dependencies.Spring.BOOT_STARTER_TEST)
Expand Down
4 changes: 3 additions & 1 deletion infra/src/main/kotlin/org/yapp/infra/InfraBaseConfigGroup.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.yapp.infra.config.internal.async.AsyncConfig
import org.yapp.infra.config.internal.jpa.JpaConfig
import org.yapp.infra.config.internal.page.PageConfig
import org.yapp.infra.config.internal.querydsl.QuerydslConfig
import org.yapp.infra.config.external.sentry.SentryConfig

enum class InfraBaseConfigGroup(
val configClass: Class<out InfraBaseConfig>
Expand All @@ -17,5 +18,6 @@ enum class InfraBaseConfigGroup(
REDIS(RedisConfig::class.java),
REST_CLIENT(RestClientConfig::class.java),
QUERY_DSL(QuerydslConfig::class.java),
AOP(AopConfig::class.java)
AOP(AopConfig::class.java),
SENTRY(SentryConfig::class.java)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.yapp.infra.config.external.sentry

import io.sentry.Sentry
import io.sentry.SentryOptions
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.yapp.infra.InfraBaseConfig

@Configuration
@EnableConfigurationProperties(SentryProperties::class)
class SentryConfig(
private val sentryProperties: SentryProperties,
@Value("\${app.module-name}")
private val moduleName: String
) : InfraBaseConfig {

@Bean
fun sentryOptionsCustomizer(): Sentry.OptionsConfiguration<SentryOptions> {
return Sentry.OptionsConfiguration { options: SentryOptions ->
if (sentryProperties.dsn.isBlank()) {
options.isEnabled = false
return@OptionsConfiguration
}

options.dsn = sentryProperties.dsn
options.environment = sentryProperties.environment
options.serverName = sentryProperties.serverName
options.setTag("module", moduleName)
}
}
Comment on lines +19 to +32
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Sentry 옵션 커스터마이저 타입이 잘못되어 적용되지 않습니다
현재 @BeanSentry.OptionsConfiguration을 반환하고 있어 Spring Boot Starter가 제공하는 커스터마이저 체인에 연결되지 않습니다. 그 결과 module 태그 주입과 DSN 미설정 시 비활성화 로직이 전혀 실행되지 않습니다. io.sentry.spring.boot.jakarta.SentryOptionsConfiguration을 반환하도록 수정해야 합니다.

-import io.sentry.Sentry
-import io.sentry.SentryOptions
+import io.sentry.SentryOptions
+import io.sentry.spring.boot.jakarta.SentryOptionsConfiguration
@@
-    fun sentryOptionsCustomizer(): Sentry.OptionsConfiguration<SentryOptions> {
-        return Sentry.OptionsConfiguration { options: SentryOptions ->
+    fun sentryOptionsCustomizer(): SentryOptionsConfiguration<SentryOptions> {
+        return SentryOptionsConfiguration { options: SentryOptions ->
🤖 Prompt for AI Agents
In infra/src/main/kotlin/org/yapp/infra/config/external/sentry/SentryConfig.kt
around lines 19 to 32, the @Bean currently returns Sentry.OptionsConfiguration
which prevents Spring Boot Starter's customizer chain from being used; change
the bean to return
io.sentry.spring.boot.jakarta.SentryOptionsConfiguration<SentryOptions> (the
Spring Boot-provided interface) and adapt the lambda signature to match that
type so Spring will wire it into the starter’s customizer chain; update imports
to use io.sentry.spring.boot.jakarta.SentryOptionsConfiguration and keep the
existing logic (disable when DSN is blank, set dsn/environment/serverName, and
setTag("module", moduleName)).

}


Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.yapp.infra.config.external.sentry

import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties(prefix = "sentry")
data class SentryProperties(
val dsn: String,
val environment: String,
val serverName: String,
)
24 changes: 24 additions & 0 deletions infra/src/main/resources/application-crosscutting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ logging:
controller:
enabled: true

sentry:
dsn: ${SENTRY_DSN}
environment: ${SENTRY_ENVIRONMENT}
server-name: ${SENTRY_SERVER_NAME}
traces-sample-rate: 1.0
Comment thread
coderabbitai[bot] marked this conversation as resolved.
send-default-pii: true
logs:
enabled: true
logging:
minimum-event-level: error
minimum-breadcrumb-level: info
Comment on lines +18 to +23
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

send-default-pii true 설정은 개인정보 보호 정책을 위반할 수 있습니다

send-default-pii: true는 기본적으로 사용자 식별자·IP 등 PII를 Sentry로 전송합니다. 사전 동의나 법무 검토 없이 활성화하면 컴플라이언스 리스크가 커지므로 기본값을 false로 두거나 환경별로 명시적으로 허용했을 때만 켜지도록 조정해 주세요.

-  send-default-pii: true
+  send-default-pii: false
...
-  send-default-pii: true
+  send-default-pii: false

Also applies to: 46-51

🤖 Prompt for AI Agents
In infra/src/main/resources/application-crosscutting.yml around lines 18-23 (and
also apply the same change at lines 46-51), send-default-pii is set to true
which causes PII to be sent to Sentry; change the default to false and implement
an explicit opt-in mechanism (e.g., environment-specific profile or an
environment variable like SENTRY_SEND_PII=true) so PII is only enabled when
explicitly allowed and approved by legal; update the YAML to set
send-default-pii: false by default, add a comment indicating it must be
explicitly enabled per environment with legal approval, and ensure the
duplicated setting at lines 46-51 is updated consistently.


---
spring:
config:
Expand All @@ -25,3 +37,15 @@ logging:
max-log-length: 500
controller:
enabled: true

sentry:
dsn:
environment: test
server-name: reed-test
traces-sample-rate: 1.0
send-default-pii: true
logs:
enabled: true
logging:
minimum-event-level: error
minimum-breadcrumb-level: info
25 changes: 5 additions & 20 deletions infra/src/main/resources/log4j2-spring.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,7 @@
<Configuration status="WARN">

<Properties>
<!-- 색상 없는 기본 패턴 (파일용) -->
<Property name="FILE_LOG_PATTERN">
%d{yyyy-MM-dd HH:mm:ss.SSSSSS} %-5level [%thread] [%X{traceId}] [%X{userId}] [%X{clientIp}] [%X{requestInfo}] %logger{36} - %msg%n
</Property>

<Property name="CONSOLE_LOG_PATTERN">
%d{yyyy-MM-dd HH:mm:ss.SSSSSS} %highlight{%-5level}{FATAL=red blink, ERROR=red, WARN=yellow bold, INFO=green, DEBUG=green bold, TRACE=blue} %style{[%thread]}{cyan} %style{[%X{traceId}]}{green} %style{[%X{userId}]}{magenta} %style{[%X{clientIp}]}{blue} %style{[%X{requestInfo}]}{yellow} %style{%logger{36}}{bright,white} - %msg%n
</Property>
<Property name="CONSOLE_LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSSSSS} %highlight{%-5level}{FATAL=red blink, ERROR=red, WARN=yellow bold, INFO=green, DEBUG=green bold, TRACE=blue} %style{[%thread]}{cyan} %style{[%X{traceId}]}{green} %style{[%X{userId}]}{magenta} %style{[%X{clientIp}]}{blue} %style{[%X{requestInfo}]}{yellow} %style{%logger{36}}{bright,white} - %msg%n</Property>
</Properties>

<Appenders>
Expand All @@ -18,29 +11,21 @@
<PatternLayout pattern="${CONSOLE_LOG_PATTERN}" disableAnsi="false"/>
</Console>

<!-- 파일 출력 - 색상 없음 -->
<RollingFile name="FileAppender" fileName="logs/application.log"
filePattern="logs/application-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="${FILE_LOG_PATTERN}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
<!-- Sentry Appender -->
<Sentry name="Sentry" dsn="${spring:sentry.dsn}"/>
</Appenders>
Comment on lines +14 to 16
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Sentry Appender의 level 속성이 무시되어 경고 로그가 발생합니다

Log4j2의 Sentry 플러그인은 level 속성을 지원하지 않아 부팅 시 “unrecognized attribute level” 경고가 남고 설정도 적용되지 않습니다. 공식 문서처럼 ThresholdFilter로 이벤트 레벨을 제어하도록 바꿔 주세요.

-        <Sentry name="Sentry" level="ERROR"/>
+        <Sentry name="Sentry">
+            <Filter type="ThresholdFilter" level="error"/>
+        </Sentry>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<!-- Sentry Appender -->
<Sentry name="Sentry" level="ERROR"/>
</Appenders>
<!-- Sentry Appender -->
<Sentry name="Sentry">
<Filter type="ThresholdFilter" level="error"/>
</Sentry>
</Appenders>
🤖 Prompt for AI Agents
infra/src/main/resources/log4j2-spring.xml around lines 36-38: the Sentry
appender currently uses a non-supported level attribute which triggers
“unrecognized attribute level” at boot and has no effect; remove the
level="ERROR" attribute from the Sentry element and instead add a
ThresholdFilter child to the Sentry appender with level="ERROR",
onMatch="ACCEPT" and onMismatch="DENY" so only ERROR-and-above events are sent
to Sentry.


<Loggers>
<!-- 내 애플리케이션 로거 -->
<Logger name="org.yapp" level="INFO" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="FileAppender"/>
<AppenderRef ref="Sentry"/>
</Logger>

<!-- 루트 로거 -->
<Root level="INFO">
<AppenderRef ref="Console"/>
<AppenderRef ref="FileAppender"/>
<AppenderRef ref="Sentry"/>
</Root>
</Loggers>
</Configuration>