PromQL의 구성 요소 및 개념

Hansu Kim·2022년 4월 26일
1

PromQL은 prometheus query이다.
본 포스트에서는 PromQL을 사용하기 위한 기본 개념들을 정리하고자 한다.

Time Series

Time series란 시간에 따른 값 변화를 말한다.
prometheus의 데이터는 [시간, 값], [시간, 값] 으로 표현되어있는데, 하나의 [시간, 값]을 sample이라고 부르고, sample의 배열을 Time series라고 한다.

Data Type

Prometheus의 자료형은 다음 4개로 구분된다.

  • Instant vector
  • Range vector
  • Scalar
    • 시간 정보가 없는 값. 단순한 숫자
  • String
    • 문자열 데이터로, 실제 사용되지는 않는다.

Instant Vector

같은 타임스탬프에 있는 Time series 집합이다.
각 Time series마다 단일 샘플을 가지고 있다.
metric 이름으로 쿼리를 실행하면 Instance Vector를 얻을 수 있고, 필터링을 하고 싶으면 Instant Vector selector를 사용한다.

  • Selector로 mysql_global_status_threads_connect 메트릭을 입력하여,
    2022-04-26 09:18:49 Timestamp의 Instant Vector 중 mysql에 연결된 쓰레드 수 메트릭 값을 조회했다.

Range vector

특정 시간 범위에 있는 Time series set.
Instant vector는 각 time-series들이 1개의 Sample만 가지는 것에 반해, Range vector는 지정된 범위의 시간에 속하는 Time series들로 구성되어 있다.

Range Vector는 metric이름 뒤에 [시간]을 붙이면 된다.
go_memstats_freees_total [5m]은 아래와 같이 분류된다.

  • Instant vector selector: go_memstats_frees_total
  • Range vector selector: [ ]
  • Time duration: 5m

Selector로 go_memstats_frees_total 메트릭을 입력하여 5분간의 Range vector가 반환됐다.
반환된 값은 <value> @<timestamp>로 구성되어있다.
Range vector는 반환값이 여러 sample들이 되므로 보통 혼자서 쓰이지는 않고, 평균값이나 변동폭(rate)과 같은 aggregation function을 사용해야 한다.

Selector

Instant vector selectors

지정된 타임스탬프의 단일 샘플 값을 가지고 올 수 있다.
간단하게는 메트릭 이름만으로 Instant vector selector를 지정할 수 있다.
또한 selector 뒤에 {}로 matcher들을 콤마로 구분하여 넣어주어 라벨에 따른 필터링을 할 수 있다.

matcher를 통한 라벨 매칭시, 아래의 Operator가 사용된다.

  • = : 일치
  • != : 불일치
  • =~ : 정규식 매칭
  • !~ : 정규식 불일치

Range vector selectors

Instant vector selector와 비슷하나, 끝에 []를 통해 기간을 추가하여, 특정 range vector들을 선택한다.

Modifier

offset modifier

과거 시간을 기준으로 Instant, range vector를 조회할 때 사용한다.
Selector 뒤에 "offset" 문자열과 time duration을 지정해준다.

offset modifier는 항상 selector 바로 뒤에 있어야 한다.

@ modifier

개별 instant, range vector를 평가하는 시간을 변경한다.
@ modifier는 Unix timestamp 형식으로 지정한다.

@ modifier도 selector 바로 뒤에 위치해야 한다.
만약 @ modifier와 offset modifier가 동시에 사용됐을 경우, @ modifer가 우선된다.

Subquery

range vector selector를 지정한 해상도로 조회한다.

Operators

Binary operators

Arithmetic binary operators

+ (addition)
- (subtraction)
* (multiplication)
/ (division)
% (modulo)
^ (power/exponentiation)

Comparison binary operators

== (equal)
!= (not-equal)
> (greater-than)
< (less-than)
>= (greater-or-equal)
<= (less-or-equal)

Logical/set binary operators

and (intersection)
or (union)
unless (complement)

Aggregation Operators

  • sum (calculate sum over dimensions)
  • min (select minimum over dimensions)
  • max (select maximum over dimensions)
  • avg (calculate the average over dimensions)
  • stddev (calculate population standard deviation over dimensions)
  • stdvar (calculate population standard variance over dimensions)
  • count (count number of elements in the vector)
  • count_values (count number of elements with the same value)
  • bottomk (smallest k elements by sample value)
  • topk (largest k elements by sample value)
  • quantile (calculate φ-quantile (0 ≤ φ ≤ 1) over dimensions)

Vector Matching

PromQL의 가장 강력한 기능이다.
Instant vector들을 Label을 통해 matching하여 값들을 연산하거나 Label을 결합할 수 있다.

One-to-one matching

Vector가 1:1로 정확히 일치하는 경우 사용한다. (Label matching으로 두 개 이상의 vector들이 1:1로 매핑되는 경우)
ignoring 키워드를 통해 특정 라벨을 무시하거나, on 키워드로 제공되는 라벨리스트를 특정 라벨들로 구성되도록 할 수 있다.

<vector expr> <bin-op> ignoring(<label list>) <vector expr>
<vector expr> <bin-op> on(<label list>) <vector expr>
# Example Input
method_code:http_errors:rate5m{method="get", code="500"}  24
method_code:http_errors:rate5m{method="get", code="404"}  30
method_code:http_errors:rate5m{method="put", code="501"}  3
method_code:http_errors:rate5m{method="post", code="500"} 6
method_code:http_errors:rate5m{method="post", code="404"} 21

method:http_requests:rate5m{method="get"}  600
method:http_requests:rate5m{method="del"}  34
method:http_requests:rate5m{method="post"} 120
# Example query
method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m
# Example output
{method="get"}  0.04            //  24 / 600
{method="post"} 0.05            //   6 / 120

One-to-many / Many-to-one matching

one 쪽의 벡터가 many쪽의 벡터와 일치할 수 있는 경우에 사용된다.
해당 케이스에서 group_left modifier나 group_right modifier를 통해 더 높은 cardinality를 갖는 쪽을 지정해줘야 한다.

<vector expr> <bin-op> ignoring(<label list>) group_left(<label list>) <vector expr>
<vector expr> <bin-op> ignoring(<label list>) group_right(<label list>) <vector expr>
<vector expr> <bin-op> on(<label list>) group_left(<label list>) <vector expr>
<vector expr> <bin-op> on(<label list>) group_right(<label list>) <vector expr>
# Example Input
method_code:http_errors:rate5m{method="get", code="500"}  24
method_code:http_errors:rate5m{method="get", code="404"}  30
method_code:http_errors:rate5m{method="put", code="501"}  3
method_code:http_errors:rate5m{method="post", code="500"} 6
method_code:http_errors:rate5m{method="post", code="404"} 21

method:http_requests:rate5m{method="get"}  600
method:http_requests:rate5m{method="del"}  34
method:http_requests:rate5m{method="post"} 120
# Example Query
method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m
# Example Output
{method="get", code="500"}  0.04            //  24 / 600
{method="get", code="404"}  0.05            //  30 / 600
{method="post", code="500"} 0.05            //   6 / 120
{method="post", code="404"} 0.175           //  21 / 120

Staleness

각 vector들의 Timestamp는 사실 정확히 일치하지 않는다.
각 exporter별 interval이나 duration 등이 다를 수 있기 때문이다.

그에 따라 Range vector 등에서 시간을 지정할 경우, 프로메테우스는 독립성으로 인해 각 Time series에 대해 해당 타임스탬프 값(sampling timestamp)을 할당하고, 실제 값은 타임스탬프 이전의 최신 샘플을 가져오게 된다.

만약 특정 Timeseries가 5분간 sample을 반환하지 않았을 경우, 그 후부터는 해당 Timeseries는 'stale'이라고 마킹되고, 해당 값들은 더 이상 Time series로 반환되지 않는다.
(새 샘플이 수집되면 다시 정상적으로 반환된다.)

sampling timestamp 5분 전에 해당 샘플이 없으면, Timeseries에 대한 값이 반환되지 않기 때문에, 이것은 사실상 값이 사라진다고 보면 된다.

만약 Scrape에 Timestamp가 포함되어있다면 해당 Time series에는 'stale'이라고 마킹되지는 않고 5분의 임계값만 적용된다.

1개의 댓글

comment-user-thumbnail
2022년 10월 13일

gg

답글 달기