Files

501 lines
13 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
$ uv run tools/flow.py push answers/79-lab01-challenge-health.json
! unpublished '79 Ops facts (reference)' (w91aa244110abf96): it used the same webhook path
✔ pushed '79 Ops facts + health (answer)' (id wed38f213f1753a6)
POST http://localhost:5678/webhook/my-ops-facts
$ uv run tools/flow.py test cases/lab01-challenge.json -v
✔ before: POST http://localhost:8800/ops-reset · HTTP 200 · 0.1s · {"seeded_at": "2026-11-04T08:30:00", "note": "79일차 운영 아침 상태 (연습 데이터, seed 79)", "counts": {"alerts": 6, "dlq": 3, "quali
→ request POST http://localhost:8800/ops-reset
{}
← response HTTP 200
{
"seeded_at": "2026-11-04T08:30:00",
"note": "79일차 운영 아침 상태 (연습 데이터, seed 79)",
"counts": {
"alerts": 6,
"dlq": 3,
"quality_log": 4,
"quarantine": 1,
"usage": 192
}
}
POST http://localhost:5678/webhook/my-ops-facts · 5 case(s) × 1
✔ 지난주 영역별 상태 · 1.1s
→ request POST /webhook/my-ops-facts
{}
← response HTTP 200
{
"period": {
"from": "2026-10-26",
"to": "2026-10-30"
},
"runs": {
"total": 357,
"errors": 21,
"error_rate": 0.0588,
"p95_ms": 2598,
"unanswered_rate": 0.0476,
"top_failure": {
"node": "Search FAQ",
"message": "timeout of 1000ms exceeded",
"count": 16
}
},
"alerts": {
"count": 6,
"high": 3,
"by_reason": {
"timeout": 1,
"rate_limit": 1,
"batch_rejected": 1,
"low_quality": 2,
"api_error": 1
}
},
"dlq": {
"size": 3,
"parked": 2,
"waiting": 1
},
"quality": {
"batches": 4,
"avg_score": 0.6583,
"last_score": 1,
"rejected_batches": 1,
"quarantine": 1
},
"cost": {
"requests": 156,
"calls": 192,
"cost_usd": 0.073604,
"daily_usd": 0.08,
"used_ratio": 0.9201,
"top_user": {
"user": "test-bot",
"cost_usd": 0.027228,
"share": 0.3699
}
},
"release": {
"active": "1.1.0",
"canary_release": "1.2.0",
"canary_percent": 20,
"active_repeat_rate": 0.0773,
"canary_repeat_rate": 0.625
},
"health": {
"runs": "red",
"alerts": "yellow",
"dlq": "red",
"quality": "yellow",
"cost": "yellow",
"release": "red"
},
"red": [
"runs",
"dlq",
"release"
],
"yellow": [
"alerts",
"quality",
"cost"
],
"overall": "red"
}
✔ 빨강 · 노랑 목록 (정해진 순서) · 0.3s
→ request POST /webhook/my-ops-facts
{}
← response HTTP 200
{
"period": {
"from": "2026-10-26",
"to": "2026-10-30"
},
"runs": {
"total": 357,
"errors": 21,
"error_rate": 0.0588,
"p95_ms": 2598,
"unanswered_rate": 0.0476,
"top_failure": {
"node": "Search FAQ",
"message": "timeout of 1000ms exceeded",
"count": 16
}
},
"alerts": {
"count": 6,
"high": 3,
"by_reason": {
"timeout": 1,
"rate_limit": 1,
"batch_rejected": 1,
"low_quality": 2,
"api_error": 1
}
},
"dlq": {
"size": 3,
"parked": 2,
"waiting": 1
},
"quality": {
"batches": 4,
"avg_score": 0.6583,
"last_score": 1,
"rejected_batches": 1,
"quarantine": 1
},
"cost": {
"requests": 156,
"calls": 192,
"cost_usd": 0.073604,
"daily_usd": 0.08,
"used_ratio": 0.9201,
"top_user": {
"user": "test-bot",
"cost_usd": 0.027228,
"share": 0.3699
}
},
"release": {
"active": "1.1.0",
"canary_release": "1.2.0",
"canary_percent": 20,
"active_repeat_rate": 0.0773,
"canary_repeat_rate": 0.625
},
"health": {
"runs": "red",
"alerts": "yellow",
"dlq": "red",
"quality": "yellow",
"cost": "yellow",
"release": "red"
},
"red": [
"runs",
"dlq",
"release"
],
"yellow": [
"alerts",
"quality",
"cost"
],
"overall": "red"
}
✔ 첫 주: 오류는 없지만 답 못 함 · 카나리 비교 불가 · 0.1s
→ request POST /webhook/my-ops-facts
{
"from": "2026-10-19",
"to": "2026-10-23"
}
← response HTTP 200
{
"period": {
"from": "2026-10-19",
"to": "2026-10-23"
},
"runs": {
"total": 309,
"errors": 0,
"error_rate": 0,
"p95_ms": 2525,
"unanswered_rate": 0.055,
"top_failure": null
},
"alerts": {
"count": 6,
"high": 3,
"by_reason": {
"timeout": 1,
"rate_limit": 1,
"batch_rejected": 1,
"low_quality": 2,
"api_error": 1
}
},
"dlq": {
"size": 3,
"parked": 2,
"waiting": 1
},
"quality": {
"batches": 4,
"avg_score": 0.6583,
"last_score": 1,
"rejected_batches": 1,
"quarantine": 1
},
"cost": {
"requests": 156,
"calls": 192,
"cost_usd": 0.073604,
"daily_usd": 0.08,
"used_ratio": 0.9201,
"top_user": {
"user": "test-bot",
"cost_usd": 0.027228,
"share": 0.3699
}
},
"release": {
"active": "1.1.0",
"canary_release": "1.2.0",
"canary_percent": 20,
"active_repeat_rate": null,
"canary_repeat_rate": null
},
"health": {
"runs": "yellow",
"alerts": "yellow",
"dlq": "red",
"quality": "yellow",
"cost": "yellow",
"release": "yellow"
},
"red": [
"dlq"
],
"yellow": [
"runs",
"alerts",
"quality",
"cost",
"release"
],
"overall": "red"
}
✔ before: POST http://localhost:8800/budget · HTTP 200 · 0.0s · {"daily_usd": 1.0, "user_limit_per_min": 20, "max_question_chars": 500, "used_usd": 0.073604, "remaining_usd": 0.926396,
→ request POST http://localhost:8800/budget
{
"daily_usd": 1
}
← response HTTP 200
{
"daily_usd": 1.0,
"user_limit_per_min": 20,
"max_question_chars": 500,
"used_usd": 0.073604,
"remaining_usd": 0.926396,
"over": false
}
✔ 예산을 늘리면 비용은 초록 · 0.1s
→ request POST /webhook/my-ops-facts
{}
← response HTTP 200
{
"period": {
"from": "2026-10-26",
"to": "2026-10-30"
},
"runs": {
"total": 357,
"errors": 21,
"error_rate": 0.0588,
"p95_ms": 2598,
"unanswered_rate": 0.0476,
"top_failure": {
"node": "Search FAQ",
"message": "timeout of 1000ms exceeded",
"count": 16
}
},
"alerts": {
"count": 6,
"high": 3,
"by_reason": {
"timeout": 1,
"rate_limit": 1,
"batch_rejected": 1,
"low_quality": 2,
"api_error": 1
}
},
"dlq": {
"size": 3,
"parked": 2,
"waiting": 1
},
"quality": {
"batches": 4,
"avg_score": 0.6583,
"last_score": 1,
"rejected_batches": 1,
"quarantine": 1
},
"cost": {
"requests": 156,
"calls": 192,
"cost_usd": 0.073604,
"daily_usd": 1,
"used_ratio": 0.0736,
"top_user": {
"user": "test-bot",
"cost_usd": 0.027228,
"share": 0.3699
}
},
"release": {
"active": "1.1.0",
"canary_release": "1.2.0",
"canary_percent": 20,
"active_repeat_rate": 0.0773,
"canary_repeat_rate": 0.625
},
"health": {
"runs": "red",
"alerts": "yellow",
"dlq": "red",
"quality": "yellow",
"cost": "green",
"release": "red"
},
"red": [
"runs",
"dlq",
"release"
],
"yellow": [
"alerts",
"quality"
],
"overall": "red"
}
✔ before: POST http://localhost:8800/dlq/update · HTTP 200 · 0.0s · {"removed": true, "size": 2}
→ request POST http://localhost:8800/dlq/update
{
"dlq_id": 1,
"remove": true
}
← response HTTP 200
{
"removed": true,
"size": 2
}
✔ before: POST http://localhost:8800/dlq/update · HTTP 200 · 0.0s · {"removed": true, "size": 1}
→ request POST http://localhost:8800/dlq/update
{
"dlq_id": 2,
"remove": true
}
← response HTTP 200
{
"removed": true,
"size": 1
}
✔ parked를 처리하면 DLQ는 노랑 · 0.1s
→ request POST /webhook/my-ops-facts
{}
← response HTTP 200
{
"period": {
"from": "2026-10-26",
"to": "2026-10-30"
},
"runs": {
"total": 357,
"errors": 21,
"error_rate": 0.0588,
"p95_ms": 2598,
"unanswered_rate": 0.0476,
"top_failure": {
"node": "Search FAQ",
"message": "timeout of 1000ms exceeded",
"count": 16
}
},
"alerts": {
"count": 6,
"high": 3,
"by_reason": {
"timeout": 1,
"rate_limit": 1,
"batch_rejected": 1,
"low_quality": 2,
"api_error": 1
}
},
"dlq": {
"size": 1,
"parked": 0,
"waiting": 1
},
"quality": {
"batches": 4,
"avg_score": 0.6583,
"last_score": 1,
"rejected_batches": 1,
"quarantine": 1
},
"cost": {
"requests": 156,
"calls": 192,
"cost_usd": 0.073604,
"daily_usd": 1,
"used_ratio": 0.0736,
"top_user": {
"user": "test-bot",
"cost_usd": 0.027228,
"share": 0.3699
}
},
"release": {
"active": "1.1.0",
"canary_release": "1.2.0",
"canary_percent": 20,
"active_repeat_rate": 0.0773,
"canary_repeat_rate": 0.625
},
"health": {
"runs": "red",
"alerts": "yellow",
"dlq": "yellow",
"quality": "yellow",
"cost": "green",
"release": "red"
},
"red": [
"runs",
"release"
],
"yellow": [
"alerts",
"dlq",
"quality"
],
"overall": "red"
}
Passed 5/5
report: runs/lab01-challenge-20261101-185142.json
✔ after: POST http://localhost:8800/ops-reset · HTTP 200 · 0.0s · {"seeded_at": "2026-11-04T08:30:00", "note": "79일차 운영 아침 상태 (연습 데이터, seed 79)", "counts": {"alerts": 6, "dlq": 3, "quali
→ request POST http://localhost:8800/ops-reset
{}
← response HTTP 200
{
"seeded_at": "2026-11-04T08:30:00",
"note": "79일차 운영 아침 상태 (연습 데이터, seed 79)",
"counts": {
"alerts": 6,
"dlq": 3,
"quality_log": 4,
"quarantine": 1,
"usage": 192
}
}
$ uv run tools/flow.py test cases/lab01.json
✔ before: POST http://localhost:8800/ops-reset · HTTP 200 · 0.0s · {"seeded_at": "2026-11-04T08:30:00", "note": "79일차 운영 아침 상태 (연습 데이터, seed 79)", "counts": {"alerts": 6, "dlq": 3, "quali
POST http://localhost:5678/webhook/my-ops-facts · 5 case(s) × 1
✔ 지난주 실행 (기본 기간) · 0.1s
✔ 지금 상태 · 알림 · DLQ · 품질 · 0.1s
✔ 비용 · 릴리스 · 0.1s
✔ 첫 주 (기간을 바꾸면 실행만 바뀜) · 0.1s
✔ before: POST http://localhost:8800/dlq/update · HTTP 200 · 0.0s · {"removed": true, "size": 2}
✔ 상태가 바뀌면 숫자도 (DLQ #3 처리) · 0.1s
Passed 5/5
report: runs/lab01-20261101-185143.json
✔ after: POST http://localhost:8800/ops-reset · HTTP 200 · 0.0s · {"seeded_at": "2026-11-04T08:30:00", "note": "79일차 운영 아침 상태 (연습 데이터, seed 79)", "counts": {"alerts": 6, "dlq": 3, "quali