LabHub
学习 学习路径 课程

Loki — 不索引日志的日志库

同样结果的两条查询,一条四分钟,一条两秒

在 LabHub 中继续学习

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

목표

Loki 응답에 실려 오는 stats.summary 를 읽어 질의가 실제로 몇 줄·몇 바이트를 읽었는지 재고, 무엇이 그 숫자를 줄이고 무엇이 줄이지 않는지 직접 확인합니다.

왜 중요한가

Loki 의 색인에는 라벨 조합과 청크의 시간 범위만 들어 있다. 본문은 색인되지 않는다. 그래서 질의는 늘 같은 순서로 돈다 — 선택자가 열 청크를 고르고, 시간 구간이 그중 겹치는 것만 남기고, 남은 것을 전부 읽어 필터를 적용한다. 앞의 두 단계만 읽는 양을 정하고 뒤는 이미 읽은 것을 버리는 일이다. 이 순서를 모르면 줄 필터를 앞에 두거나 limit 을 줄이면서 질의가 빨라지기를 기다리게 된다. 비용이 바이트로 매겨지는 저장소에서는 이 차이가 곧 청구서다.

단계

  1. /root/lk-filters 에서 Loki 를 띄우고 date +%s/root/lk-filters/anchor.txt 에 적은 뒤 python3 /opt/lab/d5/gen.py filters "$(cat anchor.txt)" 로 자료를 넣으세요. 그리고 {app=~"edge|cart|ship|batch"} 를 기준 시각에서 과거 한 시간 구간으로 질의해 응답의 stats.summary 에서 읽은 줄 수와 바이트를 /root/lk-filters/01-base.txtprocessed=<정수>bytes=<정수> 두 줄로 적으세요.
  2. 같은 한 시간 구간에서 네 스트림 전체를 대상으로 본문에 SETTLE-LATE 가 든 줄을 찾는 질의를 /root/lk-filters/02-marker.logql 에 쓰고, 결과 줄 수와 읽은 줄 수를 /root/lk-filters/02-marker.txtlines=<정수>processed=<정수> 두 줄로 적으세요.
  3. 같은 답(같은 줄)을 내면서 스트림 선택자만 좁힌 질의를 /root/lk-filters/03-stream.logql 에 쓰고, 결과 줄 수와 읽은 줄 수를 /root/lk-filters/03-stream.txtlines=<정수>·processed=<정수> 로 적으세요. 그리고 /root/lk-filters/03-ratio.txtratio=<소수 둘째 자리> 한 줄로 2단계 대비 읽은 줄 수의 비율을 적습니다.
  4. 3단계와 같은 질의를 구간만 30분(기준 시각에서 과거 1800초)으로 바꿔 던지세요. 결과 줄 수와 읽은 줄 수를 /root/lk-filters/04-window.txtlines=<정수>·processed=<정수> 로 적고, /root/lk-filters/04-note.txttradeoff= 로 시작하는 한 문장(공백 뺀 40자 이상)을 적어 구간을 좁힐 때 무엇을 얻고 무엇을 잃는지 자기 말로 쓰세요.
  5. 네 스트림 전체·한 시간 구간에서 두 질의를 던져 읽은 줄 수를 견주세요. 하나는 필터가 전혀 없는 {app=~"edge|cart|ship|batch"}, 다른 하나는 거기에 줄 필터 두 개를 더한 질의입니다. 결과를 /root/lk-filters/05-linefilter.txt 에 네 줄로 적습니다 — plain_processed=, plain_lines=, filtered_processed=, filtered_lines=.
  6. 네 스트림 전체·한 시간 구간에 | logfmt | status="500" 을 붙인 질의를 던져 세 숫자를 /root/lk-filters/06-parser.txt 에 적으세요 — processed=<읽은 줄 수>, post_filter=<필터를 통과해 남은 줄 수>, lines=<결과 줄 수>. 세 숫자를 1단계 기준선과 견주어, 무엇이 같고 무엇이 달라졌는지 보세요.
  7. 지금까지 잰 것을 /root/lk-filters/cost.tsv 로 정리하세요. 머리글 없이 네 줄이고 각 줄은 탭으로 나눈 세 칸 <방법><탭><읽은줄수><탭><결과줄수> 입니다. 방법 이름은 순서대로 all(2단계), stream(3단계), window(4단계), parser(6단계)입니다.
  8. /root/lk-filters/08-budget.logql 에 질의를 하나 쓰세요. 조건은 셋입니다 — (1) 기준 시각에서 과거 한 시간 구간으로 던졌을 때 2단계와 똑같은 줄을 돌려줄 것, (2) 읽은 줄 수가 1단계 기준선의 3분의 1 이하일 것, (3) limit 에 기대지 말 것. 그리고 /root/lk-filters/08-budget.txtprocessed=<정수> 한 줄로 그 질의가 읽은 줄 수를 적으세요.

참고

네 스트림을 넣고 기준선을 잰다

/root/lk-filters 에서 Loki 를 띄우고 date +%s/root/lk-filters/anchor.txt 에 적은 뒤 python3 /opt/lab/d5/gen.py filters "$(cat anchor.txt)" 로 자료를 넣으세요. 그리고 {app=~"edge|cart|ship|batch"} 를 기준 시각에서 과거 한 시간 구간으로 질의해 응답의 stats.summary 에서 읽은 줄 수와 바이트를 /root/lk-filters/01-base.txtprocessed=<정수>bytes=<정수> 두 줄로 적으세요.

통계는 query_range 응답의 data.stats.summary 에 들어 있습니다 — jq '.data.stats.summary' 로 한 번 통째로 보세요. totalLinesProcessedtotalBytesProcessed 두 칸입니다. 이 숫자가 이 실습 내내 견줄 기준선입니다.

다섯 줄을 찾으려고 몇 줄을 읽었나

같은 한 시간 구간에서 네 스트림 전체를 대상으로 본문에 SETTLE-LATE 가 든 줄을 찾는 질의를 /root/lk-filters/02-marker.logql 에 쓰고, 결과 줄 수와 읽은 줄 수를 /root/lk-filters/02-marker.txtlines=<정수>processed=<정수> 두 줄로 적으세요.

줄 필터 하나면 됩니다. 중요한 것은 답이 아니라 답을 얻으려고 읽은 양 입니다 — 두 숫자를 나란히 놓고 보세요. 읽은 줄 수가 1단계의 기준선과 같은지도 확인하세요.

선택자를 좁히면 읽는 양이 준다

같은 답(같은 줄)을 내면서 스트림 선택자만 좁힌 질의를 /root/lk-filters/03-stream.logql 에 쓰고, 결과 줄 수와 읽은 줄 수를 /root/lk-filters/03-stream.txtlines=<정수>·processed=<정수> 로 적으세요. 그리고 /root/lk-filters/03-ratio.txtratio=<소수 둘째 자리> 한 줄로 2단계 대비 읽은 줄 수의 비율을 적습니다.

표시가 어느 서비스에서 나오는지는 2단계 결과의 stream 라벨을 보면 압니다. 선택자를 그 하나로 줄이세요. 결과 줄 수는 그대로여야 합니다 — 답을 바꾸지 않고 비용만 줄이는 것이 이 단계의 요점입니다. 비율은 3단계 읽은 줄 수를 2단계 값으로 나눕니다.

구간을 좁히면 읽는 양은 줄고 답도 줄어든다

3단계와 같은 질의를 구간만 30분(기준 시각에서 과거 1800초)으로 바꿔 던지세요. 결과 줄 수와 읽은 줄 수를 /root/lk-filters/04-window.txtlines=<정수>·processed=<정수> 로 적고, /root/lk-filters/04-note.txttradeoff= 로 시작하는 한 문장(공백 뺀 40자 이상)을 적어 구간을 좁힐 때 무엇을 얻고 무엇을 잃는지 자기 말로 쓰세요.

질의문은 그대로 두고 start 만 바꿉니다. 읽은 줄 수가 절반쯤으로 줄어드는데 결과 줄 수도 함께 줄어듭니다 — 구간 밖의 답은 아예 보이지 않습니다. 사고 시각을 모르는 채 구간부터 좁히면 무엇이 위험한지 생각해 보세요.

줄 필터를 더해도 읽는 양은 그대로다

네 스트림 전체·한 시간 구간에서 두 질의를 던져 읽은 줄 수를 견주세요. 하나는 필터가 전혀 없는 {app=~"edge|cart|ship|batch"}, 다른 하나는 거기에 줄 필터 두 개를 더한 질의입니다. 결과를 /root/lk-filters/05-linefilter.txt 에 네 줄로 적습니다 — plain_processed=, plain_lines=, filtered_processed=, filtered_lines=.

줄 필터는 무엇이든 좋습니다(예: |= "level=error"!= "route=/a"). 보아야 할 것은 네 숫자의 관계입니다 — 어느 쌍이 같고 어느 쌍이 다른가. 같은 쪽이 '읽은 양', 다른 쪽이 '남은 양' 입니다.

파서를 붙여도 읽는 양은 그대로다

네 스트림 전체·한 시간 구간에 | logfmt | status="500" 을 붙인 질의를 던져 세 숫자를 /root/lk-filters/06-parser.txt 에 적으세요 — processed=<읽은 줄 수>, post_filter=<필터를 통과해 남은 줄 수>, lines=<결과 줄 수>. 세 숫자를 1단계 기준선과 견주어, 무엇이 같고 무엇이 달라졌는지 보세요.

totalPostFilterLines 가 통계의 세 번째 칸입니다. cost.sh 는 이 칸을 안 내니 curl ... | jq '.data.stats.summary' 로 직접 보거나 도우미를 고쳐 쓰세요. 파서는 줄 필터보다 비싼 일을 하지만, 읽는 양 이라는 기준에서는 둘이 같은 자리에 있습니다.

응용 ① — 네 방법의 비용표

지금까지 잰 것을 /root/lk-filters/cost.tsv 로 정리하세요. 머리글 없이 네 줄이고 각 줄은 탭으로 나눈 세 칸 <방법><탭><읽은줄수><탭><결과줄수> 입니다. 방법 이름은 순서대로 all(2단계), stream(3단계), window(4단계), parser(6단계)입니다.

앞 단계에서 만든 파일들에서 값을 꺼내 모으면 됩니다. 표를 만들고 나면 한눈에 보입니다 — 읽은 줄 수가 실제로 줄어든 행은 몇 개인가.

응용 ② — 예산 안에서 같은 답을 내는 질의

/root/lk-filters/08-budget.logql 에 질의를 하나 쓰세요. 조건은 셋입니다 — (1) 기준 시각에서 과거 한 시간 구간으로 던졌을 때 2단계와 똑같은 줄을 돌려줄 것, (2) 읽은 줄 수가 1단계 기준선의 3분의 1 이하일 것, (3) limit 에 기대지 말 것. 그리고 /root/lk-filters/08-budget.txtprocessed=<정수> 한 줄로 그 질의가 읽은 줄 수를 적으세요.

읽는 양을 줄이는 손잡이는 둘뿐입니다. 이 단계는 구간을 바꿀 수 없으니 남은 하나로 풀어야 합니다. 2단계 결과의 stream 라벨이 답을 알려 줍니다. 질의를 바꾸고 나서 결과 줄 수가 그대로인지 꼭 다시 재세요 — 싸졌는데 답이 달라지면 튜닝이 아니라 사고입니다.