본문 바로가기
Development

동적 Prometheus 쿼리 만들기 with golang(레이블 삽입하기)

by 토마스.dev 2023. 12. 27.
반응형

그라파나를 통해서 사용자에게 메트릭을 제공하려고 할때 가끔가다가 사용자별 테넌트 분리를 해야하는 경우가 있다.

또는 동적으로 변하는 특정 타겟별로 각 메트릭을 얻어오는 사이드카를 만들려고 할때 고정된 쿼리를 사용할수 없는 경우도 있다.

 

이럴 때는 base prometheus 쿼리를 기반으로 동적으로 레이블을 넣어줄 수 있다. 여기서는 golang client를 이용하는 방법을 설명한다.

 

package main

import (
	"fmt"
	"github.com/prometheus/prometheus/promql/parser"
)

// addLabelToQuery는 주어진 PromQL 쿼리에 새로운 레이블을 추가합니다.
func addLabelToQuery(query, labelName, labelValue string) (string, error) {
	expr, err := parser.ParseExpr(query)
	if err != nil {
		return "", err
	}

	parser.Inspect(expr, func(node parser.Node, path []parser.Node) error {
		switch n := node.(type) {
		case *parser.VectorSelector:
			n.LabelMatchers = append(n.LabelMatchers, &parser.LabelMatcher{
				Type:  parser.MatchEqual,
				Name:  labelName,
				Value: labelValue,
			})
		}
		return nil
	})

	return expr.String(), nil
}

func main() {
	originalQuery := `sum(rate(http_requests_total[5m])) by (service)`
	labelToAdd := "region"
	labelValue := "us-west"

	newQuery, err := addLabelToQuery(originalQuery, labelToAdd, labelValue)
	if err != nil {
		fmt.Println("Error modifying query:", err)
		return
	}

	fmt.Println("Modified Query:", newQuery)
}

 

client 에 포함된 parser pkg를 사용한다.

parser 는 문자열로 인입된 쿼리를 파싱하여. 셀렉터(레이블) 노드 지점에 새로운 셀렉터를 추가한다.

셀렉터 외에도 다른 노드도 처리할 수 있다.

 

https://pkg.go.dev/github.com/prometheus/prometheus/promql/parser

 

parser package - github.com/prometheus/prometheus/promql/parser - Go Packages

  The highest tagged major version is v2. Discover Packages github.com/prometheus/prometheus promql parser Version: v0.48.1 Opens a new window with list of versions in this module. Published: Dec 8, 2023 License: Apache-2.0 Opens a new window with license

pkg.go.dev

 

위 예시코드의 결과는 다음과 같다.

sum(rate(http_requests_total{region="us-west"}[5m])) by (service)

 

리전이 동적으로 변해서 미래에 추가되거나 삭제될수 있는데, 리전별로 메트릭을 추출해 운영 자동화를 하고자할때 유용하게 사용할 수 있다.

반응형