Files
llm-wiki/vault/30-knowledge/projects/ca-tmpl/observability-log-metric-trace-runbook.md
T

144 lines
11 KiB
Markdown

---
title: ca-tmpl - Observability Baseline 결정 (Log + Metric + Trace + Runbook)
source_type: project
status: verified
confidence: high
tags: [ca-tmpl, observability, logging, metrics, tracing, actually-implemented, locally-verified, documented-only]
related_projects: [ca-tmpl]
last_reviewed: 2026-07-02
---
# ca-tmpl - Observability Baseline 결정 (Log + Metric + Trace + Runbook)
> Layer: `wiki/projects/` — 내 프로젝트 사실. 일반 개념은 [[wiki/concepts/observability-log-metric-trace-runbook]] 참조.
## 프로젝트 컨텍스트
ca-tmpl은 Clean Architecture 기반 백엔드 skeleton 프로젝트다. **운영 계약(operational contract)** 단계에서 observability 4축 — **structured JSON Logback + masking, Micrometer dot.case + Prometheus, W3C tracecontext 전파, `runbook://` scheme** — 을 baseline으로 묶어 단일 운영 계약으로 통합하는 결정을 했다.
현재 진행 상태:
- **Phase E (운영 계약 설계) 완료** — 4 sub-topic 각각의 branch-note가 작성되어 대안 검토와 결정 근거가 정리됨.
- **C2 (구현 단계) 미진입** — 어떤 Logback config, Micrometer registry, Sleuth/Tracing 설정 파일도 작성되지 않음.
**정정 (2026-06-04):** "문서/설계 산출물만 존재"는 더 이상 정확하지 않다. 4축(Log/Metric/Trace/Runbook)의 *full* 기능은 여전히 미구현이지만, foundation branch가 소유한 **observability 토대 slice**(MDC snake_case 표준 + 응답-로그 상관 + inbound 헤더 sanitization)는 2026-06-01 Phase C2로 코드화·로컬 검증됐다(아래 actually-implemented / locally-verified).
> **Ground-truth 대조 (2026-06-04, ca-tmpl @0c996fc "운영 에러 관측성 foundation 계약 구현", HEAD `db61075`에서도 존재 확인):** 아래 foundation slice 파일·MDC 키는 ca-tmpl 코드 실측으로 일치 확인. `MdcKeys.java`는 `request_id`/`trace_id`/`span_id`/`correlation_id`/`user_principal` snake_case 상수를 정의하고 **`tenant_id`는 아직 없음**(tenant-context-policy branch 도착 시 조건부). `RequestLoggingFilter.java`는 `adapter-web/filter/`에 위치(observability 패키지 아님). 패키지 root는 `dev.caskeleton.*`, 모듈 경로는 `src/<module>/src/main/java/dev/caskeleton/...`. stale 추출 잔재(`com.example.blog`/`sample-ticket`)는 없음 — sample 모듈은 `sample-portfolio`.
## 실제 구현 내용 (`actually-implemented`)
> 4축(Log/Metric/Trace/Runbook)의 *전체* 구현은 여전히 각 owner branch의 미진입 작업이다(아래 documented-only). 단 **foundation branch([[raw/branch-notes/feature-operational-error-observability-foundation]])가 소유한 observability 토대 slice**는 2026-06-01 Phase C2로 코드화됨 (grep 확인):
- `adapter-web/observability/MdcKeys.java` — MDC key snake_case 상수 표준(`request_id`/`trace_id`/`span_id`/`correlation_id`).
- `app-bootstrap/logback-spring.xml` — snake_case `includeMdcKeyName` 설정.
- `adapter-web/observability/HeaderSanitizer.java` — inbound 헤더 CR/LF·제어문자 strip + length cap (log injection / CWE-117 방어).
- `adapter-web/filter/RequestLoggingFilter.java``X-Request-Id`/`X-Correlation-Id` 수신·생성·MDC set/clear + sanitization 적용.
- `shared-contract/response/ResponseMeta.java` + `adapter-web/observability/ResponseMetaFactory.java``request_id`/`trace_id`/`correlation_id` MDC → `meta.{requestId,traceId,correlationId}` 응답 투영.
이것은 log/metric/trace 신호의 *식별자 토대*(MDC 표준 + 응답-로그 상관 + 헤더 sanitization)이며, 4축의 full 기능(JSON masking/sampling, Prometheus, trace sampling, runbook)은 포함하지 않는다.
## 로컬/dev 검증 (`locally-verified`)
위 foundation slice는 `./gradlew check` (전 모듈 test + ArchUnit) **BUILD SUCCESSFUL** (2026-06-01)로 검증됨 — `HeaderSanitizerTest`/`ResponseMetaFactoryTest`/`RequestLoggingFilterTest`/`EnvelopeMetaIntegrationTest`. **4축 full 구현(masking 효과·alert 발화·trace sampling·runbook link-check)의 로컬 검증은 여전히 없음.**
## 운영 검증 (`prod-verified`)
**없음.** 운영 환경 검증 없음. alert 발화·trace sampling 결과·log masking 효과 측정 모두 없음.
## 문서/계획만 존재 (`documented-only` / `planned`)
운영 계약 문서(canonical §8, §29 G-A)와 4 branch-note에 다음이 **설계 수준**으로만 기록되어 있다.
### Log (`documented-only`)
- Structured JSON Logback 스키마: `@timestamp`, `log.level`, `service.name`, `trace.id` 등 ECS 호환 필드.
- Masking 항목: PII / credential / token 필드 발신지 마스킹 정책.
- Sampling: prod 환경 일반 로그 10% sampling, error/warn 전량 sampling.
- 대안 검토: ECS vs OTel log signal vs Loki 자체 schema — branch-note `feature-log-management-contract`.
### Metric (`documented-only`)
- Micrometer dot.case naming + Prometheus exporter(`_` 변환).
- Alert severity: P1 / P2 / P3 분리.
- Cardinality bound: `userId`·`requestId` 등 unbounded label 금지.
- 대안 검토: SLO burn-rate vs traffic-based threshold — branch-note `feature-metrics-alerting-contract`.
### Trace (`documented-only`)
- W3C traceparent 헤더 채택 (B3 미채택).
- Micrometer Tracing + OTel bridge 방향.
- Sampling: prod 1% head-based.
- 대안 검토: head-based vs tail-based, B3 hybrid 변환 — branch-note `feature-distributed-tracing-contract`.
### Runbook (`documented-only`)
- `runbook://` 내부 URI scheme + repo path 매핑.
- Alert payload에 runbook URL 박아넣는 계약.
- Link-check smoke test로 drift 방지.
- 대안 검토: Confluence runbook vs runbook-as-code vs PagerDuty Runbook Automation — branch-note `feature-operational-runbook-contract`.
**모두 문서/설계 단계.** Logback config, Micrometer registry 설정, Sleuth/Tracing 설정 파일, runbook markdown 본문 모두 미작성.
## 면접에서 말할 수 있는 범위
### 자신 있게 답할 수 있는 (개념·설계 의도)
- Observability 3 pillars(log/metric/trace) 정의와 각 신호가 대체 불가능한 이유.
- W3C tracecontext vs B3 propagation 차이 (128-bit vs 64-bit trace-id, 변환 한계).
- Log masking 범위와 발신지 마스킹이 필요한 이유.
- Runbook drift 방지를 위해 `runbook://` scheme + git 관리 + link-check를 선택한 설계 근거.
### 적당히 답할 수 있는
- SLO burn-rate alert vs traffic-based threshold의 트레이드오프 — SLO 합의 전 단계에서 traffic-based가 합리적인 이유.
- Head-based vs tail-based sampling의 비용/정확도 trade-off.
### 답하면 안 되는 (실측·운영 경험 없음)
- "Grafana 대시보드를 운영하면서…" — 대시보드 미구축.
- "trace 1% sampling 결과 rare-error 누락률은…" — 측정 없음.
- "incident response를 실제로 수행하면서…" — 운영 경험 없음.
- "log masking으로 PII 사고를 막은 사례" — 미적용.
## 과장 금지 지점
- **"OpenTelemetry로 통일했으니 vendor-neutral이다"** → ❌. instrument 표준은 중립이지만 backend(Datadog/Tempo/Jaeger) 선택 시 lock-in 잔존.
- **"SLO burn-rate alert를 채택했다"** → ❌. 설계 단계에서 검토만 했고, SLO 자체가 합의되지 않은 단계에선 traffic-based가 더 운영 가능함을 결론으로 두었다.
- **"운영 환경에서 alert가 동작하는 것을 확인했다"** → ❌. 미구현. alert rule 파일조차 없음.
- **"structured logging을 적용해 PII를 안전하게 처리하고 있다"** → ❌. masking 정책은 문서에만 존재.
- **"trace sampling 1%로 비용을 최적화했다"** → ❌. 적용 결과 없음. 설계상 채택만.
- **"runbook을 자동화했다"** → ❌. `runbook://` scheme은 정의했으나 자동 실행 도구 미도입.
### Blog-topic ingest: w3c-traceparent-fork-activated-seam (2026-07-02)
[[raw/blog-topics/w3c-traceparent-fork-activated-seam-2026-07-02]] 는 OTel SDK를 붙이기 전에 W3C `traceparent` 계약을 먼저 둘 때 생기는 seam과 landmine을 블로그로 풀기 위한 raw seed다.
- **canonical 반영 범위**: distributed tracing contract의 W3C trace context seam을 observability canonical에 연결했다.
- **source-backed 로 말할 부분**: W3C Trace Context와 OTel 관련 설명은 공식 raw source claim으로 확인된 범위에 한정한다.
- **블로그 전 과장 방지**: end-to-end distributed tracing 구현 완료처럼 쓰지 않고, seam/contract 중심으로 제한한다.
- [[raw/blog-topics/runbook-coverage-junit-contract-test-2026-07-02]]: 운영 runbook 링크가 문서에만 존재하는지, error registry와 연결되어 release를 막을 수 있는지 JUnit contract test로 확인하는 글감. runbook 내용 품질까지 자동 보장한다고 쓰지 않고 coverage/link existence 검증으로 제한한다.
- [[raw/blog-topics/logback-layer1-secret-masking-json-vs-pattern-2026-06-14]]: Logback `%replace`가 JSON encoder 경로를 우회하는 문제와 JSON decorator / pattern converter가 같은 masking regex SSOT를 공유해야 하는 이유를 다루는 글감. regex masking이 모든 secret 형태를 잡는다고 쓰지 않는다.
- [[raw/blog-topics/spring-async-taskdecorator-bounded-executor-saturation-shutdown-2026-06-13]]: bounded executor, `TaskDecorator` MDC/context propagation, saturation metric, graceful shutdown budget을 하나의 background job 운영 계약으로 다루는 글감. 숫자값을 부하테스트 튜닝 결과처럼 쓰지 않는다.
## 관련 개념
- [[wiki/concepts/observability-log-metric-trace-runbook]]
## Sources
- [[raw/project-notes/ca-skeleton-operational-contract]] — ca-tmpl 운영 계약 SSOT (§8 Structured Log, §29 G-A).
- [[raw/branch-notes/feature-log-management-contract]] — JSON Logback + masking + trace 상관관계 계약.
- [[raw/branch-notes/feature-metrics-alerting-contract]] — Micrometer dot.case + alert severity 계약.
- [[raw/branch-notes/feature-distributed-tracing-contract]] — W3C tracecontext 전파 + sampling 계약.
- [[raw/blog-topics/w3c-traceparent-fork-activated-seam-2026-07-02]] — W3C traceparent seam 블로그 글감 raw seed
- [[raw/branch-notes/feature-operational-runbook-contract]] — `runbook://` scheme + link-check 계약.
- [[raw/blog-topics/runbook-coverage-junit-contract-test-2026-07-02]] — runbook coverage JUnit contract test 블로그 글감 raw seed.
- [[raw/blog-topics/logback-layer1-secret-masking-json-vs-pattern-2026-06-14]] — Logback JSON vs pattern masking 블로그 글감 raw seed
- [[raw/blog-topics/spring-async-taskdecorator-bounded-executor-saturation-shutdown-2026-06-13]] — async executor context/saturation/shutdown 블로그 글감 raw seed
## Cluster / 묶음
<!-- GENERATED: derived-blogs:start -->
- [[wiki/blog/ca-tmpl-observability-log-metric-trace-runbook-2026-07-02]]
<!-- GENERATED: derived-blogs:end -->