GrepBoard/매뉴얼
47 편 ·

HAProxy 로그 한 줄 읽기 — 상태 코드와 종료 상태

·Ubuntu 24.04 · HAProxy 2.8.16 · 설명은 HAProxy 2.8 configuration manual 기준·7 단계

option httplog 로그 한 줄의 칸을 나눠 읽고, 종료 상태 4글자의 앞 두 글자 뜻을 표로 확인한 뒤 awk 로 상태별 건수와 느린 요청을 셉니다.

option httplog 가 켜진 프런트엔드는 요청 하나당 한 줄을 남깁니다. 아래 출력은 HAProxy 2.8.16 에 curl 로 요청을 보내 얻은 실제 로그이고, 칸 설명은 configuration manual 8.2.3 · 8.5절에서 옮겼습니다.

[1] 정상 요청 한 줄을 칸으로 나눕니다. 이 줄은 syslog 머리말 없이 log stdout format raw local0 로 받은 것입니다.

output
203.0.113.7:37660 [19/Oct/2026:12:17:20.987] web ok/s1 0/0/0/5/5 200 185 - - ---- 1/1/0/0/0 0/0 "GET /index.html HTTP/1.1"
  • 1 203.0.113.7:37660 — 클라이언트 주소:포트
  • 2 […] — 요청 첫 바이트를 받은 시각
  • 3 web — 프런트엔드 이름
  • 4 ok/s1 — 백엔드/서버. 서버까지 가지 못했으면 <NOSRV>
  • 5 0/0/0/5/5 — 타이머 TR/Tw/Tc/Tr/Ta(밀리초)
  • 6 200 — 클라이언트가 받은 상태 코드
  • 7 185 — 클라이언트로 보낸 바이트(헤더 포함)
  • 8·9 - - — 캡처한 쿠키
  • 10 ---- — 종료 상태
  • 11 1/1/0/0/0 — actconn/feconn/beconn/srv_conn/retries
  • 12 0/0 — 서버 대기열/백엔드 대기열
  • 13 "GET …" — 요청 줄

[2] 타이머를 읽습니다. TR 은 요청 전체를 받기까지, Tw 는 대기열, Tc 는 서버 연결, Tr 은 서버가 응답 헤더를 보내기까지이고, Ta 는 요청이 HAProxy 에 머문 전체 시간입니다. 해당 단계에 이르지 못하면 -1 입니다. 서버 지연은 Tr 에서 봅니다.

[3] 종료 상태 4글자 중 앞 두 글자가 원인과 위치입니다. 정상은 ---- 입니다.

output
## 첫 글자 — 누가 끝냈나- `-` 정상 종료- `C` 클라이언트가 중간에 끊음 · `c` 클라이언트 쪽 timeout- `S` 서버가 끊었거나 연결을 거부함 · `s` 서버 쪽 timeout- `P` 프록시가 차단(제한 · deny 규칙 · 보안 검사)- `L` HAProxy 가 직접 처리(redirect · return · stats 등)- `R` 프록시 자원 고갈 · `I` 내부 오류 ## 둘째 글자 — 어느 단계였나- `R` 요청을 기다리는 중 · `Q` 대기열- `C` 서버 연결 중 · `H` 서버 응답 헤더를 기다리는 중- `D` 데이터 전송 중 · `L` 마지막 데이터 전송 중- `T` tarpit · `-` 전송까지 정상 종료

[4] 서버를 못 쓰는 경우를 봅니다. 없는 포트로 보낸 요청은 연결 거부라 SC-- 와 503, 응답이 timeout server(2초)를 넘긴 요청은 sH-- 와 504 입니다. 두 줄 모두 Tr 이 -1 입니다.

output
203.0.113.7:37674 [19/Oct/2026:12:17:21.013] web dead/s1 0/0/-1/-1/3007 503 217 - - SC-- 1/1/0/0/3 0/0 "GET /dead HTTP/1.1"203.0.113.7:37538 [19/Oct/2026:12:17:24.033] web slow/s1 0/0/0/-1/2003 504 198 - - sH-- 1/1/0/0/0 0/0 "GET /slow HTTP/1.1"

[5] 서버에 가지 않은 요청을 봅니다. <NOSRV> 가 보이면 서버가 응답한 것이 아닙니다. http-request return 은 LR--, http-request deny 는 PR--, 요청을 다 보내지 않고 가만히 있던 연결은 cR-- 입니다.

output
203.0.113.7:37554 [19/Oct/2026:12:18:00.736] web web/<NOSRV> 0/-1/-1/-1/0 403 84 - - LR-- 1/1/0/0/0 0/0 "GET /deny HTTP/1.1"203.0.113.7:38422 [19/Oct/2026:12:18:00.747] web web/<NOSRV> 0/-1/-1/-1/0 403 192 - - PR-- 1/1/0/0/0 0/0 "GET /block HTTP/1.1"203.0.113.7:45032 [19/Oct/2026:12:18:16.812] web web/<NOSRV> -1/-1/-1/-1/2003 408 0 - - cR-- 2/2/0/0/0 0/0 "<BADREQ>"

[6] 종료 상태별 건수를 셉니다. 머리말이 없는 로그라 종료 상태는 10번째 칸입니다. 정상(----)이 아닌 줄만 보려면 $10 != "----" 조건을 씁니다.

console
$ awk '{c[$10]++} END{for(k in c) print c[k], k}' access.log | sort -rn13 ----2 sH--2 SC--1 PR--1 LR--

[7] Ta 가 큰 요청을 찾습니다. Ta 는 5번째 칸 / 로 나눈 다섯 번째 값입니다.

console
$ awk '{split($5,t,"/"); print t[5], $6, $10, $4}' access.log | sort -rn | head -33007 503 SC-- dead/s13006 503 SC-- dead/s12003 504 sH-- slow/s1

Ta 가 크면서 SC-- 나 sH-- 면 앱이 아니라 백엔드 서버 쪽을 먼저 확인합니다.

HAProxy 로그를 브라우저에서 바로 분석 ↗ — 아무것도 올라가지 않습니다.

#haproxy#logs