托管 Prometheus 工作区兼容原生 Prom,支持通过 Go 语言进行数据写入和查询。本文介绍使用 Go 语言在工作区进行进行数据写入和查询的方法和示例。
package main import ( "context" "encoding/base64" "fmt" "net/http" "time" "github.com/castai/promwrite" ) // NewRoundTripper ... func NewRoundTripper(username, password string) http.RoundTripper { return &basicAuthTransport{ transport: http.DefaultTransport, basicAuth: "Basic " + base64.StdEncoding.EncodeToString([]byte(username+":"+password)), } } type basicAuthTransport struct { transport http.RoundTripper basicAuth string } func (bat *basicAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { req.Header.Add("Authorization", bat.basicAuth) return bat.transport.RoundTrip(req) } func main() { username := "username" // 在 vmp 工作区配置的 basicAuth username password := "password" // 在 vmp 工作区配置的 basicAuth password remotewriteURL := "remotewrite 地址" // 可在 vmp 工作区详情页复制 c := promwrite.NewClient(remotewriteURL, promwrite.HttpClient(&http.Client{ Transport: NewRoundTripper(username, password), })) resp, err := c.Write(context.Background(), &promwrite.WriteRequest{ TimeSeries: []promwrite.TimeSeries{ { Labels: []promwrite.Label{ { Name: "__name__", Value: "my_metric_name", }, }, Sample: promwrite.Sample{ Time: time.Now(), Value: 123, }, }, }, }) fmt.Println(resp, err) }
package main import ( "context" "fmt" "net/http" "time" "github.com/castai/promwrite" "github.com/volcengine/volc-sdk-golang/base" ) // Config is the configuration for signing remote write requests with // volcengine verification process. Empty values will be retrieved using the // volcengine default credentials chain. type Config struct { Region string AccessKey string SecretKey string Service string } // NewRoundTripper returns a new http.RoundTripper that will sign requests // using Volcengine's Signature Verification signing procedure. // Credentials for signing are retrieved using the the default volcengine credential // chain. If credentials cannot be found, an error will be returned. func NewRoundTripper(cfg *Config) (http.RoundTripper, error) { rt := &volcRoundTripper{ next: http.DefaultTransport, signer: &base.Credentials{ AccessKeyID: cfg.AccessKey, SecretAccessKey: cfg.SecretKey, Region: cfg.Region, Service: cfg.Service, }, } return rt, nil } type volcRoundTripper struct { next http.RoundTripper signer *base.Credentials } func (rt *volcRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { q := req.URL.Query() req.URL.RawQuery = q.Encode() return rt.next.RoundTrip(rt.signer.Sign(req)) } func main() { rt, err := NewRoundTripper(&Config{ Region: "region", // workspace 地域 AccessKey: "ak", // 具有 vmp remotewrite 访问权限的用户 ak SecretKey: "sk", // 具有 vmp remotewrite 访问权限的用户 sk Service: "vmp", }) if err != nil { panic(err) } remotewriteURL := "remotewrite 地址" // 可在 vmp 工作区详情页复制 c := promwrite.NewClient(remotewriteURL, promwrite.HttpClient(&http.Client{ Transport: rt, })) resp, err := c.Write(context.Background(), &promwrite.WriteRequest{ TimeSeries: []promwrite.TimeSeries{ { Labels: []promwrite.Label{ { Name: "__name__", Value: "my_metric_name", }, }, Sample: promwrite.Sample{ Time: time.Now(), Value: 123, }, }, }, }) fmt.Println(resp, err) }
由于托管 Prometheus 产品接口兼容原生 Prom,因此在调用接口时可以使用现成的 Prom SDK,以下是基于 client_go 的实现样例。
import ( "net/http" "strconv" "github.com/prometheus/client_golang/api" promv1 "github.com/prometheus/client_golang/api/prometheus/v1" ) // NewPromAPI ... func NewPromAPI(queryAddress, username, password string) (promv1.API, error) { promClient, err := api.NewClient(api.Config{ Address: queryAddress, RoundTripper: NewBasicAuthRoundTripper(http.DefaultTransport, username, password), }) if err != nil { return nil, err } return promv1.NewAPI(promClient), nil } // NewBasicAuthRoundTripper ... func NewBasicAuthRoundTripper(next http.RoundTripper, username, password string) http.RoundTripper { if next == nil { next = http.DefaultTransport } return &basicAuthTransport{ transport: http.DefaultTransport, basicAuth: "Basic " + base64.StdEncoding.EncodeToString([]byte(username+":"+password)), } } type basicAuthTransport struct { transport http.RoundTripper basicAuth string } func (bat *basicAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { req.Header.Add("Authorization", bat.basicAuth) return bat.transport.RoundTrip(req) } func main(){ address := "vmp query 地址" // 可在 vmp 工作区详情页复制 username := "username" // 在 vmp 工作区配置的 basicAuth username password := "password" // 在 vmp 工作区配置的 basicAuth password api, err := NewPromAPI(address, username, password) res, _, err := api.Query(context.TODO(), "up", time.Now()) fmt.Println(res, err) }
import ( "context" "fmt" "net/http" "time" "github.com/prometheus/client_golang/api" promv1 "github.com/prometheus/client_golang/api/prometheus/v1" "github.com/volcengine/volc-sdk-golang/base" ) // Config is the configuration for signing query requests with // volcengine verification process. Empty values will be retrieved using the // volcengine default credentials chain. type Config struct { Region string // 访问地区 AccessKey string // 服务ak SecretKey string // 服务sk Service string // vmp 服务名,为 vmp } type volcRoundTripper struct { next http.RoundTripper signer *base.Credentials } // NewRoundTripper returns a new http.RoundTripper that will sign requests // using Volcengine's Signature Verification signing procedure. // // Credentials for signing are retrieved using the the default volcengine credential // chain. If credentials cannot be found, an error will be returned. func NewRoundTripper(cfg *Config) (http.RoundTripper, error) { rt := &volcRoundTripper{ next: http.DefaultTransport, signer: &base.Credentials{ AccessKeyID: cfg.AccessKey, SecretAccessKey: cfg.SecretKey, Region: cfg.Region, Service: cfg.Service, }, } return rt, nil } func (rt *volcRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { q := req.URL.Query() req.URL.RawQuery = q.Encode() return rt.next.RoundTrip(rt.signer.Sign(req)) } // NewPromClient ... func NewPromClient(cfg *Config, queryAddress string) (promv1.API, error) { rt, err := NewRoundTripper(cfg) if err != nil { return nil, err } promClient, err := api.NewClient(api.Config{ Address: queryAddress, RoundTripper: rt, }) if err != nil { return nil, err } return promv1.NewAPI(promClient), nil } func main() { api, err := NewPromClient(&Config{ Region: "region", AccessKey: "ak", SecretKey: "sk", Service: "vmp", }, "query地址") if err != nil { fmt.Println(err.Error()) } res, _, err := api.Query(context.TODO(), "up", time.Now()) fmt.Println(res, err) }
Query 的结果一般是 ValVector 和 ValScalar 类型,可参考下面对结果进行处理。另外 QueryRange 的查询类型是 prommodel.Matrix,可依据下面做扩展。
func parseQueryResp(value prommodel.Value) (prommodel.Vector, error) { var samples prommodel.Vector var ok bool switch value.Type() { case prommodel.ValVector: samples, ok = value.(prommodel.Vector) if !ok { return nil, errors.New("convert result to \"model.Vector\"") } case prommodel.ValScalar: var scalar *prommodel.Scalar scalar, ok = value.(*prommodel.Scalar) if !ok { return nil, errors.New("convert result to \"model.Scalar\"") } samples = append(samples, &prommodel.Sample{ Timestamp: scalar.Timestamp, Value: scalar.Value, }) default: return nil, errors.New("invalid query result") } return samples, nil }