LabHub
学习 学习路径 课程

Loki — 不索引日志的日志库

一个错误都没有,5xx 的数量却只有真实值的三分之一

在 LabHub 中继续学习

한국어 원문으로 표시합니다.

목표

파드 안의 진짜 Loki 에서 네 가지 LogQL 파서를 직접 붙여 보고, 파싱 오류가 난 줄과 오류 없이 조용히 값을 못 꺼낸 줄을 각각 세어 진짜 5xx 건수를 구합니다.

왜 중요한가

Loki 는 본문을 색인하지 않는다. 그래서 본문 속 값으로 거르려면 질의할 때마다 파서로 꺼내야 하고, 파서를 잘못 고르면 숫자가 조용히 줄어든다. json 은 실패를 __error__ 라벨로 신고하지만 logfmt 는 신고하지 않는다 — 형식이 다른 줄을 만나면 아무 라벨도 만들지 않고 지나가고, 라벨이 없으면 뒤따르는 라벨 필터는 그 줄을 조용히 버린다. 대시보드에는 오류도 경고도 안 뜬다. 그래서 새 스트림을 질의하기 전에 늘 두 숫자를 먼저 재야 한다 — 파싱이 실패한 줄 수와, 실패하지도 않았는데 값이 안 나온 줄 수.

단계

  1. /root/lk-parsers 에서 Loki 를 띄우고 date +%s/root/lk-parsers/anchor.txt 에 적은 뒤 python3 /opt/lab/d5/gen.py parsers "$(cat anchor.txt)" 로 자료를 넣으세요. 그리고 기준 시각에서 과거 한 시간 동안 {app="mixed"}{app="orders"} 가 각각 몇 줄인지 세어 /root/lk-parsers/01-boot.txtmixed=<정수>orders=<정수> 두 줄로 적으세요.
  2. orders 스트림에서 status 가 500 인 줄이 몇 줄인지 logfmt 파서로 세세요. 질의는 /root/lk-parsers/02-logfmt.logql, 답은 /root/lk-parsers/02-logfmt.txtlines=<정수> 로 적습니다.
  3. mixed 스트림에 json 파서를 붙여, 파싱에 성공한 줄과 __error__ 라벨이 붙은 줄을 각각 세세요. 답은 /root/lk-parsers/03-json.txtok=<정수>err=<정수> 두 줄로 적고, __error__ 의 실제 값 하나를 /root/lk-parsers/03-json-name.txt 에 한 줄로 적으세요.
  4. mixed 스트림에 logfmt 파서를 붙였을 때 오류는 나지 않았는데 status 라벨이 만들어지지 않은 줄이 몇 줄인지 세세요. 질의는 /root/lk-parsers/04-silent.logql, 답은 /root/lk-parsers/04-silent.txtlines=<정수> 로 적습니다.
  5. 본문에 legacy 가 든 줄만 골라 pattern 파서로 상태 코드를 꺼내고, 그 값이 500 인 줄을 세세요. 질의는 /root/lk-parsers/05-pattern.logql, 답은 /root/lk-parsers/05-pattern.txtlines=<정수> 로 적습니다. 질의에는 pattern 파서가 반드시 들어가야 합니다.
  6. 같은 레거시 줄에서 regexp 파서로 걸린 시간(밀리초)을 꺼내, 1000 보다 큰 줄을 세세요. 질의는 /root/lk-parsers/06-regexp.logql, 답은 /root/lk-parsers/06-regexp.txtlines=<정수> 로 적습니다. 질의에는 regexp 파서가 반드시 들어가야 합니다.
  7. mixed 스트림의 줄을 형식 세 가지로 갈라 세어 /root/lk-parsers/tally.tsv 를 만드세요. 머리글 없이 세 줄이고 각 줄은 탭으로 나눈 두 칸 <형식><탭><줄수> 입니다. 형식 이름은 순서대로 json, legacy, logfmt 이고, 세 줄의 합은 1단계에서 센 mixed 전체 줄 수와 같아야 합니다.
  8. mixed 스트림에서 상태 코드가 500 인 줄의 진짜 총 건수를 구해 /root/lk-parsers/08-total.txttotal=<정수> 로 적고, 그 다음 줄에 reason= 으로 시작하는 한 문장(공백 뺀 40자 이상)을 적으세요. 왜 파서 하나로는 이 숫자를 셀 수 없는지 자기 말로 씁니다.

참고

형식이 섞인 스트림을 손에 쥔다

/root/lk-parsers 에서 Loki 를 띄우고 date +%s/root/lk-parsers/anchor.txt 에 적은 뒤 python3 /opt/lab/d5/gen.py parsers "$(cat anchor.txt)" 로 자료를 넣으세요. 그리고 기준 시각에서 과거 한 시간 동안 {app="mixed"}{app="orders"} 가 각각 몇 줄인지 세어 /root/lk-parsers/01-boot.txtmixed=<정수>orders=<정수> 두 줄로 적으세요.

/readyready 를 돌려줄 때까지 20초쯤 걸립니다. 구간은 anchor.txt 의 값으로 start·end 를 나노초로 주세요. 파서 없이 선택자만으로 세면 됩니다.

형식이 깔끔할 때는 logfmt 한 줄이면 된다

orders 스트림에서 status 가 500 인 줄이 몇 줄인지 logfmt 파서로 세세요. 질의는 /root/lk-parsers/02-logfmt.logql, 답은 /root/lk-parsers/02-logfmt.txtlines=<정수> 로 적습니다.

파서는 선택자 뒤에 파이프로 붙입니다. 파서가 만든 라벨은 그 뒤에서 라벨 필터로 쓸 수 있습니다. 줄 필터로 |= "status=500" 처럼 문자열을 찾는 것과는 다릅니다 — 이번에는 파서로 꺼낸 값을 쓰세요.

json 파서는 실패를 신고한다

mixed 스트림에 json 파서를 붙여, 파싱에 성공한 줄과 __error__ 라벨이 붙은 줄을 각각 세세요. 답은 /root/lk-parsers/03-json.txtok=<정수>err=<정수> 두 줄로 적고, __error__ 의 실제 값 하나를 /root/lk-parsers/03-json-name.txt 에 한 줄로 적으세요.

파서가 실패하면 __error__ 라벨이 붙습니다. 그 라벨이 비어 있는 줄과 비어 있지 않은 줄을 각각 고르면 됩니다. 라벨 값이 무엇인지는 결과의 stream 을 그대로 들여다보면 보입니다 — __error_details__ 도 함께 붙습니다.

오류도 없이 아무것도 안 꺼낸 줄을 센다

mixed 스트림에 logfmt 파서를 붙였을 때 오류는 나지 않았는데 status 라벨이 만들어지지 않은 줄이 몇 줄인지 세세요. 질의는 /root/lk-parsers/04-silent.logql, 답은 /root/lk-parsers/04-silent.txtlines=<정수> 로 적습니다.

LogQL 에서 '없는 라벨' 은 빈 문자열과 같게 비교됩니다. 그 성질을 쓰면 '파서가 값을 못 만든 줄' 을 고를 수 있습니다. 이 숫자가 이 실습에서 가장 무서운 숫자입니다 — 대시보드 어디에도 안 뜨는데 합계를 깎아 먹습니다.

자리가 고정된 줄에는 pattern 이 맞다

본문에 legacy 가 든 줄만 골라 pattern 파서로 상태 코드를 꺼내고, 그 값이 500 인 줄을 세세요. 질의는 /root/lk-parsers/05-pattern.logql, 답은 /root/lk-parsers/05-pattern.txtlines=<정수> 로 적습니다. 질의에는 pattern 파서가 반드시 들어가야 합니다.

레거시 줄은 legacy handler finished code 500 in 123ms 모양입니다. pattern 은 꺼낼 자리에 꺾쇠로 이름을 적고 나머지는 글자 그대로 씁니다. 파서 앞에 줄 필터를 두어 레거시 줄만 넘기는 것이 중요합니다 — 다른 형식 줄에는 이 모양이 없습니다.

정규식 파서로 숫자를 꺼내 비교한다

같은 레거시 줄에서 regexp 파서로 걸린 시간(밀리초)을 꺼내, 1000 보다 큰 줄을 세세요. 질의는 /root/lk-parsers/06-regexp.logql, 답은 /root/lk-parsers/06-regexp.txtlines=<정수> 로 적습니다. 질의에는 regexp 파서가 반드시 들어가야 합니다.

regexp이름 있는 잡기 그룹만 라벨로 만듭니다 — 이름 없는 괄호는 버려집니다. 꺼낸 값은 문자열이지만 부등호로 비교하면 LogQL 이 숫자로 바꿔 줍니다. 같은 답을 pattern 으로도 낼 수 있습니다 — 어느 쪽이 읽기 쉬운지 견주어 보세요.

응용 ① — 형식별로 몇 줄인지 표로 만든다

mixed 스트림의 줄을 형식 세 가지로 갈라 세어 /root/lk-parsers/tally.tsv 를 만드세요. 머리글 없이 세 줄이고 각 줄은 탭으로 나눈 두 칸 <형식><탭><줄수> 입니다. 형식 이름은 순서대로 json, legacy, logfmt 이고, 세 줄의 합은 1단계에서 센 mixed 전체 줄 수와 같아야 합니다.

JSON 줄은 json 파서가 오류를 내지 않는 줄입니다. 레거시 줄은 본문에 legacy 가 있습니다. 남은 것이 logfmt 줄인데, 이 줄들은 logfmtstatus 가 만들어집니다. 세 숫자의 합이 전체와 맞는지 꼭 확인하세요 — 안 맞으면 어딘가를 두 번 셌거나 빠뜨린 것입니다.

응용 ② — 진짜 5xx 건수와 그 사실을 남긴다

mixed 스트림에서 상태 코드가 500 인 줄의 진짜 총 건수를 구해 /root/lk-parsers/08-total.txttotal=<정수> 로 적고, 그 다음 줄에 reason= 으로 시작하는 한 문장(공백 뺀 40자 이상)을 적으세요. 왜 파서 하나로는 이 숫자를 셀 수 없는지 자기 말로 씁니다.

한 질의에 파서를 두 개 이어 붙여도 두 형식을 함께 읽지는 못합니다. 형식마다 따로 세고 더하세요. 4단계에서 센 '조용히 빠진 줄' 이 어디로 갔는지 생각하면 몇 갈래로 나눠야 하는지 보입니다. 답을 적을 때는 세 갈래의 숫자가 각각 얼마였는지도 확인해 두세요.