실습: 운영 모니터링 결과 기록하기¶
운영 신호는 확인한 시간대와 대표 요청을 함께 남겨야 원인 후보를 점검하는 근거가 됩니다. 이 실습에서는 어떤 대시보드 조회식과 트래픽 시나리오를 어느 시간대에 확인했는지, 대표 요청에서 무엇을 찾았는지 기록합니다.
실습의 결과물
- 팀 산출물: 실시간 경로에서는 환경·모델 정보, 세 run ID, 시나리오별 UTC 구간·상태, 대시보드 URL·절대 UTC 조회 범위를 담은 수집 매니페스트(collection manifest)를 남깁니다. 오프라인 경로에서는 같은 역할의 준비된 수집 묶음을 지정합니다.
- 개인 산출물: 같은 범위를 직접 복원해 본 개인 관찰 기록과 6교시에서 이어 볼 대표 request ID
강의 순서에서의 위치
5교시는 099~108에 해당하는 운영 신호와 비교 범위를 고정하고 팀 수집 기록만 남깁니다. live 경로를 고르면 0, 1, 3, 4-1절을, offline 경로를 고르면 0, 1, 2절을 따릅니다. live 인계 점검에서 필요한 정보가 빠졌을 때만 2절의 offline 자료로 전환합니다. 6교시는 109~116에 해당하는 요청 단위 조사입니다. 저장 범위 분석에서 그 자료의 절대 UTC 범위를 복원해 대표 요청을 고르고, 5-1 입력 분포와 5-2 점수와 예측 분포를 보조 읽기로 연결합니다. 같은 교시 안에서 5-3 요청 한 건에서 원인 후보 추적하기로 로그, 처리 경로, 상관관계와 원인 후보를 확인합니다.
먼저 예상하기¶
명령을 실행하기 전에 앞선 근거의 두 조건을 보고 다음 질문에 답합니다.
- 같은 기준 모델에서
baseline과current-shift의 예측 비율·점수 P95가 달라졌다면 어떤 원인 후보를 먼저 확인할 것인가? invalid의 422가 늘어도 5xx 오류율 패널에는 보이지 않을 수 있는 이유는 무엇인가?- 대표 요청의 trace가 어디까지 이어져야 수집과 전파가 정상이라고 볼 것인가?
예상 trace는 traffic.generate → risk-api.predict (CLIENT) → POST /v1/predict (SERVER) → risk.predict입니다. KServe를 사용하는 환경에서는 그 아래에 kserve.infer CLIENT·SERVER·내부 추론 구간이 이어집니다. 예상과 다른 결과가 나오면 원인 후보 표에서 어떤 상태를 바꿀지도 한 줄 적습니다.
관측 환경과 확인 범위¶
조회식, 트래픽, 시간대가 빠진 운영 기록은 대시보드 한 화면을 과장한 결론이 되기 쉽습니다. 이 실습에서는 이 세 정보를 함께 기록하며, 지표, 로그, 추적 기록, 95백분위수(P95)의 역할이 낯설다면 실행 환경과 운영 기록과 대시보드 자료를 해석하는 방법을 먼저 읽습니다.
확인 경로 선택
모든 명령은 tta-aiqa 저장소 루트에서 실행합니다. 실습 환경 준비에서 노트북 환경을 확인한 뒤, 접속 정보가 없으면 대시보드 정적 검사와 준비된 오프라인 묶음으로 상관관계 추적을 연습합니다. 로컬 API가 있으면 /metrics를 확인하고, Grafana Cloud와 Alloy가 준비된 경우에만 실시간 트래픽과 대시보드 시간대를 확인합니다.
정적 검사와 준비된 묶음은 조회식·로그·trace 계약을 연습하는 scope=static 근거입니다. 실시간 자료를 보지 못했다면 그 이유와 다음 담당자의 조치를 기록하며, 접속 자격 자료는 Git에 추가하지 않습니다.
0. 준비 상태 기록¶
대시보드 URL 하나만으로 대상 환경 배포를 증명했다고 쓰지 않으려면 확인 범위를 먼저 정해야 합니다. 이번 보고서에서 ‘조회식만 확인함’, ‘준비된 오프라인 묶음을 확인함’, ‘로컬 지표를 확인함’, ‘Grafana Cloud의 실시간 자료를 확인함’ 가운데 하나를 고르고, 3장에서 확인한 API 모델 정보와 함께 기록합니다. 외부 환경을 사용할 수 없다면 그 이유와 담당자의 다음 조치를 함께 남깁니다.
| 확인 범위 | 뜻 |
|---|---|
| 조회식만 확인함 | 노트북과 템플릿에서 대시보드 조회식만 확인했습니다. |
| 준비된 오프라인 묶음을 확인함 | 저장소의 준비 자료에서 실행 ID→요청 ID→로그→trace 부모 관계를 연습했습니다. 실시간 수집을 확인한 것은 아닙니다. |
| 로컬 지표를 확인함 | 로컬 API의 /metrics에서 지표를 직접 확인했습니다. |
| Grafana Cloud의 실시간 자료를 확인함 | Grafana Cloud에서 환경, 시간대, 모델 정보, 운영 지표를 직접 확인했습니다. Compose에서 만든 신호라면 scope=local, 제공된 대상 환경에서 만든 신호라면 scope=target입니다. |
1. 노트북으로 대시보드 조회식 점검¶
대시보드 조회식과 코드 설정이 맞는지는 실시간 값이 없어도 먼저 점검할 수 있습니다. 이 노트북은 대시보드가 어떤 지표와 데이터 소스를 읽도록 설정됐는지 확인합니다.
labs/chapters/ch04/01_inspect_dashboard_contract.ipynb
정적 검사는 대시보드가 실제 운영 자료를 받는지까지 보여 주지 않고, 선언한 조회식과 데이터 소스가 맞는지만 확인합니다.
노트북 결과는 다음처럼 나눠 기록합니다.
- UID·지표 이름·데이터 소스: 조회식 계약을 확인한 근거
- 로컬
/metrics: API를 실제로 실행했을 때만 로컬 지표 확인 근거 API_NOT_RUNNING: 실시간 값이 아니라 실행을 막은 조건
| 확인할 항목 | 예상 결과 | 보고서에서 쓰는 방법 |
|---|---|---|
| 대시보드 UID | tta-aiqa-quality |
같은 대시보드를 반복해 가져오는 식별값 |
| 지표 이름과 필터 | 다섯 개 aiqa_risk_* 지표와 제한된 scenario 필터가 있음 |
코드, 설정, 대시보드 조회식이 맞는지 확인 |
| 데이터 소스와 시나리오 | timeseries=Prometheus, logs=Loki, traces=Tempo이며 세 조회 경로에 $scenario 선택이 적용됨 |
지표, 로그, 추적 기록을 같은 비교 조건으로 좁힘 |
로컬 /metrics |
API 실행 시 모델 버전 시계열, 미실행 시 API_NOT_RUNNING |
로컬 지표를 보았는지 또는 막힌 조건 |
노트북 정적 검사가 통과해도 Grafana Cloud 수집까지 확인한 것은 아닙니다. 실제 /metrics나 대시보드 URL을 보지 못했다면 AVAILABLE이라고 기록하지 않습니다.
2. 준비된 오프라인 자료의 범위 확인¶
Grafana Cloud, Loki, Tempo를 사용할 수 없는 팀은 schema v2의 범위가 고정된 수집 묶음을 사용합니다. 이 파일에는 세 시나리오의 대시보드 요약·시계열과 정상·느린·422 대표 요청의 로그·trace가 함께 있지만, 실제 수집 자료는 아닙니다.
docs/evidence/incident/prepared-observability-correlation.json
jq '{schema_version, artifact_id, classification, live_telemetry, provenance, limitations, observation_window, environment, handoff_contract, model, dashboard, representative_requests, selection_rules}' \
docs/evidence/incident/prepared-observability-correlation.json
이 명령은 현재 교시에서 사용하는 필드만 보여 줍니다. 원본 파일의 purpose는 이전 교시 배치를 설명한 레거시 메타데이터이므로 현재 수업 순서나 판단 근거로 사용하지 않습니다.
5교시 팀 수집 기록에는 classification=PREPARED/OFFLINE, live_telemetry=false, environment.scope=static을 확인합니다. 이어 handoff_contract의 session ID와 수집 묶음 경로, observation_window의 절대 UTC 범위, model, 시나리오별 run ID를 팀 인계값으로 사용합니다. live 수집 매니페스트 경로인 artifacts/traffic/collection-session.json과 오프라인 수집 묶음 경로를 같은 파일로 착각하지 않습니다.
수집 묶음 안의 자료는 교시별로 다음 역할을 맡습니다.
| 교시 | 사용할 필드 | 확인할 내용 |
|---|---|---|
| 5교시 수집 인계 | handoff_contract, observation_window, model, environment |
scope=static, 절대 UTC 범위와 모델 정보 |
| 6교시 대시보드와 요청 분석 | dashboard.scenario_summaries, dashboard.time_series |
세 시나리오의 요청·상태, 5xx, 지연 P95, 누락 특성 P95, 점수 P95, 고위험 예측 비율 |
| 대표 요청 조사 | representative_requests |
normal, slow, invalid_422 가운데 6교시에서 고른 요청의 로그·trace |
5교시에는 숫자의 원인을 해석하지 않고 팀 수집 범위만 확인합니다. 6교시에는 수집 묶음의 범위가 고정된 요약과 시계열을 같은 절대 UTC 범위에서 분석하고, 대표 요청을 골라 5-3 요청 한 건에서 원인 후보 추적하기에서 span 부모 관계와 처리 경로를 확인합니다. 수집 묶음의 식별자를 Loki나 Tempo 검색창에 넣지 않으며 live 수집 성공·실제 운영 발생 시각·대상 환경 상태로 확대하지 않습니다.
3. Grafana Cloud 연결 확인¶
실시간 경로의 준비 책임¶
Alloy는 Risk API의 지표, 로그, 추적 기록을 Grafana Cloud로 보내는 수집기입니다. 하지만 접속 정보 발급, 대시보드 가져오기와 이미지 빌드는 수강생 활동이 아닙니다. 강사 또는 환경 담당자가 강의 시작 전에 준비하고 다음 정보를 안내합니다.
- 사용할 환경과 대시보드 URL
- Prometheus·Loki·Tempo 가운데 확인할 수 있어야 하는 데이터 소스
- LIVE 경로를 시작해도 되는지 여부
세 항목 가운데 하나라도 안내받지 못했다면 접속 자격을 추측하거나 환경을 직접
고치지 않습니다. 2절의 PREPARED/OFFLINE 묶음으로 진행하고, 실시간 자료를
확인하지 못한 이유와 다음 담당자를 기록합니다. 접속 정보가 제공된 경우에도
접속 자격 정보를 Git, 명령 출력, 판단 기록에 남기지 않습니다.
4-1. 관측 자료 생성과 수집¶
5교시의 목표는 원인을 해석하는 것이 아니라 6교시에서 다시 열 수 있는 자료를 만드는 것입니다. 실시간 경로는 Docker, Alloy, Grafana Cloud 준비를 강사가 확인한 팀만 사용합니다.
실행 명령의 단일 원본은 실습 코드 저장소의
labs/chapters/ch04/README.md에 있는 5교시 팀 수집 절입니다. 이 페이지와
코드 README의 명령을 모두 실행하지 말고, 코드 README의 LIVE 명령을 한 번만
실행합니다. 먼저 서비스를 시작한 뒤 course-session으로 baseline,
current-shift, invalid를 순서대로 보내고 팀 수집 매니페스트를 만듭니다.
기본 요청 간격과 수집 대기 시간은 유지합니다.
세션 ID는 실행할 때마다 자동으로 새로 생성됩니다. 명령 출력의 session_id는
이어지는 course-session-status --session-id <SESSION_ID>에 그대로 사용합니다.
정본 수집 매니페스트는 호스트의
artifacts/traffic/collection-session.json이며, 컨테이너 경로는
/runtime/artifacts/traffic/collection-session.json입니다. 시나리오별 요청
원본은 호스트의 artifacts/traffic/compose.jsonl에 남습니다. request ID는
<scenario>-<run_id>-<4자리 순번> 형식입니다.
course-session이 끝난 직후에는 dashboard_url=null일 수 있고 Prometheus·Loki·Tempo의 signal_availability가 모두 not_checked입니다. 이 값은 자동 확인 결과가 아니라 아직 사람이 확인하지 않았다는 뜻입니다. 팀원이 실제 화면과 데이터 소스에서 도착 여부를 확인한 뒤 코드 README의 상태 갱신 명령을 한 번만 실행합니다.
--session-id가 현재 매니페스트와 다르면 명령이 갱신을 거부합니다. 확인한 신호만 available 또는 unavailable로 바꿉니다. 예를 들어 Tempo를 열어 보지 않았다면 해당 인자를 빼고 not_checked를 유지합니다. URL을 확인하지 못했다면 임의 주소를 넣지 않고 dashboard_url=null로 둡니다. 대시보드에서는 값의 도착 여부만 확인하고, 패널 간 관계나 원인은 6교시까지 해석하지 않습니다.
팀 수집 매니페스트 artifacts/traffic/collection-session.json¶
수집 매니페스트는 다음 팀원이 같은 자료를 다시 열기 위한 인계 기록입니다. course-session이 만든 값을 명령 출력과 대조하되 접속 자격 자료는 추가하지 않습니다.
| 필드 | 기록할 값 |
|---|---|
| 선택 경로 | 실시간이면 이 파일의 scope=local/target, 오프라인이면 별도 수집 묶음의 PREPARED/OFFLINE, scope=static |
| 환경과 모델 | environment, model_identity의 profile·version·threshold |
| 실행별 범위 | baseline·current-shift·invalid의 run ID, UTC 시작·종료, 상태 코드 구성 |
| 분석 범위 | 대시보드 URL, 모든 실행과 수집 지연을 포함한 절대 UTC 시작·종료 |
| 수집 상태 | 사람이 확인한 Prometheus·Loki·Tempo의 available/unavailable, 확인하지 않은 신호의 not_checked |
대시보드의 기본 상대 범위는 시간이 지나면 함께 움직이므로 인계값으로 쓰지
않습니다. 앞서 수집한 baseline까지 다시 열 수 있도록 시작·종료를 절대
UTC로 저장합니다. 팀원은 live 매니페스트의 run ID와 시간 범위가 명령 출력과
맞는지만 서로 확인합니다.
인계 점검에서 수집 도착과 필수 필드를 모두 확인하지 못하면 재시작을 멈춥니다. 팀은 schema v2 수집 묶음의 handoff_contract, 절대 UTC 범위, 모델과 세 시나리오 run ID를 PREPARED/OFFLINE, scope=static 인계값으로 확정합니다. live 수집 실패 자체와 필요한 담당자는 BLOCKED로 남기되, 수집 묶음에 실제로 있는 범위가 고정된 대시보드 값까지 없는 것으로 기록하지 않습니다. 다음 교시까지 Compose와 Alloy를 내리지 않고 새 트래픽도 보내지 않습니다.
4-2. 저장 범위 분석¶
6교시 요청 단위 조사는 5교시 팀 수집 기록을 여는 데서 시작합니다. live 팀은 artifacts/traffic/collection-session.json에서 대시보드의 환경, 시나리오와 절대 UTC 시작과 종료를 복원합니다. offline 팀은 schema v2 수집 묶음의 observation_window, environment, dashboard 필드를 같은 방식으로 복원합니다. 이 교시에는 수집 환경을 다시 만들거나 live/offline 경로를 바꾸지 않습니다.
첫째 날의 100건 비교와 이 교시의 세 시나리오는 같은 증감이 아닙니다. 초기 비교는 같은 기준 모델의 정답 없는 100건이고, 여기 자료는 기준 입력 60건, 변화 입력 60건, 잘못된 입력 3건입니다. 표본과 시간이 다르므로 3건에서 6건으로 늘어난 숫자를 이 15분 자료의 직접 원인으로 쓰지 않습니다.
세 시나리오의 질문과 예상 상태가 다릅니다.
| 시나리오 | 보내는 입력 | 예상 상태 | 모델 성능 계산 |
|---|---|---|---|
baseline |
기준 입력 | 200 | 비교의 출발점 |
current-shift |
변화 입력 | 200 | 입력 변화와 점수, 예측 변화를 같이 볼 때 |
invalid |
잘못된 입력 | 422 | 제외. 입력 검증 결과이며 5xx가 아님 |
같은 범위를 유지하며 다음 질문을 한 흐름으로 조사합니다.
- 요청 수와 상태 코드 구성에서 세 시나리오가 모두 보이는가?
invalid의 422와 5xx 서비스 오류를 분리했는가?baseline과current-shift의 P95 지연과 누락 특성 신호는 어떻게 다른가?- 5-1 입력 분포의 입력 변화가 같은 범위의 누락 특성·상태 신호와 맞는가?
- 5-2 점수와 예측 분포의 점수 P95와
high_risk비율은 입력·API 신호와 어떤 관계인가?
이 다섯 질문은 별도 강의를 차례로 듣는 목록이 아닙니다. 같은 5교시 팀 수집 기록의 범위에서 입력, API 처리와 출력을 연결해 원인 후보를 강화하거나 약화하는 6교시 조사 순서입니다. 정답이 없는 운영 요청에서는 새 재현율, 정밀도, 미탐을 계산하지 않습니다.
요청 단위 조사로 이어 볼 요청 선택¶
6교시의 대표 요청 선택은 live 팀이 같은 절대 UTC 범위의 Loki에서 run ID로 요청을 좁히는 일입니다. <ENVIRONMENT>와 <RUN_ID>는 팀 수집 매니페스트의 실제 값으로 바꿉니다.
{service_name="risk-api", environment="<ENVIRONMENT>"}
| json
| run_id="<RUN_ID>"
offline 팀은 Loki를 흉내 내지 않고 수집 묶음의 representative_requests에서 normal, slow, invalid_422 가운데 관측을 대표하는 요청을 고릅니다. 상태 코드, 처리 시간 또는 조사 중인 시나리오를 대표하는 request ID를 기록하면 같은 6교시의 5-3 요청 한 건에서 원인 후보 추적하기는 이 요청에서 바로 시작합니다. 요청이 5교시 팀 수집 기록의 모델, 시나리오, 시간 범위와 맞지 않을 때만 불일치를 남기고 대체 요청을 고릅니다.
한 요청은 전체 현상의 증명이 아니라 조사 시작점입니다. 결측 처리 비용, 모델 계산, 네트워크 대기처럼 경쟁하는 설명을 관측 자료와 대조하고, 함께 움직인 신호만으로 원인을 고정하지 않습니다. 상관관계는 단서이고, 원인 확인에는 입력을 통제한 재실행이나 추가 측정이 필요합니다.
개인 조사 기록 마무리¶
5교시 팀 수집 기록을 그대로 복사하지 않고 자신이 직접 본 관측과 한계를 개인 관찰 기록에 적습니다.
- 근거: 5교시 팀 수집 기록의 유형·경로, 복원한 절대 UTC 범위, 대시보드 URL 또는 고정 자료
- 관측: 상태·5xx·지연·누락 특성·점수·예측 가운데 직접 비교한 값
- 인계: 대표 run ID와 request ID, 선택 이유
- 한계와 다음 질문: 정답 부재, 확인하지 못한 패널·환경, 5-3 요청 한 건에서 원인 후보 추적하기에서 확인할 내용
[5교시 팀 수집 기록 유형·식별값]의 [절대 UTC 범위]를 [환경/URL 또는 고정 자료]에서 복원해 [모델 정보와 시나리오]의 [관측 신호]를 확인했다. 이 신호는 [원인 후보]를 더 확인할 필요를 보여 주지만 정답 기반 품질과 확정 원인은 알 수 없다. 같은 6교시의 5-3 요청 한 건에서 원인 후보 추적하기에서 [run ID/request ID]를 이어 확인한다.
Compose 종료는 이 절에서 실행하지 않습니다. 이 교시의 요청 조사를 끝내고 제출한 뒤 최종 실습의 환경 정리로 이어갑니다.
막히면¶
scenario필터가 없거나 시계열이 합쳐지면 다른 시간대로 추측해 분리하지 않고 대시보드 계약 불일치로 기록합니다.- 로그에 오류 코드나 제한된 검증 분류가 없으면 응답 내용으로 로그를 채워 넣지 않고 로그 계약 보완을 서빙 담당자에게 요청합니다.
- 5교시 팀 수집 기록 점검에서 live 수집의 필수 필드가 빠졌다면
PREPARED/OFFLINE으로 확정하고 6교시를 재시작하지 않습니다. - schema v2 수집 묶음에 없는 대상 환경 상태나 live 수집 성공은 추정하지 않고
BLOCKED와 필요한 담당자를 적습니다.
운영 신호를 모델 평가 결론으로 바꾸지 않으려면 앞선 데이터, 모델, 서빙 기록과 함께 읽어야 합니다. 이 교시에서 고른 요청은 5-3 요청 한 건에서 원인 후보 추적하기로 이어 확인하고, 그 결과로 승인·보류 위험과 담당자, 롤백 또는 다음 확인 조건을 정리합니다.