Loki — 로그를 색인하지 않는 로그 저장소 · 질의 시점에 이름을 다시 붙인다 · 실습
오류가 하나도 없다고 보고했는데 그 시간에 서른 건이 있었다
목표
파서가 꺼낸 이름이 스트림 라벨과 부딪혀 밀려나는 것을 직접 재현하고, label_format·line_format·keep·drop 으로 결과를 원하는 모양으로 정리합니다.
왜 중요한가
Loki 에서 라벨은 두 곳에서 온다 — 수집할 때 붙여 색인된 스트림 라벨과, 질의할 때 파서가 본문에서 꺼낸 라벨이다. 이름이 겹치면 나중에 꺼낸 쪽에 _extracted 가 붙어 밀려나는데 경고도 오류도 없다. 그래서 level="error" 가 0건을 돌려주고, 사람은 그것을 '오류가 없다' 로 읽는다. 질의 시점의 이름 정리는 결과에만 작용하고 색인은 건드리지 않으므로 마음껏 써도 비용이 늘지 않는다 — 카디널리티가 걱정되는 값을 본문에 두고 질의할 때 꺼내 쓰는 설계가 성립하는 이유다.
단계
1. /root/lk-format 에서 Loki 를 띄우고 date +%s 를 /root/lk-format/anchor.txt 에 적은 뒤 python3 /opt/lab/d5/gen.py format "$(cat anchor.txt)" 로 자료를 넣으세요. 그리고 {app="payment"} 의 한 시간 줄 수와, 그 스트림에 붙어 있는 스트림 라벨 이름들을 /root/lk-format/01-boot.txt 에 두 줄로 적으세요 — lines=<정수> 와 labels=<이름들을 쉼표로, 사전순>.
2. {app="payment"} | logfmt | level="error" 를 한 시간 구간으로 던져 결과가 몇 줄인지 보고, 이름이 밀려난 라벨로 다시 물어 몇 줄인지 세세요. 답은 /root/lk-format/02-collision.txt 에 세 줄로 적습니다 — naive=<정수>, extracted_name=<밀려난 라벨 이름>, correct=<정수>.
3. label_format 을 써서 본문의 수준 값이 level 이라는 이름으로 오게 만든 뒤 level="error" 로 거르세요. 질의는 /root/lk-format/03-relabel.logql, 답은 /root/lk-format/03-relabel.txt 에 lines=<정수> 로 적습니다. 결과 줄 수는 2단계의 correct 와 같아야 합니다.
4. {app="payment"} 의 모든 줄을 <svc>/<본문의 수준>/<dur_ms> 형태로 다시 쓰는 질의를 /root/lk-format/04-line.logql 에 쓰세요. 슬래시 두 개로만 나누고 다른 글자는 넣지 않습니다. 그리고 결과 중 가장 이른 줄의 본문을 /root/lk-format/04-line.txt 에 한 줄로 적으세요.
5. 본문의 수준별로 줄 수를 세는 지표 질의를 /root/lk-format/05-bylevel.logql 에 쓰세요. 결과는 정확히 두 계열이어야 하고 각 계열의 라벨은 lvl 하나뿐이어야 합니다. 값은 /root/lk-format/05-bylevel.txt 에 info=<정수> 와 error=<정수> 두 줄로 적습니다.
6. 5단계 질의에서 keep 대신 drop 을 써서 같은 결과를 내는 질의를 /root/lk-format/06-drop.logql 에 쓰세요. 그리고 /root/lk-format/06-drop.txt 에 두 줄을 적습니다 — series=<계열 수> 와 dropped=<버린 라벨 이름들을 쉼표로, 사전순>.
7. 3단계에서 label_format 으로 라벨을 만들었고 5단계에서는 새 이름으로 계열을 묶었습니다. 그 뒤 색인의 스트림 수가 달라졌는지 확인해 /root/lk-format/07-index.txt 에 두 줄로 적으세요 — streams=<정수> 와 changed=<yes|no>. 스트림 수는 series API 로 셉니다.
8. /root/lk-format/08-panel.logql 에 질의 하나를 쓰세요. 조건은 셋입니다 — (1) 본문의 수준이 error 인 줄만 돌려줄 것, (2) 돌려주는 본문이 <dur_ms>ms <svc> <region> 형태일 것(공백 두 개로만 나누고 다른 글자는 없음), (3) 줄 필터를 본문 다시 쓰기 앞 에 둘 것. 그리고 결과의 가장 이른 줄을 /root/lk-format/08-panel.txt 에 한 줄로 적으세요.
참고
- 작업 디렉터리는
/root/lk-format입니다. Loki 는 1단계에서 직접 띄웁니다. - 자료 생성기는
/opt/lab/d5/gen.py이고format자료를 씁니다. 채점기는 이 파일을 읽지 않습니다. - 템플릿은 Go 의 text/template 입니다. 필드 앞에 점을 찍고 중괄호 두 겹으로 감쌉니다. 질의문은 역따옴표로 감싸는 쪽이 안전합니다.
- 결과의 라벨 목록은
jq '.data.result[0].stream'으로 한 번 펼쳐 보는 습관을 들이세요. 이름이 밀려난 것은 그렇게 해야 보입니다. - 흔한 실수:
line_format을 줄 필터 앞에 두는 것. 그 뒤의 필터는 새 본문을 보게 됩니다. - 흔한 실수:
since=1h로 재는 것.anchor.txt의 기준 시각으로start·end를 주세요. - [로그 질의와 서식](https://grafana.com/docs/loki/latest/query/log_queries/) · [지표 질의](https://grafana.com/docs/loki/latest/query/metric_queries/) · [라벨](https://grafana.com/docs/loki/latest/get-started/labels/) · [HTTP API](https://grafana.com/docs/loki/latest/reference/loki-http-api/)
단계 8개
- 라벨과 본문이 어긋난 자료를 넣는다
- level="error" 가 0건을 돌려준다
- label_format 으로 이름을 되돌린다
- line_format 으로 줄을 다시 쓴다
- keep 으로 계열을 묶는다
- drop 은 무엇을 버리고 무엇을 남기나
- 응용 ① — 라벨을 바꿔도 색인은 그대로다
- 응용 ② — 사람이 읽을 수 있는 오류 패널 질의