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
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ plugins {
alias(libs.plugins.asciidoctor.convert) apply false
alias(libs.plugins.epages.restdocs.api.spec) apply false
alias(libs.plugins.hidetake.swagger.generator) apply false
alias(libs.plugins.sentry.jvm.gradle) apply false
}

allprojects {
Expand Down
12 changes: 10 additions & 2 deletions docker/DockerfileDev
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
FROM alpine:latest AS agent-downloader
RUN wget -O /sentry-opentelemetry-agent.jar https://get.sentry.io/sentry-opentelemetry-agent.jar

FROM amazoncorretto:21
ENV TZ="Asia/Seoul"

RUN mkdir -p /service/pida
RUN mkdir -p /service/pida /opt/sentry
COPY --from=agent-downloader /sentry-opentelemetry-agent.jar /opt/sentry/agent.jar
COPY pida-core/core-api/build/libs/core-api-0.0.1.jar /service/pida/core-api-0.0.1.jar

EXPOSE 8080

CMD java -jar -Xmx2048m /service/pida/core-api-0.0.1.jar
CMD java \
-javaagent:/opt/sentry/agent.jar \
-Dsentry.auto.init=false \
-Xmx2048m \
-jar /service/pida/core-api-0.0.1.jar
9 changes: 7 additions & 2 deletions docker/DockerfileProd
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
FROM alpine:latest AS agent-downloader
RUN wget -O /sentry-opentelemetry-agent.jar https://get.sentry.io/sentry-opentelemetry-agent.jar

FROM amazoncorretto:21
ENV TZ="Asia/Seoul"

ARG PROFILE
ENV PROFILE=${PROFILE}

RUN mkdir -p /service/pida

RUN mkdir -p /service/pida /opt/sentry
COPY --from=agent-downloader /sentry-opentelemetry-agent.jar /opt/sentry/agent.jar
COPY pida-core/core-api/build/libs/core-api-0.0.1.jar /service/pida/core-api-0.0.1.jar

EXPOSE 8080

CMD java \
-javaagent:/opt/sentry/agent.jar \
-Dsentry.auto.init=false \
-Dspring.profiles.active=${PROFILE} \
-jar /service/pida/core-api-0.0.1.jar
8 changes: 7 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ hidetake_swagger_generator = "2.18.2"
swaggerVersion = "2.8.5"

# Sentry version
sentry = "7.3.0"
sentry = "8.31.0"
sentry_gradle = "6.0.0"

# AWS version
aws = "2.40.13"
Expand Down Expand Up @@ -79,6 +80,9 @@ ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }
spring_boot = { id = "org.springframework.boot", version.ref = "spring_boot" }
spring_dependency_management = { id = "io.spring.dependency-management", version.ref = "spring_dependency_management" }

# Sentry Plugin
sentry_jvm_gradle = { id = "io.sentry.jvm.gradle", version.ref = "sentry_gradle" }

# Api-Docs Plugins
asciidoctor_convert = { id = "org.asciidoctor.jvm.convert", version.ref = "asciidoctor_convert" }
epages_restdocs_api_spec = { id = "com.epages.restdocs-api-spec", version.ref = "epages_restdocs_api_spec" }
Expand Down Expand Up @@ -184,6 +188,8 @@ epages_restdocs_api_spec_restassured = { module = "com.epages:restdocs-api-spec-
# Monitoring & Logging Libraries
micrometer_tracing_bridge_brave = { module = "io.micrometer:micrometer-tracing-bridge-brave" }
micrometer_registry_prometheus = { module = "io.micrometer:micrometer-registry-prometheus" }
sentry_spring_boot_starter_jakarta = { module = "io.sentry:sentry-spring-boot-starter-jakarta", version.ref = "sentry" }
sentry_opentelemetry_agent = { module = "io.sentry:sentry-opentelemetry-agent", version.ref = "sentry" }
slf4j = { module = "org.slf4j:slf4j-api", version = "2.0.9" }

# AWS Libraries
Expand Down
26 changes: 26 additions & 0 deletions pida-core/core-api/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
plugins {
id("io.sentry.jvm.gradle")
}

val hasSentryToken = System.getenv("SENTRY_AUTH_TOKEN") != null

sentry {
includeSourceContext.set(hasSentryToken)
org.set("pida-za")
projectName.set("pida")
authToken.set(System.getenv("SENTRY_AUTH_TOKEN"))
}

val sentryAgent: Configuration by configurations.creating

tasks.getByName("bootJar") {
enabled = true
}
Expand All @@ -6,7 +21,18 @@ tasks.getByName("jar") {
enabled = false
}

tasks.register<Copy>("copySentryAgent") {
from(sentryAgent)
into(layout.buildDirectory.dir("agent"))
rename { "sentry-opentelemetry-agent.jar" }
}

tasks.named("build") {
dependsOn("copySentryAgent")
}
Comment on lines +24 to +32
Copy link
Contributor

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐ŸŸ  Major

copySentryAgent task output is unused โ€” Dockerfiles download the agent from a URL instead.

The Gradle task copies the agent to build/agent/sentry-opentelemetry-agent.jar, but both DockerfileDev and DockerfileProd download the agent via wget from https://get.sentry.io/sentry-opentelemetry-agent.jar. This means the Gradle-resolved artifact is never used at runtime, creating two separate supply chains for the same artifact โ€” with potentially different versions.

Pick one approach:

  • Option A (preferred): Use the Gradle-resolved agent in Docker (guarantees the version matches libs.versions.toml). COPY the build output in the Dockerfile instead of wget.
  • Option B: Remove the copySentryAgent task and sentryAgent configuration, and rely solely on the Docker download (but you lose version pinning).
๐Ÿค– Prompt for AI Agents
In `@pida-core/core-api/build.gradle.kts` around lines 24 - 32, The
copySentryAgent Gradle task (copySentryAgent) produces
build/agent/sentry-opentelemetry-agent.jar but DockerfileDev and DockerfileProd
still wget the agent, creating two supply chains; pick one approach. Preferred:
switch DockerfileDev/DockerfileProd to COPY the Gradle output
(build/agent/sentry-opentelemetry-agent.jar) into the image and remove the wget
step so the Docker build uses the pinned libs.versions.toml artifact (keep the
copySentryAgent task and its dependency on build). Alternative: remove the
copySentryAgent task and any sentryAgent configuration if you want to keep
downloading via wget (accepting loss of version pinning).


dependencies {
sentryAgent(libs.sentry.opentelemetry.agent)
implementation(libs.spring.boot.starter.web)
implementation(libs.spring.boot.starter.aop)
implementation(libs.spring.boot.starter.validation)
Expand Down
2 changes: 2 additions & 0 deletions pida-supports/monitoring/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
dependencies {
implementation(libs.spring.boot.starter.actuator)
implementation(libs.micrometer.registry.prometheus)
implementation(libs.sentry.spring.boot.starter.jakarta)
implementation(project(":pida-core:core-domain"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.pida.monitoring.sentry

import com.pida.support.error.AuthenticationErrorException
import com.pida.support.error.ErrorException
import io.sentry.Hint
import io.sentry.SentryEvent
import io.sentry.SentryOptions
import org.springframework.stereotype.Component

@Component
class SentryFingerprintCallback : SentryOptions.BeforeSendCallback {
override fun execute(
event: SentryEvent,
hint: Hint,
): SentryEvent {
val exception = event.throwable ?: return event

val fingerprint = resolveFingerprint(exception)
if (fingerprint != null) {
event.fingerprints = fingerprint
}

return event
}

private fun resolveFingerprint(exception: Throwable): List<String>? =
when (exception) {
is ErrorException ->
listOf(
"ErrorException",
exception.errorType.kind.name,
exception.errorType.name,
)

is AuthenticationErrorException ->
listOf(
"AuthenticationErrorException",
exception.authenticationErrorType.kind.name,
exception.authenticationErrorType.name,
)

else -> null
}
}
19 changes: 18 additions & 1 deletion pida-supports/monitoring/src/main/resources/monitoring.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,21 @@ management:
include: health, prometheus
health:
defaults:
enabled: false
enabled: false

sentry:
dsn: ${SENTRY_DSN}
traces-sample-rate: 1.0
environment: ${SPRING_PROFILES_ACTIVE:local}
exception-resolver-order: -2147483648
logging:
minimum-event-level: error
minimum-breadcrumb-level: info
---
spring:
config:
activate:
on-profile: prod

sentry:
traces-sample-rate: 0.1
Loading