阿里云Prometheus监控的Remote Write功能支持作为远程数据库存储Prometheus监控数据。本文将介绍如何创建Prometheus实例 for Remote Write(Remote Write类型的Prometheus实例),即如何使用阿里云Prometheus监控的Remote Write对接自建Prometheus,构建监控数据的高效存储方案。
(可选)步骤一:为RAM用户授予GetPrometheusApiToken接口调用权限
自建Prometheus写入阿里云Prometheus监控时需要调用GetPrometheusApiToken接口。阿里云账号(主账号)默认支持调用GetPrometheusApiToken接口。如果您是RAM用户(子账号),则需要先使用阿里云账号为RAM用户授予GetPrometheusApiToken接口的调用权限。
步骤二:创建Remote Write并获取读写URL
步骤三:配置Prometheus
使用远程存储对接OpenTelemetry
阿里云Prometheus监控的远程存储对接OpenTelemetry之后,您可以使用Prometheus监控的远程存储功能存储OpenTelemetry的数据。
- 业务代码进行OpenTelemetry埋点。
package stat import ( "context" "fmt" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/metric" "time" ) var buyCounter metric.Int64Counter func init() { fmt.Println(time.Now(), " - initMetrics start......") meter := otel.GetMeterProvider().Meter("github.com/liguozhong/prometheus-arms-aliyun-go-demo") buyCounter = metric.Must(meter).NewInt64Counter( "buy_total", metric.WithDescription("Measures buy"), ) } func DoBuy() (string, error) { buyCounter.Add(context.Background(), 1) return "buy success", nil }
- OpenTelemetry对Meter进行初始化并和连接Prometheus。
package stat import ( "context" prometheusPushExporter "go.opentelemetry.io/contrib/exporters/metric/cortex" prometheusExporter "go.opentelemetry.io/otel/exporters/metric/prometheus" "errors" "fmt" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp" "go.opentelemetry.io/otel/label" "go.opentelemetry.io/otel/sdk/metric/controller/pull" "go.opentelemetry.io/otel/sdk/metric/controller/push" "go.opentelemetry.io/otel/sdk/metric/processor/basic" "go.opentelemetry.io/otel/sdk/metric/selector/simple" "go.opentelemetry.io/otel/sdk/resource" "net/http" "time" _ "net/http/pprof" ) func InitMeter(app string, push bool) error { fmt.Println(time.Now(), " - initMeter start......") if push { fmt.Println(time.Now(), " - initMeter opentelemetry push......") remoteUrl := "http://region.arms.aliyuncs.com/prometheus/../../../../api/v3/write" ak := "ak" sk := "sk" return initPushMeter(app, remoteUrl, ak, sk) } fmt.Println(time.Now(), " - initMeter opentelemetry pull......") return initPullMeter(app) } func initPushMeter(regionId string, remoteWriteUrl string, ak string, sk string) error { fmt.Println(time.Now(), " - initPushMeter start......") var validatedStandardConfig = prometheusPushExporter.Config{ Endpoint: remoteWriteUrl, Name: "AliyunConfig", RemoteTimeout: 30 * time.Second, PushInterval: 10 * time.Second, Quantiles: []float64{0.5, 0.9, 0.95, 0.99}, BasicAuth: map[string]string{ "username": ak, "password": sk, }, } if validatedStandardConfig.Endpoint == "" { return errors.New(" validatedStandardConfig.Endpoint==empty.regionId:" + regionId) } fmt.Println("Success: Created Config struct") r, err := resource.New(context.Background(), resource.WithAttributes( label.String("cluster", "test-otel"), label.String("app", "buy"))) if err != nil { fmt.Println("resource Error:", err) } pusher, err := prometheusPushExporter.InstallNewPipeline(validatedStandardConfig, push.WithPeriod(30*time.Second), push.WithResource(r)) if err != nil { fmt.Println("InstallNewPipeline Error:", err) } otel.SetMeterProvider(pusher.MeterProvider()) return nil } func initPullMeter(app string) error { fmt.Println(time.Now(), " - initPullMeter start......") r, err := resource.New(context.Background(), resource.WithAttributes( label.String("cluster", "test-otel"), label.String("app", app))) if err != nil { fmt.Println("resource Error:", err) } exporter, err := prometheusExporter.NewExportPipeline( prometheusExporter.Config{ DefaultHistogramBoundaries: []float64{-0.5, 1}, }, pull.WithCachePeriod(0), pull.WithResource(r), ) if err != nil { return err } http.HandleFunc("/opentelemetry", exporter.ServeHTTP) otel.SetMeterProvider(exporter.MeterProvider()) return nil } func initOtlpProvider(regionId string) (*push.Controller, error) { exporter, err := otlp.NewExporter( context.Background(), otlp.WithInsecure(), otlp.WithAddress(regionId+"-intranet.arms.aliyuncs.com:8000"), ) if err != nil { return nil, err } pusher := push.New( basic.New( simple.NewWithExactDistribution(), exporter, ), exporter, push.WithPeriod(30*time.Second), ) otel.SetMeterProvider(pusher.MeterProvider()) pusher.Start() return pusher, err }
- 业务入口初始化,并启动OpenTelemetry功能。
package pkg import ( "fmt" stat "github.com/liguozhong/prometheus-arms-aliyun-go-demo/pkg/opentelemetry" "github.com/prometheus/client_golang/prometheus/promhttp" "io" "net/http" "strconv" ) type Server struct { port int } func NewServer(port int) *Server { return &Server{ port: port, } } func (s *Server) Run() error { port := ":" + strconv.Itoa(s.port) path := "/metrics" service := "/buy" http.Handle(path, promhttp.Handler()) //初始一个http handler http.HandleFunc(service, func(writer http.ResponseWriter, request *http.Request) { content, err := stat.DoBuy() if err != nil { io.WriteString(writer, err.Error()) return } io.WriteString(writer, content) }) stat.InitMeter("buy2", true) fmt.Println("http.url: http://localhost" + port + path) fmt.Println("service.url: http://localhost" + port + service) err := http.ListenAndServe(port, nil) if err != nil { return err } return nil }
- 查看Go module的依赖列表。
module github.com/liguozhong/prometheus-arms-aliyun-go-demo go 1.12 require ( github.com/go-kit/kit v0.9.0 github.com/prometheus/client_golang v1.7.1 go.opentelemetry.io/contrib/exporters/metric/cortex v0.15.0 go.opentelemetry.io/otel v0.15.0 go.opentelemetry.io/otel/exporters/metric/prometheus v0.15.0 go.opentelemetry.io/otel/exporters/otlp v0.15.0 go.opentelemetry.io/otel/sdk v0.15.0 golang.org/x/text v0.3.3 // indirect )
- 在Grafana大盘中查看数据。
停止远程存储Prometheus监控数据
如需停止远程数据库存储Prometheus监控数据,请按照以下步骤卸载插件。