From 68b63ed4f5e746242198c4b992fdd8462f4ff69b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A7=80=ED=98=84?= Date: Mon, 18 May 2026 11:00:05 +0900 Subject: [PATCH 1/3] feat(observability): export traces to Tempo via Zipkin reporter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 홈서버 모니터링 스택의 Tempo로 trace를 보내도록 reporter 추가. 이미 micrometer-tracing-bridge-brave가 있고 logback의 prod profile이 traceId MDC를 JSON 로그에 박고 있으므로, Zipkin wire format reporter만 추가하면 Loki ↔ Tempo 양방향 점프 가능. 변경: - build.gradle: io.zipkin.reporter2:zipkin-reporter-brave 추가 (Brave가 이미 classpath에 있어서 Spring Boot의 ZipkinAutoConfiguration이 ZipkinSpanHandler bean을 자동 생성) - application-prod.yml: - management.tracing.propagation.type=b3,w3c — b3는 Brave 표준, w3c는 OTel 클라이언트와 호환 - management.zipkin.tracing.endpoint=http://tempo:9411/api/v2/spans (ZIPKIN_ENDPOINT 환경변수로 오버라이드 가능) 샘플링 1.0은 가정 트래픽 기준. 운영 트래픽 증가 시 0.05~0.1 권장. --- build.gradle | 3 +++ src/main/resources/application-prod.yml | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/build.gradle b/build.gradle index 5f1f23c..60d919b 100644 --- a/build.gradle +++ b/build.gradle @@ -48,6 +48,9 @@ dependencies { // Micrometer Tracing - traceId/spanId 자동 생성 implementation 'io.micrometer:micrometer-tracing-bridge-brave' + // Tempo로 trace export (Zipkin wire format). brave가 classpath에 있으면 + // Spring Boot이 ZipkinAutoConfiguration로 자동 구성. + implementation 'io.zipkin.reporter2:zipkin-reporter-brave' // 구조화된 JSON 로깅 implementation 'net.logstash.logback:logstash-logback-encoder:8.0' diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 953ef0f..e813e9f 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -68,6 +68,12 @@ management: tracing: sampling: probability: 1.0 + propagation: + type: b3,w3c # Brave 기본은 b3. w3c도 받아서 OTel 클라이언트 호환 + zipkin: + tracing: + # 같은 web 도커 네트워크의 Tempo. ZIPKIN_ENDPOINT 환경변수로 오버라이드 가능. + endpoint: ${ZIPKIN_ENDPOINT:http://tempo:9411/api/v2/spans} sentry: dsn: ${SENTRY_DSN} From 2bac72d9945be6b4990167ecc58a8ea63eb54dff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A7=80=ED=98=84?= Date: Mon, 18 May 2026 11:21:15 +0900 Subject: [PATCH 2/3] fix(observability): use zipkin reporter3 + add urlconnection sender MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 리뷰 피드백 반영: - io.zipkin.reporter2 → io.zipkin.reporter3 Spring Boot 3.4+ BOM이 reporter3 그룹을 관리. 3.5.6 사용 중이므로 reporter3가 권장. - zipkin-sender-urlconnection 추가 reporter-brave는 직렬화만 담당. 실제 HTTP 전송은 Sender 구현체가 필요. Sender가 classpath에 없으면 ZipkinAutoConfiguration이 ZipkinSpanHandler 빈을 만들지 않음 → trace 전송 안 됨. URLConnection 기반은 JDK 내장이라 의존성 가벼움. 트래픽 증가 시 okhttp3 sender로 교체 가능. --- build.gradle | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 60d919b..8b84c69 100644 --- a/build.gradle +++ b/build.gradle @@ -48,9 +48,12 @@ dependencies { // Micrometer Tracing - traceId/spanId 자동 생성 implementation 'io.micrometer:micrometer-tracing-bridge-brave' - // Tempo로 trace export (Zipkin wire format). brave가 classpath에 있으면 - // Spring Boot이 ZipkinAutoConfiguration로 자동 구성. - implementation 'io.zipkin.reporter2:zipkin-reporter-brave' + // Tempo로 trace export (Zipkin wire format). + // Spring Boot 3.4+ BOM이 io.zipkin.reporter3 그룹을 관리(reporter2는 deprecated). + // - reporter-brave: Brave Span → Zipkin V2 모델 변환 + // - sender-urlconnection: 실제 HTTP POST. Sender 없으면 ZipkinSpanHandler 빈 생성 안 됨 + implementation 'io.zipkin.reporter3:zipkin-reporter-brave' + implementation 'io.zipkin.reporter3:zipkin-sender-urlconnection' // 구조화된 JSON 로깅 implementation 'net.logstash.logback:logstash-logback-encoder:8.0' From 436710366d09aec19dc47fa1235bd248b6342d8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A7=80=ED=98=84?= Date: Mon, 18 May 2026 11:50:25 +0900 Subject: [PATCH 3/3] fix(observability): use correct zipkin reporter group (reporter2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Spring Boot 3.5 BOM이 관리하는 그룹은 'io.zipkin.reporter2'이며 그 그룹의 내부 버전이 3.5.1로 올라온 형태. 'reporter3'라는 별도 그룹은 Maven Central에 존재하지 않아서 버전 해석이 안 되어 빌드 실패함. 이전 커밋의 리뷰 피드백을 검증 없이 반영한 실수. spring-boot-dependencies-3.5.6.pom의 3.5.1 + reporter-bom 그룹이 reporter2임을 확인. - io.zipkin.reporter3 → io.zipkin.reporter2 (sender는 동일하게 유지) --- build.gradle | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 8b84c69..4e6af90 100644 --- a/build.gradle +++ b/build.gradle @@ -49,11 +49,12 @@ dependencies { // Micrometer Tracing - traceId/spanId 자동 생성 implementation 'io.micrometer:micrometer-tracing-bridge-brave' // Tempo로 trace export (Zipkin wire format). - // Spring Boot 3.4+ BOM이 io.zipkin.reporter3 그룹을 관리(reporter2는 deprecated). + // Spring Boot 3.5 BOM이 io.zipkin.reporter2 그룹을 3.5.x 버전으로 관리. + // ("reporter3" 그룹은 존재하지 않음 — 그룹명은 reporter2 유지하고 내부 버전만 v3로 올라옴.) // - reporter-brave: Brave Span → Zipkin V2 모델 변환 // - sender-urlconnection: 실제 HTTP POST. Sender 없으면 ZipkinSpanHandler 빈 생성 안 됨 - implementation 'io.zipkin.reporter3:zipkin-reporter-brave' - implementation 'io.zipkin.reporter3:zipkin-sender-urlconnection' + implementation 'io.zipkin.reporter2:zipkin-reporter-brave' + implementation 'io.zipkin.reporter2:zipkin-sender-urlconnection' // 구조화된 JSON 로깅 implementation 'net.logstash.logback:logstash-logback-encoder:8.0'