SLI / SLO 카탈로그

03-quality/slo-catalog.html · LogiNippon · TRD · 2026-06-13 · 신뢰도 라벨 확인/추정/설계

techspec의 8개 SLI(S1~S8)를 실측 가능한 숫자 SLO로 확정하고, 각각의 측정 윈도·데이터소스 쿼리·에러버짓 공식·관련 NFR/KPI ID를 고정한다. 모든 SLO 목표치는 운영 데이터가 없는 진입 단계의 초기 확정치(설계)이며 운영 베이스라인으로 분기별 조정한다 — 달성치(achieved)는 기재하지 않는다. 그리고 이 카탈로그의 전제이자 갭인 METRICS.writeDataPoint 미방출(현재 TODO)OBS-METRICS-001로 정규 요구화한다. 본 페이지는 NFR 페이지가 위임한 SLO 상세의 단일 소유처다.

p95 ≤ 200ms
S1 인제스트 accept (NFR-PERF-001)
p95 ≤ 5s
S2 지오펜스 평가 lag (NFR-PERF-002)
≥ 99.0%
S3 웹훅 전달 /28일 (NFR-RELY-001)
≥ 85%
S4 Tracking Rate floor (KPI-TRACK-001)
≥ 99.9%
S5 가용성 /역월 (NFR-AVAIL-001)
p95 ≤ 1.5s
S6 WebSocket 반영 (NFR-PERF-003)
≤ 25% → 15%
S7 ETA MAPE 룰→ML (KPI-ETA-001)
≥ 99%
S8 정규화 canonical (KPI-NORM-001)

1. 원칙 — 측정 불가능한 SLO는 요구사항이 아니다

SLO는 "약속한 숫자"가 아니라 "지속적으로 측정되어 위반 시 행동을 유발하는 숫자"일 때만 요구사항이 된다. 따라서 이 카탈로그의 모든 SLI는 측정 경로가 코드에 존재함을 전제로 한다.

현재 갭(as-built). METRICS(Analytics Engine loginippon_metrics) 바인딩은 존재하나(server/src/types/index.ts METRICS: AnalyticsEngineDataset), writeDataPoint 호출은 TODO다. 즉 현재 S1·S2·S3·S5·S6·S8은 측정되지 않는다. 이 카탈로그는 목표를 약속하기 전에 방출(emission)을 먼저 요구한다 → OBS-METRICS-001. 측정 평면이 없는 SLO는 본 TRD에서 "요구사항"이 아니라 "의도"로 간주한다.
두 종류의 지표. 시스템 SLI(S1·S2·S3·S5·S6·S8)는 "플랫폼이 건강한가", 제품 KPI(S4·S7)는 "서비스가 화주에게 주는 가치"를 잰다. S4(Tracking Rate)·S7(MAPE)은 두 렌즈를 동시에 갖는다 — 정의는 north-star-kpi와 동일하며, 여기서는 측정 윈도·에러버짓·알람을 추가한다.

2. SLO 카탈로그 (S1~S8)

아래 8행은 각 SLI의 정의, §4.1/§4.2 정규 수치표에서 글자 그대로 인용한 SLO 목표, 측정 윈도, 데이터소스 쿼리(어떤 메트릭/태그를 어떻게 집계하는가), 에러버짓 공식, 관련 NFR/KPI ID를 고정한다. 목표치는 전부 초기 확정치(설계)이며 운영 베이스라인으로 조정한다.

SLI 정의 / 측정 지점 SLO 목표 설계 측정 윈도 데이터소스 쿼리 (loginippon_metrics) 에러버짓 공식 관련 ID
S1 인제스트 accept 지연 POST /v1/ingest/positions 수신 → 202 {accepted} 반환까지(server/src/ingest/positions.ts 핸들러 entry→exit). 무거운 처리는 비동기. p95 ≤ 200ms, p99 ≤ 400ms 28일 롤링 blob: metric="ingest_accept"; double1=latency_ms; idx=route. quantileWeighted(latency_ms, .95) WHERE metric='ingest_accept' AND outcome='ok' over 28d. budget = events(latency>200ms) / events 총; 목표 ≤5%(p95 정의상) NFR-PERF-001
S2 지오펜스 평가 lag enqueue(GeofenceJob) → enter/exit 판정 + event INSERT까지. 컨슈머 handleGeofenceBatch(server/src/consumers/queue.ts)에서 ping.captured_at 또는 enqueue ts 대비 처리완료 ts. p95 ≤ 5s, p99 ≤ 15s 28일 롤링 blob: metric="geofence_lag"; double1=lag_ms; idx=queue='loginippon-geofence-eval'. quantileWeighted(lag_ms,.95). 큐 깊이는 Queues 지표 보조. budget = events(lag>5s)/총. 큐 max_batch_timeout=5s와 정합 — 초과는 백로그 신호 NFR-PERF-002
S3 웹훅 전달 성공률 첫 시도 또는 재시도 래더 내 2xx 수신 비율. 발신 지점 handleNotifyBatch(queue.ts, 큐 loginippon-notify). 발신 타임아웃 5s hard. ≥ 99.0% / 28일 28일 롤링 blob: metric="webhook_delivery"; idx=outcome∈{2xx,4xx,5xx,timeout}; double1=attempt. sum(outcome='2xx') / count(distinct delivery_id) over 28d. budget = 1 − 0.99 = 1.0% 실패/28일; 재시도 소진(8회) 후에도 비-2xx면 실패 1건 NFR-RELY-001 · FR-DLV-WH-001
S4 Tracking Rate (추적 커버리지) received_pings / expected_pings; expected = active_segment_sec / ping_cadence. 제품 KPI 겸 수집 파이프라인 건강도. 스마트폰 GPS 한계로 100%는 비현실 — 정직 노출. MVP exit floor ≥ 85%, 정상상태 지향 ≥ 92% 역월 (테넌트/캐리어 드릴다운) 1차: D1 집계(active_segment vs received pings). 보조: metric="ingest_accept" shipment 태그 카운트 / 기대 cadence. floor 미달 = 게이트 위반(에러버짓 아님; phase-gates P1 exit DoD 연결) KPI-TRACK-001
S5 가용성 대시보드/API 성공 응답 비율(5xx·timeout 제외). Web Analytics + 합성 점검(synthetic) 보강. 엣지 자동확장 전제. ≥ 99.9% / 역월 역월 (calendar month) blob: metric="http"; idx=outcome∈{ok,5xx,timeout}. 1 − sum(outcome∈{5xx,timeout})/count(*). 합성 프로브 별도 데이터셋 row. budget = 0.1%/월 ≈ 43분/역월 다운타임 허용 NFR-AVAIL-001
S6 WebSocket 실시간 반영 위치 push → 대시보드 broadcast까지. pushToDo 수신 → broadcast({type:'position'})(server/src/do/shipment.ts). Flutter 단일-shipment 라이브 뷰 체감 직결. p95 ≤ 1.5s, p99 ≤ 3s 28일 롤링 blob: metric="ws_broadcast"; double1=fanout_ms; idx=shipment_id(저카디널리티 샘플). quantileWeighted(fanout_ms,.95). DO 내부 계측. budget = events(fanout>1.5s)/총. console 플릿 개요는 폴링이라 별도(NFR-PERF-003b staleness) NFR-PERF-003
S7 ETA 오차 (MAPE) |predicted − actual_arrival| / actual 평균(배달 12h 전 기준). 룰 기반은 "추정치"(eta_is_estimate=1) 정직 표기. 콜드스타트엔 하드 SLO 아님. 룰 기반 ≤ 25%(하드 SLO 아님), ML 후 ≤ 15% 역월 (레인-클래스별) D1: 완료 운행의 predicted vs actual_arrival join. 보조 metric="eta_error" double1=ape; idx=lane_class. avg(ape). 하드 게이트 아님 → 번레이트 알람 대신 추세 보고. ML 전환 트리거는 FR-ENG-ETA-002 KPI-ETA-001
S8 이벤트 정규화 정확도 raw_code → canonical 해결률. 컨슈머 정규화 단계 event_code_map 미스 카운트. 미매핑 raw_code는 알림→매핑 보강. ≥ 99% canonical 해결(미매핑 <1%/일), 충돌 0 역월 (일 단위 미스 추세 병행) blob: metric="normalize"; idx=outcome∈{resolved,unmapped,collision}; blob2=raw_code. sum(resolved)/count(*); count(unmapped)/hour 알람. budget = 1.0% 미매핑/일; collision은 무관용(0 목표) KPI-NORM-001 · DM-EVT-ENUM-001
중복이 아니라 두 렌즈. S4·S7은 north-star-kpi·functional이 정의한 동일 지표를 SLO(목표·감시) 관점으로 재참조한다. 정의의 단일 진실원은 KPI/FR 페이지이며, 여기서는 ID를 소유하지 않고 링크한다. 본 페이지가 소유하는 새 ID는 OBS-METRICS-001 하나뿐이다(나머지 SLO-S* 행은 NFR/KPI ID의 측정 사양 확장).

3. 에러버짓 정책

가용성·성공률 SLO(S5·S3)에는 에러버짓 = 1 − SLO를 둔다. 버짓은 "위반 없이 쓸 수 있는 실패의 양"이며, 변경 속도(릴리스)와 안정화를 저울질하는 통화다.

SLO버짓 = 1 − SLO윈도소진 시 행동
S5 가용성 ≥ 99.9% 0.1% / 월 ≈ 43분 다운타임 역월 버짓 소진 시 prod 승격 차단(릴리스 게이트) — 신규 기능보다 안정화·회귀 수정 우선. pipeline-ops의 CI 게이트와 결합.
S3 웹훅 ≥ 99.0% 1.0% 실패 / 28일 28일 롤링 대량 disabled 또는 성공률 하락 시 발신 경로·구독자 엔드포인트 점검. 버짓 50% 소진 시 경고, 100% 시 발신 변경 동결.

번 레이트(burn rate) 알람. 단일 임계가 아니라 소진 속도로 경보한다. 번레이트 = (윈도 내 실패율) / (허용 실패율). 다중창 알람으로 거짓 경보를 줄인다.

진입 단계 캘리브레이션. 위 번레이트 계수는 Google SRE 워크북 표준값을 초기 차용한 설계 추정이다. 운영 베이스라인 수집 후 첫 분기에 거짓 경보율을 보고 임계를 조인다 — 무리한 목표로 alert fatigue를 만들지 않는다. 릴리스 게이트의 정식 정의·승인 흐름은 pipeline-ops가 소유한다.

4. OBS-METRICS-001 — METRICS.writeDataPoint 방출 요구

위 카탈로그 전체는 데이터포인트 방출에 의존한다. 현재 방출이 없으므로(§1 갭), 이를 정규 요구사항으로 못박는다. 아래 카드가 본 페이지가 소유하는 유일한 ID다.

OBS-METRICS-001 SLI별 writeDataPoint 방출 + 표준 태그 스키마 P0·MustPhase 1T 테스트

요구. 시스템은 S1·S2·S3·S5·S6·S8 각 SLI의 정의된 측정 지점에서 env.METRICS.writeDataPoint(...)반드시 호출하여 loginippon_metrics 데이터셋에 데이터포인트를 방출해야 한다(MUST). 현재 writeDataPoint는 TODO이며 측정 평면이 부재하다 — 이 요구가 충족되기 전까지 S1·S2·S3·S5·S6·S8 SLO는 "의도"이지 측정 가능한 요구사항이 아니다.

호출 지점(SLI 매핑).

  • S1 인제스트: server/src/ingest/positions.ts202 반환 직전, 핸들러 entry→exit 경과로 ingest_accept 방출.
  • S2 / S8 컨슈머: server/src/consumers/queue.ts handleGeofenceBatch — 평가 lag(geofence_lag) + 정규화 결과(normalize: resolved/unmapped/collision)를 ping 처리마다 방출.
  • S3 웹훅 발신: handleNotifyBatch(큐 loginippon-notify) — POST 응답 코드·시도 횟수로 webhook_delivery 방출(발신 구현 시 동시 배선; 현재 ack-only STUB).
  • S6 DO broadcast: server/src/do/shipment.ts broadcast() — push 수신→fan-out 경과로 ws_broadcast 방출.
  • S5 가용성: server/src/middleware/error.ts 응답 경로 — 전 요청 outcome(ok/5xx/timeout)으로 http 방출 + 합성 프로브 row.

태그 스키마(표준). 모든 데이터포인트는 차원 request_id·route(또는 queue/op)·tenant·outcome를 인덱스/blob에 부착한다(좌표·실명 금지 — PII 최소화). 지연 계열은 doubleslatency_ms/lag_ms/fanout_ms를 싣는다.

수용기준

  • Given 정상 인제스트 1건, When POST /v1/ingest/positions202를 반환, Then loginippon_metricsmetric='ingest_accept', outcome='ok', route·tenant·request_id 차원과 latency_ms를 가진 데이터포인트가 정확히 1건 기록된다.
  • Given 미매핑 raw_code 1건, When 컨슈머 정규화가 event_code_map 미스로 떨어짐, Then metric='normalize', outcome='unmapped', raw_code blob을 가진 데이터포인트가 기록되어 S8/§5 알람이 집계 가능하다.
  • Given 임의 데이터포인트, When 차원을 검사, Then request_id·route(or queue/op)·tenant·outcome가 모두 존재하고 좌표/실명 필드는 부재한다.
근거 techspec 08-operations/observability-slo.md(Analytics Engine·writeDataPoint·상관 키) · 구현 server/src/types/index.ts(METRICS: AnalyticsEngineDataset 바인딩 존재) STUB(writeDataPoint TODO=ABSENT) · 검증 T 테스트(메트릭 방출 단언 회귀)

5. 알림 임계

여기서의 알림은 시스템 건강(SLO 위반·예외 폭증·비용)을 다룬다 — 제품 예외(배달 지연·荷待ち 초과 등)와 채널은 재사용(LINE/이메일)하되 대상이 다르다. 임계는 디바운싱·중복 억제로 거짓 경보를 줄인다.

트리거임계 설계심각도채널·동작관련
미매핑 raw_code 급증 (S8) unmapped > 50 / 시간 LOW~MEDIUM 대시보드 + 일일 요약 → event_code_map 보강. 정밀도 매트릭스 충돌은 무관용. KPI-NORM-001
추적손실 오경보율 (FR-ENG-EXC-003 정합) 오경보율 > 5% MEDIUM 이메일 + 임계 튜닝 검토. TRACKING_LOST(마지막 유효 핑 후 45min, Cron 5min sweep)의 거짓 양성 비율 감시. FR-ENG-EXC-003
가용성/지연 SLO 빠른 소진 (S5·S1·S6) 번레이트 1h ≥ 14.4 HIGH LINE 즉시 + 버짓 소진 추세 동반 보고. prod 승격 차단 연동. NFR-AVAIL-001
큐 백로그/소비 지연 (S2) p95 lag > 5s 지속 or DLQ 증가 HIGH LINE/이메일. 소비자 스케일·핫스팟 점검. max_batch_timeout=5s 초과는 백로그 신호. NFR-PERF-002
웹훅 성공률 하락 / 대량 disabled (S3) 28일 성공률 < 99% 추세 MEDIUM~HIGH 이메일 + 대시보드. 8연속 실패 auto-disable 급증 감시. NFR-RELY-001
비용 가드레일 근접 D1 쓰기 ≥ 70% 일 예산, R2 ≥ 80% 티어, DO active-time 월 cap 근접 MEDIUM 이메일 + 비용/한도근접 대시보드. 아카이브·샤딩·폴링 분할 레버 검토. NFR-COST-001 · NFR-SCALE-001
측정 의존성. 위 알림은 전부 OBS-METRICS-001의 데이터포인트 방출(또는 S4·S7의 D1 집계)에 의존한다. 방출이 배선되기 전에는 이 임계들은 대기(armed-but-blind) 상태다 — TRD 추적성 매트릭스(acceptance-traceability)에서 이 의존을 단일 차단 항목으로 표기한다. 인시던트 심각도(P1~P4) MTTA/MTTR·온콜·릴리스 게이트의 정식 운영 정의는 pipeline-ops가 소유한다.
법무 서명 플래그(RR-LEGAL). 본 페이지의 가용성·웹훅 SLO는 내부 운영 목표이며 외부 계약상 SLA가 아니다. 규제 산출물(実運送体制管理簿·荷待ち 기록)의 가용성·보존이 법정 의무 수준을 충족하는지는 미확정 — 공식 포맷·보존 요건의 법무 확인은 RR-LEGAL-001로 위임한다(추정 규제 사실).

근거·상호참조