차원별 동적 임계값 예제
차원별 동적 임계값 예제 (Example of dynamic thresholds per dimension)
Grafana Alerting에서 각 알림 규칙은 조건 표현식(condition expression)을 하나만 지원해요. 대부분의 알림은 latency > 3s나 error_rate > 5% 같은 고정 수치 임계값을 쓰니 충분하지만, 알림 구성이 커지면 서로 다른 대상이 서로 다른 임계값을 요구할 수 있어요. 이 예제는 규칙을 중복하지 않고 같은 조건을 유지하면서 대상마다 다른 임계값을 할당하는 방법을 다차원 알림과 Math 표현식으로 보여줘요.
출처: 문서
본문
예제 개요
여러 API 서비스의 지연 시간을 모니터링한다고 해요. 처음에는 95번째 백분위 지연 시간(p95_api_latency)이 3초를 초과하면 알림이 오도록 단일 정적 임계값을 씁니다:
p95_api_latency > 3
하지만 일부 서비스는 더 엄격한 임계값이 필요해요. 예를 들어 결제 API는 1.5초 아래를 유지해야 하고, 백그라운드 작업은 최대 5초까지 견딜 수 있어요. 서비스별 임계값이 이렇게 달라져요:
p95_api_latency{service="checkout-api"}: 1.5s 아래 유지p95_api_latency{service="auth-api"}: 역시 엄격, 1.5sp95_api_latency{service="catalog-api"}: 덜 중요, 3sp95_api_latency{service="async-tasks"}: 백그라운드 작업, 최대 5s
서비스마다 규칙을 하나씩 만드는 건 관리가 어려우니 피하고 싶어요. Grafana Alerting에서는 이런 비슷한 컴포넌트 여러 개를 모니터링하는 하나의 알림 규칙을 정의할 수 있어요 — 이를 다차원 알림이라 해요. 하지만 Grafana는 규칙당 조건을 하나만 지원해요:
One alert rule
├─ One condition ( e.g., $A > 3)
│ └─ Applies to all returned series in $A
│ ├─ {service="checkout-api"}
│ ├─ {service="auth-api"}
│ ├─ {service="catalog-api"}
│ └─ {service="async-tasks"}
서비스별 임계값을 평가하려면 반환된 각 시리즈에 대해 서로 다른 임계값이 필요해요.
Math 표현식으로 동적 임계값 만들기
두 개의 쿼리에 Math 표현식을 적용해 동적 알림 조건을 만들 수 있어요.
$A: 쿼리 결과(예:p95_api_latency)$B: 서비스별 임계값(CSV 데이터나 다른 쿼리에서)$A > $B: 알림 조건을 정의하는 Math 표현식
Grafana는 시리즈별로 Math 표현식을 평가해요. $A와 $B의 시리즈를 공유 라벨을 기준으로 조인한 뒤 표현식을 적용해요. 산술 연산 예제:
$A가{host="web01"} 30,{host="web02"} 20반환$B가{host="web01"} 10,{host="web02"} 0반환$A + $B는{host="web01"} 40,{host="web02"} 20반환
실제로는 임계값 입력을 알림 쿼리가 반환하는 라벨 집합과 정렬해야 해요. 다음 표는 앞선 예제에서 서비스별 임계값이 어떻게 평가되는지 보여줘요:
| $A: p95 지연 쿼리 | $B: 임계값 | $C: $A>$B | 상태 |
|---|---|---|---|
| {service="checkout-api"} 3 | {service="checkout-api"} 1.5 | {service="checkout-api"} 1 | Firing |
| {service="auth-api"} 1 | {service="auth-api"} 1.5 | {service="auth-api"} 0 | Normal |
| {service="catalog-api"} 2 | {service="catalog-api"} 3 | {service="catalog-api"} 0 | Normal |
| {service="sync-work"} 3 | {service="sync-work"} 5 | {service="sync-work"} 0 | Normal |
이 예제에서 $A는 p95_api_latency 쿼리에서, $B는 $A의 각 시리즈에 대한 임계값으로 수동 정의돼요. 알림 조건은 라벨 일치로 시리즈를 조인하는 Math 관계 연산자(>, <, >=, <=, ==, !=)로 $A>$B를 비교하고, 조건이 참인 곳에서 발화 상태를 설정해요.
Math 표현식은 $A의 각 시리즈가 $B의 시리즈 정확히 하나와 일치할 수 있을 때 작동해요. 한 쿼리의 시리즈가 다른 쿼리의 어떤 시리즈와도 일치하지 않으면 결과에서 제외되고 경고 메시지가 표시돼요:
Caution 1 items dropped from union(s) : ["$A > $B": ($B: {service=payment-api})]
양 시리즈의 라벨이 동일할 필요는 없어요. 라벨이 다른 쪽의 부분집합이면 조인할 수 있어요. 예를 들어 $A가 {host="web01", job="event"} 30을, $B가 {host="web01"} 10을 반환하면 $A + $B는 {host="web01", job="event"} 40을 반환해요.
TestData로 시도해 보기
TestData 데이터 소스로 이 예제를 재현할 수 있어요:
- Connections 메뉴로 TestData 데이터 소스를 추가해요.
- Alerting → Alert rules로 이동해 알림 규칙을 만들어요.
- 각 서비스의 지연 시간을 반환하는 쿼리(
$A)를 시뮬레이션해요. TestData에서 Scenario: Random Walk, Alias: latency, Labels: service=api-$seriesIndex, Series count: 4, Start value: 1, Min: 1, Max: 4로 설정해요. ($seriesIndex로 api-0, api-1 식의 고유 service 라벨을 부여해요.) - 정적 데이터로 서비스별 임계값을 정의해요. 새 쿼리(
$B)를 추가하고 TestData를 선택한 뒤 Scenario에서 CSV Content를 선택해 이 CSV를 붙여넣어요:
service,value
api-0,1.5
api-1,1.5
api-2,3
api-3,5
service 열은 $A의 라벨과 일치해야 해요. value 열은 알림 비교에 쓰는 수치 값이에요.
- 새 Reduce 표현식(
$C)을 추가해요. Type: Reduce, Input: A, Function: Mean, Name: C. 각 서비스의 평균 지연 시간을 계산해요. - Math 표현식을 추가해요. Type: Math, Expression:
$C > $B, 이 표현식을 알림 조건으로 설정해요. 어떤 서비스든 평균 지연 시간($C)이$B의 임계값을 초과하면 발화해요.
다른 사용 사례
이 예제는 다차원 알림과 Math 표현식으로 시리즈별 서로 다른 임계값을 가진 단일 알림 규칙을 만드는 법을 보여줬어요. 이 접근법은 서로 다른 안정성 목표를 가진 비슷한 컴포넌트를 모니터링할 때 잘 확장돼요. 두 쿼리의 시리즈를 정렬하면 규칙 중복 없이 라벨 집합당 하나의 값인 동적 임계값을 적용할 수 있어요. 이 예제는 임계값 정의에 정적 CSV를 쓰지만, 같은 기법은 다른 시나리오에서도 적용 가능해요:
- 쿼리나 레코딩 규칙의 동적 임계값: 실시간 쿼리나 커스텀 레코딩 규칙에서 임계값을 가져와요.
- 여러 조건 결합: 지연 시간, 오류율, 트래픽 양 같은 여러 조건을 결합해 더 고급 임계값 로직을 만들 수 있어요.
예를 들어 트래픽에 따라 조정되는 지연 임계값을 설정하는 PromQL 표현식을 정의할 수 있어요 — 높은 부하 기간에 더 높은 응답 시간을 허용하는 방식이에요:
(
// Fires when p95 latency > 2s during usual traffic (≤ 1000 req/s)
service:latency:p95 > 2 and service:request_rate:rate1m <= 1000
)
or
(
// Fires when p95 latency > 4s during high traffic (> 1000 req/s)
service:latency:p95 > 4 and service:request_rate:rate1m > 1000
)