TT Lab
블로그 시작하기
배우기 러닝패스 코스

장애 지휘와 포스트모템

영향받은 사람은 몇 명이었나 — 규칙으로 세는 영향

TT Lab 에서 이어서 보기

목표

결제 장애의 접근 로그에서 사용자가 아닌 요청을 걸러 내고, 재시도를 묶고, 사람을 규칙대로 세서 요청·실패·오류율·영향받은 사용자를 구합니다. 그 규칙을 스크립트로 만들어 처음 보는 로그에도 맞게 하고, 마지막에는 서로 다른 숫자를 내는 세 팀의 스크립트를 고칩니다.

왜 중요한가

영향 숫자는 상황 공지·보상·규제 보고·SLO 가 그대로 가져다 쓰는 값입니다. 그런데 같은 로그에서도 무엇을 빼고 무엇을 묶느냐에 따라 숫자가 몇 배씩 달라집니다. 헬스체크를 넣으면 장애가 실제보다 커 보이고, 요청 수를 사람 수로 쓰면 영향이 부풀고, 구간의 시간대를 버리면 엉뚱한 시간을 셉니다. 「누가 맞나」 를 다투기 전에 규칙을 맞추고, 규칙을 코드로 남기는 것이 이 실습의 핵심입니다.

단계

  1. python3 /opt/fixtures/ic/ickit.py open impact 로 재료를 펼치고 /root/ic/impact/README.txt 의 세는 규칙을 읽으세요. access.log 에서 헬스체크(경로가 정확히 /healthz 또는 /readyz) 줄 수를 /root/ic/impact/answers/health.txt 에 숫자 하나로 적습니다.
  2. 로그 전체에서 헬스체크·봇(User-Agent 에 bot·crawler·spider, 대소문자 무시)·사내 대역(클라이언트 IP 가 10. 으로 시작)을 뺀 줄 수를 /root/ic/impact/answers/external.txt 에 숫자 하나로 적습니다.
  3. 사고 구간(window.txt, KST)에 첫 시도가 든 바깥 요청의 수와, 그중 마지막 시도의 상태가 500 이상인 요청의 수를 /root/ic/impact/answers/requests.txt 에 requests=<n>, failed=<n> 두 줄로 적습니다(같은 req 의 줄은 한 요청).
  4. 같은 규칙으로 사고 구간의 오류율과, 로그 처음부터 구간 시작 전까지의 평소 오류율을 퍼센트(소수 둘째 자리)로 계산해 /root/ic/impact/answers/rate.txt 에 error_rate=<percent>, baseline_rate=<percent> 두 줄로 적습니다.
  5. 구간에 실패한 요청이 하나라도 있는 사람의 수와 구간에 요청을 보낸 사람의 수를 /root/ic/impact/answers/users.txt 에 affected_users=<n>, active_users=<n> 두 줄로 적습니다. 사람은 user= 로, 로그인하지 않은 요청(user=-)은 session= 하나를 한 명으로 셉니다.
  6. /root/ic/impact/impact.sh <log> <start-iso> <end-iso> 가 README 규칙대로 requests=<n>, failed=<n>, affected_users=<n> 세 줄을 내게 만드세요(실행 권한 필요, 언어는 자유 — 첫 줄 셔뱅으로 정합니다). 구간 인자는 2026-11-04T14:10:00+09:00 꼴입니다. 채점기가 이 실습의 로그와, 그 자리에서 새로 만든 다른 로그·구간에도 돌려 봅니다.
  7. incident ic-impact-dispute 를 실행하면 사건이 납니다. 같은 로그(/srv/impact/access.log)·같은 구간(/srv/impact/window.txt)인데 /srv/impact/bin/statuspage·support·sre 세 스크립트의 affected_users 가 서로 다릅니다. 세 스크립트를 README 규칙대로 고쳐 셋 다 같은 참값을 내게 하세요 (부르는 법은 그대로, 숫자를 적어 넣으면 다른 로그에서 떨어집니다). /root/incident/ic-impact-dispute/report.txt 에 statuspage: <code>, support: <code>, sre: <code> 세 줄과 evidence: <defective-line> 을 적습니다. 코드는 스크립트마다 다음 중 하나입니다: includes-probes(헬스체크·봇·사내 대역을 빼지 않음), requests-as-users(실패 요청 수를 사람 수로), retries-double-counted(재시도 중 한 번이라도 실패면 실패로), sampling-gap(로그 표본이 빠짐), sessions-as-users(로그인한 사람도 세션마다 따로), window-timezone(구간 시각의 시간대를 버림).

참고

재료 펼치기 — 헬스체크는 몇 줄인가

python3 /opt/fixtures/ic/ickit.py open impact 로 재료를 펼치고 /root/ic/impact/README.txt 의 세는 규칙을 읽으세요. access.log 에서 헬스체크(경로가 정확히 /healthz 또는 /readyz) 줄 수를 /root/ic/impact/answers/health.txt 에 숫자 하나로 적습니다.

요청 줄은 따옴표 안에 메서드·경로·프로토콜이 있습니다. 공백으로 나누면 경로가 넷째 칸입니다.

바깥 사용자의 줄만 남기기

로그 전체에서 헬스체크·봇(User-Agent 에 bot·crawler·spider, 대소문자 무시)·사내 대역(클라이언트 IP 가 10. 으로 시작)을 뺀 줄 수를 /root/ic/impact/answers/external.txt 에 숫자 하나로 적습니다.

User-Agent 는 따옴표로 묶인 둘째 칸입니다 — 따옴표를 구분자로 쓰면(awk -F'"') 넷째 칸이 됩니다. 줄 전체에서 bot 을 찾으면 다른 칸에 걸릴 수 있습니다.

구간의 요청과 실패 — 재시도는 하나로

사고 구간(window.txt, KST)에 첫 시도가 든 바깥 요청의 수와, 그중 마지막 시도의 상태가 500 이상인 요청의 수를 /root/ic/impact/answers/requests.txt 에 requests=<n>, failed=<n> 두 줄로 적습니다(같은 req 의 줄은 한 요청).

로그는 UTC, 구간은 KST 입니다. 요청마다 첫 시도의 시각과 마지막 시도의 상태를 따로 들고 있어야 합니다 — python 의 dict 두 개가 편합니다.

오류율과 평소 오류율

같은 규칙으로 사고 구간의 오류율과, 로그 처음부터 구간 시작 전까지의 평소 오류율을 퍼센트(소수 둘째 자리)로 계산해 /root/ic/impact/answers/rate.txt 에 error_rate=<percent>, baseline_rate=<percent> 두 줄로 적습니다.

오류율 = 실패 요청 ÷ 요청 × 100. 분모와 분자가 같은 규칙(바깥 요청, 재시도는 한 요청)이어야 합니다. 비율(0.09)이 아니라 퍼센트(9.33)입니다.

영향받은 사람 세기

구간에 실패한 요청이 하나라도 있는 사람의 수와 구간에 요청을 보낸 사람의 수를 /root/ic/impact/answers/users.txt 에 affected_users=<n>, active_users=<n> 두 줄로 적습니다. 사람은 user= 로, 로그인하지 않은 요청(user=-)은 session= 하나를 한 명으로 셉니다.

실패 요청 수와 사람 수는 다릅니다. 로그인한 사람의 세션이 여럿이어도 한 명입니다.

규칙을 스크립트로

/root/ic/impact/impact.sh <log> <start-iso> <end-iso> 가 README 규칙대로 requests=<n>, failed=<n>, affected_users=<n> 세 줄을 내게 만드세요(실행 권한 필요, 언어는 자유 — 첫 줄 셔뱅으로 정합니다). 구간 인자는 2026-11-04T14:10:00+09:00 꼴입니다. 채점기가 이 실습의 로그와, 그 자리에서 새로 만든 다른 로그·구간에도 돌려 봅니다.

앞 세 단계의 계산을 인자를 받는 한 파일로 모으면 됩니다. 구간 인자의 시간대 표시를 버리지 마세요.

사건 — 세 팀의 영향 숫자가 서로 다르다

incident ic-impact-dispute 를 실행하면 사건이 납니다. 같은 로그(/srv/impact/access.log)·같은 구간(/srv/impact/window.txt)인데 /srv/impact/bin/statuspage·support·sre 세 스크립트의 affected_users 가 서로 다릅니다. 세 스크립트를 README 규칙대로 고쳐 셋 다 같은 참값을 내게 하세요 (부르는 법은 그대로, 숫자를 적어 넣으면 다른 로그에서 떨어집니다). /root/incident/ic-impact-dispute/report.txt 에 statuspage: <code>, support: <code>, sre: <code> 세 줄과 evidence: <defective-line> 을 적습니다. 코드는 스크립트마다 다음 중 하나입니다: includes-probes(헬스체크·봇·사내 대역을 빼지 않음), requests-as-users(실패 요청 수를 사람 수로), retries-double-counted(재시도 중 한 번이라도 실패면 실패로), sampling-gap(로그 표본이 빠짐), sessions-as-users(로그인한 사람도 세션마다 따로), window-timezone(구간 시각의 시간대를 버림).

방향: 세 스크립트는 같은 틀에서 갈라졌습니다. README 의 다섯 규칙과 한 줄씩 맞대면 어긋난 자리가 스크립트마다 하나씩 나옵니다. 도구: diff(두 스크립트를 나란히), python3 -X 없이도 print 로 중간값 보기, 앞 단계의 impact.sh. 구체: 걸러 내는 조건(경로·User-Agent·IP), 마지막 시도를 고르는 줄, 사람을 모으는 자료형(집합인가 목록인가, 무엇을 넣는가), 구간 인자를 읽는 줄을 차례로 보세요. 고친 뒤 셋을 같은 인자로 돌려 숫자가 하나로 모이는지 확인합니다.