DevOps/Loki
LogQL과 구성 요소
peanutwalnut
2025. 3. 25. 15:55
LogQL은 Grafana Loki에서 로그를 검색하고 집계하기 위해 사용하는 쿼리 언어입니다. PromQL(Prometheus 쿼리 언어)과 유사한 구문 체계를 사용하되, 로그라는 특성에 맞춰 다양한 필터링 기능을 제공합니다. LogQL 쿼리는 크게 **로그 쿼리(Log Query)**와 **로그 기반 메트릭 쿼리(Metric Query)**로 나뉩니다.
1. 기본 구성 요소
1) 레이블 셀렉터(Label Selector)
{app="myapp", environment="production"}
- Loki에 저장된 로그 라인에는 여러 레이블(label)들이 있으며, app="myapp"과 같은 식으로 필수적으로 레이블 조건을 사용해야 합니다.
- 중괄호 {} 안에서 ,로 구분하여 여러 개의 레이블을 지정할 수 있습니다.
- 아래 연산자들을 사용합니다.
- =: 정확히 일치
- !=: 일치하지 않음
- =~: 정규식(Regex) 패턴 일치
- !~: 정규식(Regex) 패턴 불일치
2) 로그 라인 필터(Log Line Filter)
레이블 셀렉터 뒤에 |=, !=, |~, !~ 같은 연산자를 붙여서 로그 라인 내용을 필터링할 수 있습니다.
{app="myapp"} |= "ERROR"
{app="myapp"} != "INFO"
{app="myapp"} |~ "Exception.*timeout"
{app="myapp"} !~ "DEBUG|TRACE"
{app="myapp"} != "INFO"
{app="myapp"} |~ "Exception.*timeout"
{app="myapp"} !~ "DEBUG|TRACE"
- |=: 지정 문자열을 포함하는 로그 라인만 매칭
- !=: 지정 문자열을 포함하지 않는 로그 라인만 매칭
- |~: 지정 정규식(Regex)에 매칭되는 로그 라인만 매칭
- !~: 지정 정규식(Regex)에 매칭되지 않는 로그 라인만 매칭
2. 로그 쿼리(Log Query)
로그 쿼리는 주로 특정 문자열(또는 패턴)을 포함(또는 제외)하는 로그를 검색하기 위해 사용합니다.
- 결과가 “로그 라인” 형태로 반환됩니다.
- 예를 들어, 아래 쿼리는 app="myapp" 레이블을 가진 로그 중 ERROR 문자열을 포함하고, DEBUG 문자열은 포함하지 않는 로그만 필터링합니다.
{app="myapp"} |= "ERROR" != "DEBUG"
이런 쿼리는 Loki에서 단순 검색 용도로 활용할 수 있고, 검색 결과를 Grafana의 Explore 창에서 확인할 수 있습니다.
3. 로그 기반 메트릭 쿼리(Metric Query)
LogQL을 사용하면 로그에서 특정 패턴을 카운트하거나, 로그의 발생 빈도를 그래프로 시각화할 수 있습니다. 이를 로그 기반 메트릭 쿼리라고 합니다. 메트릭 쿼리는 파이프(|) 뒤에 여러 함수를 조합해 사용할 수 있습니다.
1) 범위 벡터(range vector) 함수
아래와 같은 함수들은 특정 시간 범위 내에서 로그 라인들을 집계(Count, Rate 등)합니다.
- count_over_time(): 주어진 기간 동안 일치하는 로그 라인 수를 세어줍니다.
- [] 안에 [5m]와 같이 범위를 지정해야 합니다(최근 5분 동안).
- count_over_time({app="myapp"} |= "ERROR" [5m])
- rate(): 시계열 형태(초당 발생 건수 등)를 구하려고 할 때 사용합니다.
- 최근 5분 동안 발생한 로그 라인의 초당 발생률을 반환합니다.
-
rate({app="myapp"} |= "ERROR" [5m])
- count_over_time() + by (label) 또는 sum by (label) 문법을 함께 사용해 레이블별, 필드별로 그룹화하여 집계할 수 있습니다.
- 예: app="myapp"로 묶여 있는 로그를 1분 단위로 집계한 뒤, level 레이블 별로 합산.
-
sum by (level)(
count_over_time({app="myapp"}[1m])
)
4. 실제 예시
- 오류 로그 발생 빈도(초당) 조회:
rate({job="nginx"} |= "ERROR" [5m])
- job="nginx" 레이블을 가진 로그 중 ERROR가 포함된 로그를 기준으로, 최근 5분 동안 초당 발생 빈도를 계산.
- 레벨별 로그 카운트:
sum by (level) (
count_over_time(
{app="myapp"}[5m]
)
)
count_over_time(
{app="myapp"}[5m]
)
)
- app="myapp"의 최근 5분간 로그 라인을 집계하고, level 레이블(예: INFO, ERROR 등) 별로 합산하여 시계열로 반환.
- 정규식을 이용한 특정 패턴 필터링:
{app=~"service.*"} |~ "user_id=(\\d+)"
- 레이블 app이 service로 시작하는 컨테이너에서, 로그 라인이 user_id=(숫자) 패턴을 포함하면 매칭.