110 lines
7.0 KiB
Markdown
110 lines
7.0 KiB
Markdown
# Lab 01 · 운영 사실 · 흩어진 출처를 한 장으로
|
||
|
||
> **강사용 정답본** · 학생 저장소에는 수업이 끝난 뒤 올립니다. 학생용 문제는 [LAB-01-Q-OPS-FACTS.md](LAB-01-Q-OPS-FACTS.md).
|
||
> 요청문은 예시이며 CLI 에이전트로 보내 재지는 않았습니다. 결과 숫자는 실습을 5개로 늘린 뒤 정답 워크플로우를 학생 순서대로 2026-11-01에 1회씩 실행한 값입니다 (강사 Mac). 운영 아침 상태 · 실행 기록이 같으므로 누가 돌려도 같습니다. 명령 · 출력 전부: [answers/LAB-TEST-RESULT.md](answers/LAB-TEST-RESULT.md).
|
||
|
||
## 예제 1 · 결과 (에이전트 없이, `answers/01`)
|
||
|
||
| 출처 | `morning` | 기준 대시보드 | 빠진 것 · 틀린 것 |
|
||
| --- | --- | --- | --- |
|
||
| 실행 기록 | (지난주 357) | **666** · 3.153… | 기간을 넘기지 않음, 백분율 · 반올림 없음 |
|
||
| 알림 | 6 · 높음 3 | 6 | 높음 · 이유 |
|
||
| DLQ | 3 · parked 2 | 3 | **parked** |
|
||
| 품질 | 4줄 · 격리 1 | 없음 | 출처를 안 읽음 |
|
||
| 비용 | $0.073604 / $0.08 | 금액 둘 | 비율 · 1위 |
|
||
| 릴리스 | 1.1.0 + 카나리 1.2.0 20% | 없음 | **카나리** |
|
||
|
||
- 풀이 때: "틀린 숫자보다 없는 칸이 위험하다" — 기준만 보면 카나리 · parked(오늘 가장 급한 둘)를 모름.
|
||
|
||
## 예제 2 · 요청문 예
|
||
|
||
```text
|
||
my-work/ops-facts.json 을 새로 만들어 줘. 웹훅 POST my-ops-facts, 이름 "79 Ops facts (my)".
|
||
Get logs(POST http://data-api:8800/logs/query) 에 본문의 from · to 를 넘기고, 비면 2026-10-26 · 2026-10-30 (지난주).
|
||
그 뒤 Get alerts · Get DLQ · Get quality · Get quarantine · Get usage · Get budget · Get release 를 한 줄로 잇고, Make facts(Code) 하나에서 AGENTS.md 3절 "사실" 표대로 모은다.
|
||
runs 는 77일차 정의 그대로 (error_rate 4자리 · p95 는 ceil(p × n)번째 · 0건이면 0), top_failure 는 (노드, 메시지) 묶음 1위 또는 null.
|
||
기간은 실행 기록에만 쓰고, 알림 · DLQ · 품질 · 비용 · 릴리스는 지금 상태. 숫자는 Code 가 세고 LLM 은 쓰지 않는다.
|
||
데이터 API 에 바꾸는 요청은 보내지 않는다 (읽기만). 기대 결과 cases/lab01.json.
|
||
```
|
||
|
||
**빈칸 답** (Q 문서 ▶ 빈칸 채우기 `____①`~`____④`)
|
||
|
||
| 빈칸 | 답 | 왜 |
|
||
| --- | --- | --- |
|
||
| ① | `my-ops-facts` | AGENTS.md 3절 계약 · 테스트 파일의 `webhook` |
|
||
| ② | `2026-10-26 · 2026-10-30` | 운영 회의는 지난주를 봄 — 기준 대시보드는 기간 없이 666을 셈 |
|
||
| ③ | 실행 기록에만 | 알림 · DLQ · 비용은 '지금' 상태 — 기간을 대면 오히려 틀림 (예제 3) |
|
||
| ④ | 바꾸는 요청 | 운영 도우미는 읽기만. `/logs/query`는 읽기 |
|
||
|
||
정답: [reference/lab01-example2-facts.json](reference/lab01-example2-facts.json)
|
||
|
||
| 11/01 결과 | |
|
||
| --- | --- |
|
||
| 고치기 전 (`answers/02`, 기준에 같은 테스트) | **0/5** · 666 · 3.153…, 높음 · parked · 품질 · 릴리스 칸 없음 |
|
||
| 고친 뒤 (`answers/03`) | **5/5** · 357 · 0.0588 · 2598 · 실패 1위 16, 알림 6 · 3, DLQ 3 · 2 · 1, 품질 0.6583, 비용 0.9201 · `test-bot` 0.3699, 카나리 62.5% 대 7.73%, 0.1초 |
|
||
|
||
## 예제 3 · 결과 (에이전트 없이, `answers/04`)
|
||
|
||
| 기간 | 실행 | 다시 묻는 비율 | 지금 숫자 |
|
||
| --- | --- | --- | --- |
|
||
| 두 주 | 666 · 21 · 0.0315 | 7.73% · 62.5% | 그대로 |
|
||
| 10/26 | 70 · 16 · 0.2286 | `null` · `null` (그날 두 판이 없음 — 10/28부터) | 그대로 |
|
||
| 빈 주 | 0 · 0 · p95 0 · 실패 1위 `null` | `null` · `null` | 그대로 |
|
||
| 기간 없음 | 357 (지난주) | 7.73% · 62.5% | 그대로 |
|
||
|
||
- **5/5.** 풀이 때: 0("없었다")과 `null`("모른다")의 차이 → 과제 1의 "카나리 비교 불가 = 노랑".
|
||
|
||
## 과제 1 · 요청문 예
|
||
|
||
```text
|
||
my-work/ops-facts.json 의 Make facts 에 영역별 상태를 더해 줘.
|
||
AGENTS.md 3절 "상태" 표대로 health {runs, alerts, dlq, quality, cost, release} 를 red · yellow · green 으로. red 를 yellow 보다 먼저 본다.
|
||
release 는 카나리가 있고 두 비율이 모두 있고 canary_repeat_rate 가 active 의 2배를 넘으면 red, 카나리만 있으면 yellow.
|
||
red · yellow 는 그 색인 영역을 runs, alerts, dlq, quality, cost, release 순서로, overall 은 red 가 있으면 red, 아니면 yellow 가 있으면 yellow, 아니면 green.
|
||
상태 판정은 LLM 이 아니라 Code. 앞의 사실은 그대로. 기대 결과 cases/lab01-challenge.json, cases/lab01.json 도.
|
||
```
|
||
|
||
**빈칸 답**
|
||
|
||
| 빈칸 | 답 | 왜 |
|
||
| --- | --- | --- |
|
||
| ① | 먼저 | 빨강 조건과 노랑 조건이 둘 다 맞으면 빨강 |
|
||
| ② | 2배 | 다시 묻는 비율 62.5%가 1.1.0(7.73%)의 두 배를 넘음 → 카나리 문제 |
|
||
| ③ | `runs, alerts, dlq, quality, cost, release` | 목록이 늘 같은 순서여야 테스트 · 브리핑이 같음 |
|
||
| ④ | Code | 정해진 규칙 — LLM에게 판정시키면 날마다 다름 |
|
||
|
||
정답: [answers/79-lab01-challenge-health.json](answers/79-lab01-challenge-health.json)
|
||
|
||
| 11/01 결과 | |
|
||
| --- | --- |
|
||
| 고치기 전 (`answers/05`) | **0/5** · 칸 없음 |
|
||
| 고친 뒤 (`answers/06`) | **5/5** · 🔴 runs · dlq · release, 🟡 alerts · quality · cost, 첫 주 빨강은 dlq 하나, 예산 $1이면 비용 🟢, parked 처리하면 DLQ 🟡. `lab01` 5/5 |
|
||
|
||
## 과제 2 · 요청문 예
|
||
|
||
```text
|
||
my-work/ops-facts.json 이 출처 하나가 멈춰도 답하게 해 줘.
|
||
Get logs 를 뺀 HTTP 노드에 neverError 를 켜고, Make facts 에서 출처의 응답 모양을 본다 (alerts 목록 · DLQ items · quality items 와 quarantine size · usage cost_usd 와 budget daily_usd 가 숫자 · release active).
|
||
답하지 않은 영역은 사실을 null, sources_down 에 영역 이름, health 는 unknown, unknown 목록에.
|
||
overall 은 red 가 있으면 red, 아니면 yellow 나 unknown 이 있으면 yellow, 아니면 green — 모르는 것을 초록으로 말하지 않는다.
|
||
응답은 언제나 HTTP 200. 앞의 칸은 그대로. 기대 결과 cases/lab01-challenge2.json, lab01 · lab01-challenge · lab01-period 도.
|
||
```
|
||
|
||
**빈칸 답**
|
||
|
||
| 빈칸 | 답 | 왜 |
|
||
| --- | --- | --- |
|
||
| ① | `neverError` | 켜지 않으면 출처 하나의 500이 워크플로우 전체를 멈춤 |
|
||
| ② | `null` | 0이 아니라 '모름' — 0이면 '비용이 0'으로 읽힘 |
|
||
| ③ | `unknown` | 모르는 영역이 있으면 적어도 노랑 |
|
||
| ④ | `200` | 다른 다섯 영역의 사실은 쓸 수 있으므로 |
|
||
|
||
정답: [answers/79-lab01-challenge2-sources.json](answers/79-lab01-challenge2-sources.json)
|
||
|
||
| 11/01 결과 | |
|
||
| --- | --- |
|
||
| 고치기 전 (`answers/07`) | **0/3** · 사용량 출처가 멈추면 **500** (사실 전체가 없음) |
|
||
| 고친 뒤 (`answers/08`) | **3/3** · 200, `cost: null` · `sources_down: ["cost"]` · `health.cost: "unknown"`, 빨강 셋 그대로, 출처가 돌아오면 🟡 0.9201. `lab01` · `lab01-challenge` · `lab01-period` 5/5 |
|
||
|
||
- 풀이 때: 비용을 0으로 적었다면 🟢(실제는 92%) — "모르는 것을 좋게 말하는 대시보드가 가장 위험하다".
|