46 KiB
title, source_type, status, branch, parent_branch, governing_docs, related_projects, tags, created, target_merge, status_label, id, kind, project, work_item, inherits, refines, overrides, depends_on, contract_packet, contract_packet_sha256
| title | source_type | status | branch | parent_branch | governing_docs | related_projects | tags | created | target_merge | status_label | id | kind | project | work_item | inherits | refines | overrides | depends_on | contract_packet | contract_packet_sha256 | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| branch / feature-distributed-tracing-contract | branch-note | raw | feature-distributed-tracing-contract |
|
|
|
2026-05-22 | in-progress | BR-CA-SKELETON-OPERATIONAL-CONTRACT-027 | project-work-item | ca-skeleton-operational-contract | WI-CA-SKELETON-OPERATIONAL-CONTRACT-027 |
|
1 | 7b6718a5912304437453bc70ffbbaba27bced681a98e7ed246687a83b38f67fa |
branch: feature-distributed-tracing-contract
Layer:
raw/branch-notes/— HTTP, async, messaging, outbound 경계에서 trace context가 끊기지 않도록 distributed tracing 기준을 정의합니다.
부모 (필수)
- Parent project (canonical SSOT): raw/project-notes/ca-skeleton-operational-contract
ca-skeleton 은 별도 root branch 없이 project-note 가 SSOT 역할. 본 feature branch 는 project-note 의 운영 계약 중 해당 영역 (§<관련 섹션>) 의 결정/근거/금지 사항을 정제한다.
브랜치 계약 패킷
- 생성 시 프로젝트 개정:
1 - 패킷 스키마:
contract_packet: 1 - 완료 조건: request·trace correlation contract test가 통과한다
상속한 프로젝트 결정
| Decision Ref | Project Summary | Branch Application | Source |
|---|---|---|---|
DEC-CA-SKELETON-OPERATIONAL-CONTRACT-ERROR-ENVELOPE-001@1 |
foundation이 envelope schema와 error.category enum의 단일 owner다 | Work Item 완료 조건에 적용 | raw/project-notes/ca-skeleton-operational-contract |
브랜치 지역 결정
기존 branch-local 결정은 아래
## Decision Evidence Map / 결정-근거 매핑의 D-row가 소유하며 이 packet에서 복제하지 않는다.
| Decision ID | Decision | Relation | Supporting Claims | Status |
|---|
선언한 예외
| Override ID | Overrides | Reason | Approval | Status |
|---|
목표
structured log만으로는 운영 장애의 흐름을 끝까지 추적하기 어렵습니다. traceId/requestId/correlationId/spanId의 의미와 전파 경계를 고정해서 어떤 adapter를 붙여도 같은 방식으로 원인을 추적할 수 있게 합니다.
- 이슈:
- PR:
범위
포함 범위
- traceId/requestId/correlationId/spanId 의미 정의.
- inbound HTTP, outbound HTTP, async job, message publish/consume 전파 기준.
- MDC와 trace context 동기화 기준.
- sampling/exporter/env 설정 기준.
- baggage 금지 정보 기준.
제외 범위
- 특정 APM vendor 종속 설정.
- business event tracing.
- provider별 dashboard 구현.
근거 (필수, 최소 1개+)
본 branch의 결정 근거. 상세 비교는 §외부 근거 / 대안 조사 (있다면) 참조.
| Source | 정당화하는 결정 |
|---|---|
| raw/official-docs/tracing-w3c-trace-context-spec.md | W3C Recommendation, OTel default propagator |
| raw/official-docs/tracing-otel-sampling-tail-vs-head-spec.md | head-based + force-sample boost가 SDK 기본 기능만으로 구현 가능 |
| raw/official-docs/tracing-b3-propagation-zipkin-spec.md | legacy, 64-bit mode는 W3C 비호환 |
| raw/company-tech-blogs/tracing-datadog-apm-vs-opentelemetry.md | auto-instrumentation 광범위하나 vendor lock-in |
| raw/official-docs/baggage-otel-baggage-api-spec | D2: SDK-level escape hatch (untrusted process 로의 모든 baggage entry 제거 MUST); D8: spec 에 allowlist 정의 없음 — restriction 은 Propagator/application 위임 (내부 governance 정책 확인) |
| raw/official-docs/tracing-micrometer-observation-introduction | D12 — Observation#error(exception) 호출이 error lifecycle event를 발생시킨다는 API 계약 (MICR-OBS-C1, MICR-OBS-C3) |
| raw/official-docs/baggage-w3c-baggage-spec | D2 — baggage 에 PII/기밀 정보 금지 + trust-boundary 제거 의무 (W3C-BAG-C1). D8 — allowlist 정책은 spec 에 없는 application 결정 (W3C-BAG-C2, W3C-BAG-C3). |
| raw/official-docs/tracing-otel-trace-api-spec | D4 — SDK noop 시 all-zero TraceId (OTEL-TAPI-C2/C3), "disabled but meaningful traceId" = SDK-on + exporter-off 로만 가능; D12 — RecordException 은 Event 기록만 (OTEL-TAPI-C4), status=ERROR 는 별도 SetStatus 호출 필요 |
| raw/official-docs/tracing-spring-boot-3-actuator-tracing-reference | D1 — Spring Boot Actuator 가 Micrometer Tracing (OTel+OTLP 와 Brave+Zipkin 두 tracer 공식 지원) 을 auto-configure 함; vendor-neutral OTLP 채택의 공식 근거 (SB-TRAC-C1 ~ C4) |
외부 근거 / 대안 조사 (2026-05-22 — Group G-A: Distributed tracing)
채택 결정 + 뒷받침
- 결정: W3C traceparent + tracestate (B3 forbidden) + Micrometer Tracing + OpenTelemetry exporter + prod 1% head-based sampling + force-sample on error/slow/retry-exhausted.
- 뒷받침 source:
- raw/official-docs/tracing-w3c-trace-context-spec.md — W3C Recommendation, OTel default propagator. 128-bit trace-id +
tracestatevendor 확장 spec. - raw/official-docs/tracing-otel-sampling-tail-vs-head-spec.md — head-based + force-sample boost가 SDK 기본 기능만으로 구현 가능. tail-based는 collector overhead.
- raw/official-docs/tracing-w3c-trace-context-spec.md — W3C Recommendation, OTel default propagator. 128-bit trace-id +
검토 대안 + source
- 대안 1 — B3 / Zipkin propagation: raw/official-docs/tracing-b3-propagation-zipkin-spec.md. legacy, 64-bit mode는 W3C 비호환. ca-tmpl은 forbidden, edge translation만 허용.
- 대안 2 — Tail-based / Adaptive sampling: raw/official-docs/tracing-otel-sampling-tail-vs-head-spec.md. error/slow trace 100% 보존 가능하나 collector 메모리 + decision_wait window 추가 운영 비용.
- 대안 3 — Datadog APM / AWS X-Ray native tracer: raw/company-tech-blogs/tracing-datadog-apm-vs-opentelemetry.md. auto-instrumentation 광범위하나 vendor lock-in. ca-tmpl out-of-scope 결정과 충돌.
비교 핵심 1줄
W3C + OTel + head-based는 vendor-neutral + SDK 기본 기능만으로 구현 가능 + Spring Boot 3 + Micrometer 통합이 강점, tail-based는 trace 완성도, vendor APM은 빠른 시작 + vendor lock-in trade-off.
TODO
TODO drained — 결정은 error.category enum 표 / MDC Key Standard 표 / error.details JSON shape 참조
Work Item Contract
각 TODO는 아래 판정 단위로 재작성되어야 canonical 승급 가능합니다. TODO가 단순히 기준 작성으로 남아 있으면 이 branch는 완료로 보지 않습니다.
| field | required | rule |
|---|---|---|
| Decision | yes | 구현자가 선택해야 하는 기본값 |
| Allowed | yes | 허용되는 예외와 조건 |
| Forbidden | yes | 절대 금지되는 구현/문서 상태 |
| Required registry update | conditional | error/env/header/log/metric/capability 변경 시 필수 |
| Required contract test | yes | 계약 위반 시 실패해야 하는 테스트 |
| Failure condition | yes | review/build에서 실패로 판정할 상태 |
| Canonical extraction target | yes | wiki/projects 승급 위치 |
진행 중 메모
- 2026-06-14 (/branch-spec 게이트): 6개
UNSUPPORTED_DECISION중 4건을 자동조사로 해소 — D1(SB-TRAC-C1~C4), D2(W3C-BAG-C1 + OTEL-BAG-C3), D4(OTEL-TAPI-C2/C3 — 부분 해소 + 핵심 정정), D8(W3C-BAG-C2/C3 + OTEL-BAG-C4 — policy 재framing), D12(MICR-OBS-C1/C3 + OTEL-TAPI-C4). 잔여UNSUPPORTED_DECISION은 D3·D9 (내부 운영 정책 — 외부 표준 인용 대상 아님). official-doc raw 5개 신규 등록(spring-boot actuator tracing / micrometer observation / otel trace api / w3c baggage / otel baggage api). - 2026-06-14 ground-truth 재검증(ca-tmpl @HEAD): env/metric/header registry row 의
owner_branch가 본 branch 임을 확인(OTEL_EXPORTER_OTLP_ENDPOINT·APP_TRACING_ENABLED·APP_TRACING_SAMPLE_RATE·tracing.sampling.rate·traceparent·tracestate). 단 Micrometer Tracing config 클래스는src/에 미존재 — 계약(registry)은 등록됐으나 구현은planned. async context 전파 코드(AsyncContextTaskDecorator)에서 carrier 표 drift 발견 → §Audit & Findings 참조. - 2026-06-14 Slice 1 (Scope C — contract mechanics) 구현 완료 (
actually-implemented,locally-verified): 3개 pure Java stdlib 타입을dev.caskeleton.shared.tracing패키지 (src/shared-contract) 에 신규 생성. TDD red→green 확인 (58 tests, 0 failures). Spring/OTel/Jackson import 없음 확인. - 2026-06-14 전체 구현 완료 (Scope C — 계약 메커니즘; tracer 런타임은 fork-activated seam) (
actually-implemented,locally-verified). 사용자 결정: OTel/Micrometer/Actuator deps 미추가, 계약 메커니즘만 코드+테스트로 실현. 슬라이스:- Slice 1 (shared-contract):
TraceParent(W3C parse/validate/render, all-zero 거부 — D5/D7),BaggageAllowlist(allow=tenant_id/request_id, header filter — D2/D8),SpanErrorRecorder+NOOP(D12 seam). 58 tests. - Slice 2 (adapter-web):
RequestLoggingFilter가 inboundtraceparentaccept/생성(부재·무효 시 32hex/16hex root) → MDCtrace_id/span_id→ResponseMetaFactorymeta.traceId항상 non-null (D4 disabled-fallback = request_id mirror 제거하고 실 W3C id 로 교체).GlobalExceptionHandler가SpanErrorRecorder.recordException(throwable, errorCode)호출(catch-all + persistence + dependency 경로).@Autowired ObjectProvider<SpanErrorRecorder>self-default → 모든 컨텍스트(@WebMvcTest 슬라이스 포함)에서 bean 없이 wiring, fork 가 bean 기여 시 override. - Slice 3 (adapter-outbound):
TraceContextPropagationInterceptor가 MDC → outboundtraceparent/X-Request-Id/X-Correlation-Id/allowlistedbaggage주입,OutboundHttpClient.baseline(...)buffered+streaming 양쪽 배선. MDC 키는 mdc-keys.yaml SSOT 리터럴(adapter-web 의존 금지). sampled=00(seam — tracer 가 실 sampled 소유). - Slice 4+5 (app-bootstrap):
.env+application.yml3키 배선(verifyEnvKeys 통과),TracingProperties(@Validated, float_between_0_and_1 + url_or_empty 시작시 검증),TracingSampleRateResolver(prod .01/staging .1/dev·local 1.0 — D6),TracingSamplingRateGauge(tracing.sampling.rate, profile tag, ObjectProvider no-op), 6개 required_test 전부 + §테스트계약 5종. - 검증:
./gradlew check= BUILD SUCCESSFUL, 1091/1091 tests, 0 failures (verifyCleanArchitectureDependencies + verifyEnvKeys + ArchUnitCleanArchitectureTest포함). 리뷰 체인: architect-sentinel PASS, spec-reviewer 19/19 요구사항 MET, quality-reviewer 0 Critical(3 Important·4 Minor 반영). - 여전히
planned(과장 금지): 실 OTel SDK/Micrometer Tracing/OTLP exporter 런타임, 실 head/force-sample sampler, Observation scope async 재establish, B3 edge translation, tracestate 한계 모니터링. 이들은 fork-activated seam — 면접/포트폴리오에 "OTel 로 추적을 구현/운영했다" 금지. 실현된 것은 계약 메커니즘(전파 형식·disabled fallback·baggage allowlist·span-error seam·sampling-rate gauge·env/header/metric 배선·계약 테스트).
- Slice 1 (shared-contract):
결정 사항
- 2026-05-22: Micrometer Tracing + OpenTelemetry exporter를 기본 기준으로 둠.
- 2026-05-22: baggage에는 PII, token, user raw identifier, request body derived value를 넣지 않음.
- 2026-05-22: trace/request/correlation ID 의미의 SSOT는
feature-operational-error-observability-foundation; 이 branch는 propagation mechanics만 소유. - 2026-05-22: tracing disabled profile에서도 envelope
meta.traceId와 logtraceId는 유지. exporter/sampling만 비활성화 가능. - 2026-05-22: propagation header는 W3C
traceparentdefault. - 2026-05-22: trace sampling rate default = prod 1%, staging 10%, dev/local 100%. force-sample = error response, slow request (p99 초과), retry exhausted.
- 2026-05-22: propagation format = W3C traceparent + tracestate only. B3 propagation은 forbidden (외부 통합 시 edge에서 변환).
- 2026-05-22: baggage allowlist =
tenant_id,request_id만 허용. 그 외 baggage 사용 forbidden. - 2026-05-22: trace sampling rate(prod 1%) < log sampling rate(prod 10%)는 의도된 분리. log-management branch와 정합.
- 2026-05-22: identifier 표기는 layer별 분리. MDC/log field는 snake_case (
request_id/trace_id/correlation_id), JSON response envelope는 camelCase (meta.requestId/meta.traceId/meta.correlationId), HTTP header는 kebab-case (X-Request-Id/X-Correlation-Id). foundation MDC SSOT와 envelope SSOT의 mapping은 본 branch의 Propagation Defaults 표가 보장.
결정-근거 매핑
각 결정이 어떤 raw source claim 으로 뒷받침되는지 명시한다.
Decision ID는 이 branch-note 안에서 안정적으로 유지한다.
| Decision ID | Decision | Supporting Claims | Evidence Strength | Open Risk |
|---|---|---|---|---|
| D1 | Micrometer Tracing + OpenTelemetry exporter 기본 채택 | raw/official-docs/tracing-spring-boot-3-actuator-tracing-reference#SB-TRAC-C1 (Actuator auto-configures Micrometer Tracing facade), #SB-TRAC-C2 (OTel+OTLP 와 Brave+Zipkin 두 tracer 모두 공식 지원), #SB-TRAC-C3 (두 조합 모두 dedicated starters 존재), #SB-TRAC-C4 (spring-boot-starter-opentelemetry 공식 starter) |
official-vendor-doc (Spring Boot 공식 reference — 2026-06-14 fetch 검증) |
"OTel 이 유일한 default" 는 증명 안 됨 — Spring Boot 는 OTel+OTLP 와 Brave+Zipkin 둘 다 지원. D1 의 framing 은 "두 tracer 중 OTel+OTLP 를 채택" 임을 명시할 것. vendor-neutral OTLP export 의 Spring Boot 공식 지원 근거로만 사용 |
| D2 | baggage 에 PII/token/user raw identifier/body 금지 | raw/official-docs/baggage-w3c-baggage-spec#W3C-BAG-C1 (baggage may carry sensitive information — trust-boundary 제거 의무, baggage spec 직접 근거) + raw/official-docs/baggage-otel-baggage-api-spec#OTEL-BAG-C3 (untrusted process 로의 모든 baggage entry 전송 방지 MUST — SDK-level escape hatch) |
official-standard + official-vendor-doc (W3C Candidate Recommendation Snapshot 2024-05-30 + OTel stable spec) |
W3C Baggage spec §4.1 이 기밀/소유 정보 금지 + trust-boundary 제거 의무 직접 규정. OTel Baggage spec 은 untrusted process 전송 방지 MUST. 구체적 금지 항목(PII/token 형태)은 application 정책. 이전 인용 tracing-w3c-trace-context-spec#W3C-TC-C5(tracestate 대상)는 baggage 직접 근거가 아니었으므로 W3C-BAG-C1 로 교체. |
| D3 | trace/request/correlation ID 의미 SSOT = feature-operational-error-observability-foundation consume |
UNSUPPORTED_DECISION (SSOT 분할은 내부 운영 정책) | N/A | branch ownership 분할은 외부 표준 인용 대상 아님 |
| D4 | tracing disabled profile 에서도 envelope meta.traceId + log traceId 유지, exporter/sampling 만 비활성화 |
raw/official-docs/tracing-otel-trace-api-spec#OTEL-TAPI-C1 (SDK 부재 시 Trace API = no-op), #OTEL-TAPI-C2 (noop + 부모 Span 없으면 SpanContext = all-zero Trace/Span IDs), #OTEL-TAPI-C3 (noop 상태 새 SpanContext 미생성) |
official-standard (OTel Trace API spec — 2026-06-14 fetch) |
핵심 정정: SDK 자체를 noop 으로 두면 traceId=all-zeros(의미 없음). 따라서 "disabled but keep meta.traceId" = SDK-on + exporter-off(sampling.probability=0)로만 구현 가능. UNSUPPORTED_IMPL_DECISION: 정확한 Spring property 조합(exporter bean exclusion + sampling 0) 또는 app-generated UUID fallback 은 ca-tmpl 운영 결정 — 단일 source 없음 |
| D5 | propagation header = W3C traceparent default |
raw/official-docs/tracing-w3c-trace-context-spec.md#W3C-TC-C1, raw/official-docs/tracing-w3c-trace-context-spec.md#W3C-TC-C2, raw/official-docs/tracing-w3c-trace-context-spec.md#W3C-TC-C3 |
official-standard (W3C TR — HTTP header + 4-field format + canonical example, 2026-05-27 verified verbatim) |
C4 (tracestate name/value vs key/value 표현 차이) 는 needs-confirmation 유지 |
| D6 | trace sampling rate default = prod 1%, staging 10%, dev/local 100% + force-sample (error/slow/retry-exhausted) | raw/official-docs/tracing-otel-sampling-tail-vs-head-spec.md#OTEL-SAMP-C1, raw/official-docs/tracing-otel-sampling-tail-vs-head-spec.md#OTEL-SAMP-C3, raw/official-docs/tracing-otel-sampling-tail-vs-head-spec.md#OTEL-SAMP-C4 |
official-vendor-doc (head sampling 정의/장점/단점) |
OTEL-SAMP-C3 Usage Boundary: 효율의 정량값 없음. 1%/10%/100% 비율 자체는 ca-tmpl 운영 가정 (OTEL-SAMP-C7 같은 권장값 spec 부재). force-sample 메커니즘은 OTEL-SAMP-C4 Does not prove 에 따르면 별도 SDK 구현 필요 |
| D7 | propagation format = W3C traceparent + tracestate only. B3 propagation forbidden | raw/official-docs/tracing-w3c-trace-context-spec.md#W3C-TC-C1, raw/official-docs/tracing-b3-propagation-zipkin-spec.md#B3-C6 (B3 trace-id 64-bit/128-bit 양쪽 허용 — W3C 128-bit only 와 호환 한계) |
official-standard (양쪽 spec) |
B3-C6 Does not prove: W3C 호환 결론은 본 인용으로 직접 증명되지 않음. ca-tmpl 의 "forbidden" 결정은 W3C 채택 + 운영 단순화 정책 |
| D8 | baggage allowlist = tenant_id, request_id 만 허용 |
raw/official-docs/baggage-w3c-baggage-spec#W3C-BAG-C2 + raw/official-docs/baggage-w3c-baggage-spec#W3C-BAG-C3 (W3C Baggage spec 은 64 list-members / 8192 bytes wire 제약만 정의, allowlist 메커니즘 없음) + raw/official-docs/baggage-otel-baggage-api-spec#OTEL-BAG-C4 (OTel spec 도 allowlist 미정의 — restriction 은 Propagator/application 위임) |
official-standard + official-vendor-doc (W3C Candidate Recommendation Snapshot 2024-05-30 + OTel stable spec) |
두 spec 모두 wire-format 제약만 정의하고 어떤 key 를 허용/금지할지 규정하지 않음. tenant_id/request_id 구체 key 선택은 ca-tmpl 운영 정책 — UNSUPPORTED_IMPL_DECISION 유지. W3C-BAG-C2/C3 는 "spec 에 allowlist 없음" 을 W3C 층에서 추가 확인. |
| D9 | identifier 표기 layer 별 분리 (MDC snake_case / envelope camelCase / HTTP header kebab-case) | UNSUPPORTED_DECISION (layer 별 표기 컨벤션은 내부 결정 — 외부 raw 표준 없음). owner = raw/branch-notes/feature-operational-error-observability-foundation D19 (mdc-keys.yaml / headers.yaml SSOT) — 본 row 는 그 결정의 consume pointer, 재진술 아님 (§Audit RESTATED_FOREIGN_DECISION 참조) | N/A | foundation branch 의 MDC Key Standard 표 와 envelope SSOT 정합으로만 정당화 |
| D10 | Datadog APM / AWS X-Ray native tracer 거부 (vendor lock-in) | raw/company-tech-blogs/tracing-datadog-apm-vs-opentelemetry.md#DD-OTEL-C1, raw/company-tech-blogs/tracing-datadog-apm-vs-opentelemetry.md#DD-OTEL-C2, raw/company-tech-blogs/tracing-datadog-apm-vs-opentelemetry.md#DD-OTEL-C3 |
company-case-study (Datadog 의 OTel vendor-neutrality 인정 + 자체 dd-trace-java 자동 계측) |
company-tech-blog 는 official best practice 아님. ca-tmpl 의 "out-of-scope" 결정은 vendor 평가 trade-off 로만 표현. DD-OTEL-C4/C5/C6 는 needs-confirmation — verbatim 미확인 |
| D11 | Tail-based / Adaptive sampling 거부 (collector overhead) | raw/official-docs/tracing-otel-sampling-tail-vs-head-spec.md#OTEL-SAMP-C5 (tail sampling = trace 의 모든/대부분 span 고려) |
official-vendor-doc |
OTEL-SAMP-C5 Usage Boundary: decision_wait window 길이 / missing span 처리 의 trade-off 본 인용 범위 밖. ca-tmpl 의 운영 비용 평가는 내부 판단 |
| D12 | span 예외 발생 시 Observation.error(throwable) + error.code 부착 + sampled span 만 stack trace attach |
raw/official-docs/tracing-micrometer-observation-introduction#MICR-OBS-C1 (Observation#error(exception) 호출 → error lifecycle event), #MICR-OBS-C3 (ObservationHandler 가 lifecycle event 로 span 생성), raw/official-docs/tracing-otel-trace-api-spec#OTEL-TAPI-C4 (RecordException = AddEvent 변형, status 변경 없음 → SetStatus 별도 호출) |
official-vendor-doc (Micrometer Observation reference + OTel Trace API spec) |
Observation.error() → OtelSpan.error() → recordException() + setStatus(ERROR) 체인은 소스코드 검증(공식 docs 산문 부재). error.code 는 ca-tmpl registry attribute 명 — OTel semantic-convention 표준 아님(표준 = exception.type/exception.message/exception.stacktrace). UNSUPPORTED_IMPL_DECISION: "sampled span 만 stack trace / unsampled = error.code only" 정책은 ca-tmpl 운영 결정 — source 없음. 코드 미구현(planned — src/ 에 Observation error handler 부재) |
구현 가이드
결정 (Decisions) 이 "무엇 을 할 것인가" 라면, 본 §는 "어디에 어떻게 구현될 것인가" 의 사전 명세다. 아래 sub-section 은 모두 본 branch 의 결정 + 근거에서 도출되며, 각 표는 Trace 헤더로
Decision ID+Supporting Claim ID를 reference 한다.코드 구현 상태: 본 branch 의 결정은 registry(env/metric/header)에는 등록됐으나, Micrometer Tracing config / Observation error handler 클래스는 ca-tmpl
src/에 아직 없음 (planned). 아래 명세는 구현될 때의 사전 계약 이다 (§Audit & Findings IMPL_STATUS 참조).
1. Boundary Propagation Defaults
Trace: D5 (
traceparentdefault — W3C-TC-C1/C2/C3) + D7 (W3C only, B3 forbidden) + D4 (disabled → exporter-off — OTEL-TAPI-C2/C3).
- UNSUPPORTED_IMPL_DECISION:
disabled tracing → generated opaque trace id행 — OTel SDK 를 noop 으로 두면 traceId = all-zeros(OTEL-TAPI-C2/C3)이므로 "meaningful opaque id 유지" 는 SDK-on + exporter-off(sampling 0) 또는 app-generated UUID 로만 가능. 정확한 메커니즘은 ca-tmpl 운영 결정(단일 source 없음).
| boundary | default |
|---|---|
| inbound HTTP | accept/generate W3C trace context |
| outbound HTTP | propagate traceparent, requestId, correlationId |
| async/job | capture and restore context wrapper |
| messaging | include trace context and correlationId in metadata |
| disabled tracing | generated opaque trace id, exporter off (SDK-on + exporter-off — noop 은 all-zeros 라 사용 불가, 위 UNSUPPORTED_IMPL_DECISION) |
2. Async / Messaging Carrier Keys
Trace: D5/D7 (W3C carrier — traceparent/tracestate) + §Claims To Verify (TaskDecorator / Kafka·Rabbit consumer-side auto-extract =
planned).
- UNSUPPORTED_IMPL_DECISION: Kafka
traceparent (binary value)인코딩 + Spring scheduler per-trigger 생성은 OTel instrumentation 모듈 동작 가정 — 본 branch 인용에 직접 spec 없음(planned, §Claims To Verify).- CARRIER_DRIFT (코드 실측):
@Async TaskDecorator행은 ca-tmpl 코드와 어긋남 — 실제AsyncContextTaskDecorator는 plain MDC copy(MDC.getCopyOfContextMap())이며 Micrometer Observation scope 를 worker thread 에 재establish 하지 않는다(io.micrometer:context-propagation + ContextPropagatingTaskDecorator 는 documented future enhancement, 미구현). 또한 이 decorator 의 owner 는 raw/branch-notes/feature-background-job-async-contract / raw/branch-notes/feature-runtime-context-propagation-contract 이지 본 branch 가 아니다. §Audit & Findings 참조.
| carrier | key |
|---|---|
| HTTP | traceparent, tracestate (W3C) |
| Kafka header | traceparent (binary value) |
| RabbitMQ header | traceparent |
| @Async TaskDecorator | (실측 정정) MDC trace_id/span_id 문자열 thread-local copy via AsyncContextTaskDecorator. Observation scope 재establish 는 미구현(future enhancement) |
| Spring scheduler | traceparent generated per trigger |
3. Span Error Recording
Trace: D12 —
Observation#errorlifecycle (MICR-OBS-C1/C3) + RecordException ≠ status 변경(OTEL-TAPI-C4, SetStatus 별도).
- UNSUPPORTED_IMPL_DECISION:
sampled span 만 stack trace attach / unsampled = error.code attribute only는 ca-tmpl 운영 정책(source 없음).error.code는 ca-tmpl registry attribute 명이며 OTel semantic-convention 표준 아님(표준 =exception.type/exception.message/exception.stacktrace).
- 예외 발생 시
Observation.error(throwable)호출 강제. - span attribute
error.code(registry value) 부착 + status=ERROR. - exception stack trace는 sampled span에만 attach. unsampled span은
error.codeattribute만 남기고 stack trace 부착 금지.
4. Registry anchors (env / metric / header — ca-tmpl SSOT)
Trace: D1 (exporter endpoint) + D4 (tracing enabled toggle) + D6 (sample rate + sampling metric) + D5/D7 (header). 아래 값은 ca-tmpl
docs/registries/*.yaml의 실재 row 로,owner_branch가 본 branch 임을 2026-06-14 확인했다.
- IMPL_STATUS: registry row 는 등록됨(계약 존재). 이를 읽어 적용하는 Micrometer Tracing config / OTLP exporter / 커스텀 sampler 클래스는
src/에 미존재(planned). registry ≠ 구현 — 면접/포트폴리오에 "구현했다" 금지(§Audit IMPL_STATUS).
| registry | key | 값 (registry 실측) | required_test | owner |
|---|---|---|---|---|
| env-keys.yaml | OTEL_EXPORTER_OTLP_ENDPOINT |
type url, default null, public-config, restart-only, validation url_or_empty | tracing-contract:exporter-endpoint-resolvable |
본 branch |
| env-keys.yaml | APP_TRACING_ENABLED |
boolean, default true, public-config, restart-only, boolean_strict | tracing-contract:meta-traceid-when-disabled |
본 branch |
| env-keys.yaml | APP_TRACING_SAMPLE_RATE |
string, default "1.0", public-config, restart-only, float_between_0_and_1 | tracing-contract:sample-rate-per-profile |
본 branch |
| metrics.yaml | tracing.sampling.rate |
gauge, tag profile(cardinality 4 — prod/staging/dev/local) |
contract-verification:metrics-cardinality |
본 branch |
| headers.yaml | traceparent |
direction both, generated_if_missing true, mdc_key trace_id, envelope meta.traceId |
contract-verification:trace-propagation |
본 branch |
| headers.yaml | tracestate |
direction both, generated_if_missing false, mdc_key null | contract-verification:trace-propagation |
본 branch |
| mdc-keys.yaml | trace_id/span_id/correlation_id/request_id |
snake_case, http_header_mapping + envelope_field 등록 | contract-verification:log-mdc-keys |
foundation (consume only — §엣지·실패·의존) |
엣지·실패·의존
R4(깊이 게이트) 캡처용. 정상 경로 외에 구현 중 부딪힐 실패/엣지/다른 계약 의존을 미리 열거.
- 실패·엣지 경로:
- disabled profile → all-zeros: OTel SDK 를 noop 으로 두면
meta.traceId=00000000...(OTEL-TAPI-C2/C3). 기대: exporter-off + SDK-on 으로 meaningful id 유지. all-zeros 가 envelope/log 에 노출되면 실패(테스트 계약meta.traceId누락 항목과 같은 실패군). - force-sample 한계: head sampler 단독으로는 error/slow/retry-exhausted boost 불가(OTEL-SAMP-C4) →
ParentBased + 커스텀 sampler별도 구현 필요(§Claims To Verify,needs-confirmation). - B3 inbound (외부 시스템): 본 branch 는 B3 forbidden(D7)이나 외부 호출자가 B3 헤더를 보낼 수 있음 → edge 에서 multi-propagator(
tracecontext,b3) 변환, receiver precedence(B3-C5/C6). 미구현 시 trace 단절. - tracestate 한계 초과: List-Members/length 제한(W3C-TC-C4,
planned) 초과 시 partial drop. vendor tracestate 누적 monitoring 필요. - baggage trust-boundary: untrusted process 호출 전 baggage remove-all(OTEL-BAG-C3) 미적용 시 D2 위반(PII 유출).
- disabled profile → all-zeros: OTel SDK 를 noop 으로 두면
- 다른 계약 의존:
- raw/branch-notes/feature-operational-error-observability-foundation 의
D11(MDC snake_case 표준) +D19(snake/camel/kebab layer mapping) +D16(operational error → span ERROR 기록) 에 의존 — 본 branch 는trace_id/span_id/correlation_id의 의미·명명 을 consume(SSOT 는 foundation +mdc-keys.yaml). 그 계약이 바뀌면 D3/D9/D12 영향. - ca-tmpl
docs/registries/mdc-keys.yaml+headers.yaml(registry SSOT) —trace_id ↔ traceparent ↔ meta.traceId매핑. 본 branch 는traceparent/tracestateheader row 의 owner, MDC key row 는 foundation owner. - raw/branch-notes/feature-log-management-contract — log sampling(prod 10%) vs trace sampling(prod 1%) 의도된 분리(D6 정합). log sampling 정책이 바뀌면 D6 비교 근거 재검토.
- raw/branch-notes/feature-background-job-async-contract + raw/branch-notes/feature-runtime-context-propagation-contract — 실제 async context 전파 메커니즘(
AsyncContextTaskDecorator/DomainContextPropagator)의 owner. 본 branch 는 carrier key 만 정의하고 전파 구현은 그 branch 소유(§Audit CARRIER_DRIFT).
- raw/branch-notes/feature-operational-error-observability-foundation 의
검증해야 할 주장
| Claim | Why uncertain | How to verify | Status |
|---|---|---|---|
W3C traceparent 의 trace-flags LSB = sampled (01 = sampled) 비트 의미 |
W3C-TC-C2 Does not prove: trace-flags 의 sampled bit 의미는 spec 동일 섹션 추가 인용 필요 |
spec 재 fetch + ca-tmpl 의 sampling 결정이 01 flag 로 downstream 에 전파되는지 wire-level capture |
planned |
| W3C tracestate entry 의 List-Members 32개 / total length 제한 | W3C-TC-C4 Usage Boundary: tracestate entry 개수 / 크기 제한 spec 별도 섹션 추가 인용 필요 |
spec 재 fetch + vendor 별 tracestate 사용 크기 monitoring | planned |
| Micrometer Tracing TaskDecorator 가 @Async / Scheduled 경계에서 trace context 자동 전파 | 본 branch 인용 자료에 Micrometer Tracing TaskDecorator 직접 spec 없음. 실측: AsyncContextTaskDecorator 는 MDC copy 만 — Observation scope 미재establish (§Audit CARRIER_DRIFT) |
@Async 호출 → child thread 에서 Span.current() 또는 MDC trace_id 확인 test |
planned |
Kafka / RabbitMQ 의 traceparent header 가 consumer side 에서 자동 extract |
OTel Java instrumentation 의 Kafka / Rabbit Spring 모듈 spec 별도 raw 없음 | producer/consumer e2e test — trace span 이 연결되는지 Jaeger / Tempo UI 확인 | planned |
| force-sample on error/slow/retry-exhausted 가 head sampler 단독으로 구현 가능 | OTEL-SAMP-C4 Usage Boundary: head sampler 는 trace 전체 데이터 기반 결정 불가 — force-sample 은 별도 SDK 구현 |
OTel SDK ParentBased + AlwaysOn / TraceIdRatioBased 조합 + 커스텀 sampler 구현 확인 |
needs-confirmation |
| B3 → W3C edge translation 의 정확한 구현 (multi-propagator 패턴) | B3-C5/B3-C6 Usage Boundary: receiver precedence 만 규정 — edge converter 구현 별도 |
OTel SDK propagators=tracecontext,b3 설정 + 외부 시스템 fixture test |
planned |
tracestate name/value vs key/value 표현 차이 (W3C-TC-C4) 의 정확한 spec 표현 |
2026-05-27 fetch 와 2026-05-25 캡처 표현 차이 — needs-confirmation |
W3C TR 페이지 단어 단위 재 fetch | needs-confirmation |
Observation.error(throwable) → OTel span recordException + setStatus(ERROR) 체인 |
공식 docs 산문 부재 — OtelSpan.error() 소스코드로만 확인(MICR-OBS-C1 + OTEL-TAPI-C4 간접) |
Micrometer Tracing reference(docs.micrometer.io/tracing) fetch 또는 OtelTracingObservationHandler 테스트로 span status 확인 |
needs-confirmation |
테스트 계약
- inbound 요청의 traceId가 response meta, log, outbound call에 연결되지 않으면 실패.
- async/job/message boundary에서 correlationId가 사라지면 실패.
- baggage에 금지 정보가 기록되면 실패.
- tracing disabled local profile에서도 requestId/correlationId log field는 유지되어야 함.
- tracing disabled 상태에서
meta.traceId가 누락되면 실패.
Audit & Findings
/branch-spec(2026-06-14) ground-truth 대조에서 발견한 drift·정합 권고·구현 상태. 사용자 작성 결정 영역은 자동 rewrite 하지 않고 정합 권고만 남긴다.
- CARRIER_DRIFT (§구현 가이드 §2): Async/Messaging Carrier Keys 표의
@Async TaskDecorator | thread-local copy via Micrometer Observation는 ca-tmpl 코드와 drift. 실제src/app-bootstrap/.../async/AsyncContextTaskDecorator.java는MDC.getCopyOfContextMap()기반 plain MDC 문자열 copy 이며 worker thread 에 Micrometer Observation scope 를 재establish 하지 않는다(javadoc 명시: io.micrometer:context-propagation + ContextPropagatingTaskDecorator 는 future enhancement). 표를 실측으로 정정함. carrier 전파 구현의 owner 는 background-job-async / runtime-context-propagation branch. - RESTATED_FOREIGN_DECISION (D9): D9 의 layer-notation mapping(snake/camel/kebab)은 foundation
D19+mdc-keys.yaml/headers.yaml(owner_branch = foundation)이 SSOT. consistency-contract(Single-Owner/Reference-Only)상 D9 는 재진술 이 아니라 foundation D19 의 consume pointer 여야 한다. D9 row 에 owner pointer 를 명시함. 추가 권고:## 결정 사항의 2026-05-22 identifier 표기 항목의 "본 branch의 Propagation Defaults 표가 보장" 문구는 "foundation D19 + mdc-keys.yaml/headers.yaml 이 SSOT, 본 branch 는 propagation 경계만 소유" 로 약화하는 것이 정확(사용자 결정 영역 → 권고만). - IMPL_STATUS (D1/D12): env/metric/header registry row 는 등록됐으나(
owner_branch= 본 branch 확인), Micrometer Tracing config·OTLP exporter·Observation error handler·커스텀 sampler 클래스는src/에 미존재. D1/D6 코드는planned/documented-only. D12 부분 구현:SpanErrorRecorder인터페이스 +NOOPconstant 는actually-implemented(Slice 1, 2026-06-14); tracer-backed 구현체는planned. governing doc wiki/projects/ca-tmpl/observability-log-metric-trace-runbook 의 "과장 금지" 절과 정합 — 면접/포트폴리오에 "OTel 로 구현/운영했다" 금지. Slice 1 신규 타입:TraceParent(D5/D7),BaggageAllowlist(D2/D8),SpanErrorRecorderNOOP seam (D12) — 3개 모두actually-implemented, 58 testslocally-verified, 2026-06-14. - GROUND_TRUTH 확인: ca-tmpl 경로 존재. registry
owner_branch = feature-distributed-tracing-contract를 env-keys/metrics/headers/secrets-classification 에서 확인.NO_GROUND_TRUTH아님.
Seam composition 위험 / fork 가 실 tracer 배선 시 밟는 지뢰 (2026-06-15)
메타 위험: Scope C 구현은
./gradlew check1091 green 이나, 이 테스트는 실 OTel SDK 없이 mechanism 만 검증한다. seam 은 실 tracer 와 단 한 번도 composition-test 된 적 없다. "1091 green = seam 이 SDK 와 검증됨" 은 거짓 확신 — 아래 두 정합 위험은 green 이 구조적으로 못 잡는다. 둘 다 spec §Claims To Verify 의planned/needs-confirmation항목(trace-flags sampled bit / Micrometer 통합)과 직접 연결된다.
- LANDMINE-1 — outbound
sampled=00하드코딩이 downstream trace 를 능동적으로 억제 (TraceContextPropagationInterceptor): mdc-keys.yaml(foundation SSOT)에 sampled/trace-flags carrier key 가 없으므로, outboundtraceparent는trace_id+span_id로만 재구성되고 flags 는00(not-sampled)으로 강제된다. downstreamParentBasedsampler 는00을 "parent not sampled" 로 읽어 child span 을 drop → 상류가 sample 한 trace 도 이 경계에서 끊긴다. 게다가 이 interceptor 는OutboundHttpClient에서 첫 번째로 등록되어traceparent를 먼저 stamp 하고, idempotency guard 가 이후 OTel instrumentation 을 skip 시킨다 —00은 fallback 이 아니라 실 결정을 덮어쓴다. seam 이 중립이 아니라 능동적으로 sampling 을 끄는 상태.- fork 조치: (a) 이 interceptor 를 비활성/제거하고 OTel RestClient instrumentation 이
traceparent를 소유하게 하거나, (b)TraceParent.of(.., false)를 실Span.getSpanContext().isSampled()로 교체 + foundation 에trace_flagsMDC carrier 신설(= cross-branch, foundation D11/D19 소유). sampled 비트 보존은 본 branch 단독으로 불가 — mdc-keys.yaml 소유권이 foundation 이기 때문.
- fork 조치: (a) 이 interceptor 를 비활성/제거하고 OTel RestClient instrumentation 이
- LANDMINE-2 — filter-생성
meta.traceIdvs 실 SDK trace-id 발산 (RequestLoggingFilter): no-tracer skeleton 에서는 filter 가 inbound 부재 시trace_id를 민팅하고ResponseMetaFactory가meta.traceId로 투영한다. fork 가 Micrometer Tracing 을 켜면 OTel SDK 도 같은 요청에 trace-id 를 민팅하고 SLF4J-Micrometer bridge 가 자기 id 를 MDCtrace_id에 쓴다. filter 가 이기면 응답의meta.traceId≠ 실제 export 된 span 의 trace-id → "응답에 박힌 id 로 백엔드에서 trace 추적"(D4 핵심 목적)이 조용히 깨진다.- fork 조치: 실 tracer 가 MDC
trace_id의 단독 owner 가 되도록 filter 를 tracing observation 이후로 ordering 하거나, filter 가Span.current()를 adopt 하도록 교체. ordering/scope 의존 → 반드시 통합 테스트로meta.traceId == exported trace-id확인.
- fork 조치: 실 tracer 가 MDC
- 권고(차기 작업): 이 두 지뢰의 진짜 해소는 (1) foundation 에
trace_flagsMDC carrier 추가(cross-branch) + (2) 실 OTel SDK 와의 composition 통합 테스트(Testcontainers OTLP collector / Jaeger 로meta.traceId↔exported span 일치 + sampled 보존 검증)를 요구한다. 둘 다 Scope C(본 branch 단독) 밖 —planned로 명시. 코드에는TraceContextPropagationInterceptor/RequestLoggingFilterjavadoc 에 ⚠ FORK LANDMINE 블록으로 박아둠.
완료 후 wiki 추출 대상
wiki/projects/ca-tmpl/observability-log-metric-trace-runbook.md의 observability/tracing canonical section (governing doc).
관심사 커버리지 (coverage-auditor 생성 — 2026-06-14)
governing doc wiki/projects/ca-tmpl/observability-log-metric-trace-runbook (§Trace) 이 요구하는 관심사를 본 branch 가 빠짐없이 덮는지의 결과. 기준:
rules/coverage-gate.md. 판정: Covered (missing 0).
| 관심사 | 상태 | owner | 심각도 | 근거 |
|---|---|---|---|---|
| 전파 형식: W3C traceparent 채택, B3 forbidden | covered-here | — | — | D5 (W3C-TC-C1/C2/C3), D7 (B3-C6); headers.yaml traceparent/tracestate owner |
| 트레이싱 라이브러리/exporter: Micrometer Tracing + OTel bridge | covered-here | — | — | D1 (SB-TRAC-C1~C4); env OTEL_EXPORTER_OTLP_ENDPOINT owner |
| 샘플링 전략: prod 1% / staging 10% / dev·local 100% + force-sample | covered-here | — | — | D6 (OTEL-SAMP-C1/C3/C4); env APP_TRACING_SAMPLE_RATE + metric tracing.sampling.rate owner |
| 대안 검토: tail-based / Datadog·X-Ray / B3 거부 | covered-here | — | — | D11 / D10 / D7; §외부 근거·대안 조사 |
| tracing 활성화 toggle + disabled 시 meta.traceId 유지 | covered-here | — | — | D4 (OTEL-TAPI-C1/C2/C3); env APP_TRACING_ENABLED owner |
| baggage: PII/token 금지 + allowlist (tenant_id/request_id) | covered-here | — | — | D2 (W3C-BAG-C1 + OTEL-BAG-C3), D8 (W3C-BAG-C2/C3 + OTEL-BAG-C4) |
| span error 기록: Observation.error() + error.code + sampled-only stack trace | covered-here | — | — | D12 (MICR-OBS-C1/C3 + OTEL-TAPI-C4). SpanErrorRecorder 인터페이스 + NOOP actually-implemented; tracer-backed impl 은 planned |
| log/trace 샘플링 분리 정합 (trace 1% vs log 10%) | delegated | raw/branch-notes/feature-log-management-contract | OK | D6 Open Risk + §엣지·실패·의존 포인터 |
| ID 의미 SSOT (traceId/spanId/correlationId/requestId 의미) | delegated | raw/branch-notes/feature-operational-error-observability-foundation | OK | D3 + D9 consume-pointer (foundation D11/D19, mdc-keys.yaml owner) |
| async/messaging carrier 실 전파 구현 (TaskDecorator/context propagation) | delegated | raw/branch-notes/feature-background-job-async-contract, raw/branch-notes/feature-runtime-context-propagation-contract | OK | §구현 가이드 §2 (carrier key 정의만 본 branch) + §Audit CARRIER_DRIFT |
마주친 문제
- SpanErrorRecorder 생성자 의존이 @WebMvcTest 슬라이스 컨텍스트를 깨뜨림 (2026-06-14, 해결됨): Slice 2 에서
GlobalExceptionHandler에SpanErrorRecorder생성자 파라미터를 추가하자,app-bootstrap의@Bean(@ConditionalOnMissingBean)만으로는 부족 —sample-portfolio의@WebMvcTest+@Import({Controller, GlobalExceptionHandler.class, ...})슬라이스 테스트 34개가NoSuchBeanDefinitionException: SpanErrorRecorder로 컨텍스트 로드 실패. @WebMvcTest 는 임의@Configuration을 component-scan 하지 않으므로 bootstrap 의 NOOP bean 이 슬라이스에 보이지 않았다. 해결:GlobalExceptionHandler에@Autowired ObjectProvider<SpanErrorRecorder>생성자를 추가해getIfAvailable(() -> NOOP)로 self-default — 모든 컨텍스트(풀 앱/슬라이스/유닛)가 bean 없이 wiring, fork 가 bean 기여 시 override. bootstrap 의 redundant bean + 테스트의 보조 @Import 는 제거. → raw/errors/spanerrorrecorder-constructor-breaks-webmvctest-slice-2026-06-14
묶음
- raw/company-tech-blogs/tracing-datadog-apm-vs-opentelemetry
- raw/official-docs/baggage-otel-baggage-api-spec
- raw/official-docs/baggage-w3c-baggage-spec
- raw/official-docs/tracing-b3-propagation-zipkin-spec
- raw/official-docs/tracing-micrometer-observation-introduction
- raw/official-docs/tracing-otel-sampling-tail-vs-head-spec
- raw/official-docs/tracing-otel-trace-api-spec
- raw/official-docs/tracing-spring-boot-3-actuator-tracing-reference
- raw/official-docs/tracing-w3c-trace-context-spec
본 feature branch 는 leaf — 자식 자료 없음. Phase C2 실 코드 작성 단계에서 errors / interview prep / lectures 가 누적되면 본 섹션에서 그룹화.
근거 자료
- raw/official-docs/tracing-w3c-trace-context-spec
- raw/official-docs/tracing-otel-sampling-tail-vs-head-spec
- raw/official-docs/tracing-b3-propagation-zipkin-spec
- raw/company-tech-blogs/tracing-datadog-apm-vs-opentelemetry
- raw/official-docs/tracing-micrometer-observation-introduction
- raw/official-docs/tracing-spring-boot-3-actuator-tracing-reference
- raw/official-docs/tracing-otel-trace-api-spec
- raw/official-docs/baggage-w3c-baggage-spec
- raw/official-docs/baggage-otel-baggage-api-spec
오류 기록 (본 feature 작업 중 발생)
- (없음 — Slice 1 구현 무오류 완료)
면접 준비 (이 작업에서 나올 수 있는 면접 질문)
- W3C traceparent 의 4개 필드와 각 필드의 유효성 검증 규칙(all-zero 거부, lowercase 강제 이유)을 설명하라.
- 왜 OTel의
recordException()만으로는 span status 가 ERROR 로 설정되지 않는가 —setStatus(ERROR)를 별도로 호출해야 하는 이유. - Java stdlib-only 모듈(
shared-contract)에 tracing 타입을 두는 이유와 trade-off. BaggageAllowlist의 D2/D8 결정 근거 — W3C Baggage spec 은 allowlist 를 정의하지 않는데 왜 여기서 allowlist 를 강제하는가.@WebMvcTest슬라이스에서 base 핸들러의 선택적 협력자를 어떻게 wiring 하는가 —@ConditionalOnMissingBean(composition-root bean) vsObjectProvider<T>self-default 의 차이와, 왜 후자가 컨텍스트 견고성이 높은가. (→ raw/errors/spanerrorrecorder-constructor-breaks-webmvctest-slice-2026-06-14)- "tracer 를 fork-activated seam 으로 둔다"는 결정의 의미 — 계약 메커니즘(전파/baggage/disabled fallback/span-error seam/sampling gauge)만 구현하고 OTel SDK 런타임은 미배선으로 두는 trade-off, 그리고 면접에서 "구현했다/운영했다"를 어디까지 말할 수 있는가(과장 금지 경계).
- 분산 추적 비활성(disabled) 상태에서도
meta.traceId를 유지하는 방법 — OTel SDK 를 noop 으로 두면 traceId=all-zeros 인데, app-generated W3C id(request filter)로 fallback 하는 이유.
job-posting tie-ins (이 작업에서 파생된 글감)
- "Spring Boot 에 OTel 없이 W3C traceparent 계약 타입만 구현하는 이유 — fork-activated seam 패턴"
관련 일일 노트
- (없음 — Phase C2 실 구현 단계에 누적)
완료 후 정리
머지/종료 시점에 채움.
- PR 링크:
- 리뷰 메모:
- 머지 결과 / 배포 환경:
- wiki 추출 대상 (verified만,
wiki/projects/로만 추출):actually-implemented항목: (1)shared.tracing.TraceParent/BaggageAllowlist/SpanErrorRecorder(+NOOP) pure 계약 타입; (2)RequestLoggingFilterW3Ctraceparentaccept/생성 +meta.traceIddisabled-fallback(D4); (3)GlobalExceptionHandlerSpanErrorRecorderseam 호출 +ObjectProviderself-default; (4)TraceContextPropagationInterceptoroutbound traceparent/X-Request-Id/X-Correlation-Id/allowlisted-baggage 전파; (5)TracingProperties(시작시 검증) +TracingSampleRateResolver(per-profile) +tracing.sampling.rategauge; (6).env/application.yml3키 배선; (7) 6개 required_test + §테스트계약 5종.locally-verified항목:cd src && ./gradlew check= BUILD SUCCESSFUL, 1091/1091 tests (verifyCleanArchitectureDependencies + verifyEnvKeys + ArchUnit 포함), 2026-06-14. 리뷰 체인(architect/spec/quality) 통과.prod-verified항목: (없음 — 운영 환경 미검증)
- 추출하지 않을 항목 (planned / documented-only / abandoned): 실 OTel SDK/Micrometer Tracing/OTLP exporter 런타임, 실 head/force-sample sampler, async Observation scope 재establish, B3 edge translation, tracestate 한계 모니터링 — 전부
planned(fork-activated seam). "OTel 로 추적을 구현/운영했다"는 추출 금지(과장 금지).