最近專案組在做Prometheus指標採集和告警,其中用到了Prometheus的exemplar特性,由於該特性比較新,當前支援該特性的儲存有比較少。因此需要自行實現exemplar功能。
我在github上建立了一個程式碼庫,內容如下:
功能支援列表
- 支援從kafka消費Prometheus指標資料,資料使用protobuf編碼
- 支援Prometheus exemplar功能
- 支援exemplar的wal
- 支援remote write指標到儲存
kafka消費端
本專案使用的是騰訊的cKafka
golang的kafka消費端需要用到github.com/confluentinc/confluent-kafka-go/kafka
,使用該庫之前需要安裝librdkafka
庫,但不支援在Windows系統上安裝librdkafka
。安裝步驟如下:
git clone https://github.com/edenhill/librdkafka.gitcd librdkafka./configuremakesudo make install
環境上執行時可以考慮將
librdkafka
庫編譯到映象中。如使用Alpine映象時執行apk add librdkafka-dev pkgconf
安裝即可。官方文件中有提到,如果使用Alpine Linux ,編譯方式為:go build -tags musl ./...
Metrics的寫入
只需將metrics使用proto.Marshal
編碼到promWR
即可:
func (c *client) WriteRaw( ctx context.Context, promWR []byte, opts WriteOptions,) (WriteResult, WriteError) { var result WriteResult encoded := snappy.Encode(nil, promWR) body := bytes.NewReader(encoded) req, err := http.NewRequest("POST", c.writeURL, body) if err != nil { return result, writeError{err: err} } req.Header.Set("Content-Type", "application/x-protobuf") req.Header.Set("Content-Encoding", "snappy") req.Header.Set("User-Agent", c.userAgent) req.Header.Set("X-Prometheus-Remote-Write-Version", "0.1.0") if opts.Headers != nil { for k, v := range opts.Headers { req.Header.Set(k, v) } } resp, err := c.httpClient.Do(req.WithContext(ctx)) if err != nil { return result, writeError{err: err} } result.StatusCode = resp.StatusCode defer resp.Body.Close() if result.StatusCode/100 != 2 { writeErr := writeError{ err: fmt.Errorf("expected HTTP 200 status code: actual=%d", resp.StatusCode), code: result.StatusCode, } body, err := ioutil.ReadAll(resp.Body) if err != nil { writeErr.err = fmt.Errorf("%v, body_read_error=%s", writeErr.err, err) return result, writeErr } writeErr.err = fmt.Errorf("%v, body=%s", writeErr.err, body) return result, writeErr } return result, nil}
metric的查詢
使用victoriametrics時,強烈建議同時部署grafana,使用grafana中的Explore
功能來查詢metrics。victoriametrics的vmselect元件自帶的UI很不方便。
映象編譯
如上所述,如果需要在需要Alpine Linux中進行編譯,則需要在在Dockerfile中新增如下內容:
RUN apk add git && apk add librdkafka-dev pkgconf && apk add build-base && apk add alpine-sdk
由於上述lib的安裝比較滿,為了加快安裝,可以將安裝了這些lib的映象作為基礎映象。
FROM golang:1.16.8-alpine3.14 as buildWORKDIR /appRUN apk add git && apk add librdkafka-dev pkgconf && apk add build-base && apk add alpine-sdkENV http_proxy= GO111MODULE=on GOPROXY=https://goproxy.cn,direct GOPRIVATE=*.weimob.comCOPY go.mod .COPY go.sum .COPY . .RUN cd cmd/ && GOOS=linux go build -tags musl -o ../prometheusWriter main.goCMD ["/app/prometheusWriter"]FROM alpine:latestWORKDIR /appRUN sed -i s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g /etc/apk/repositoriesRUN apk add tzdataRUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo "Asia/Shanghai" > /etc/timezoneCOPY --from=build /app/prometheusWriter /app/RUN chmod +x /app/prometheusWriterCOPY config.json /app/config.jsonCMD ["/app/prometheusWriter"]
支援Exemplar
Exemplar的資料結構比較簡單,就是個ring buffer。
下面是使用curl命令進行查詢的例子:
# curl '127.0.0.1:8000' --header 'Content-Type: application/json' -d '{"start":"1632980302","end":"1632980402","query":"{testlabel11=\"test\"}"}'