106 lines
2.3 KiB
Go
106 lines
2.3 KiB
Go
package tracker
|
|
|
|
import (
|
|
"context"
|
|
"github.com/prometheus/client_golang/api"
|
|
v1 "github.com/prometheus/client_golang/api/prometheus/v1"
|
|
"github.com/prometheus/common/model"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type prometheus struct {
|
|
client v1.API
|
|
}
|
|
|
|
// NewPrometheus 初始化Prometheus客户端
|
|
func NewPrometheus(address string) (Interface, error) {
|
|
cfg := api.Config{
|
|
Address: address,
|
|
}
|
|
|
|
client, err := api.NewClient(cfg)
|
|
return prometheus{client: v1.NewAPI(client)}, err
|
|
}
|
|
|
|
func (p prometheus) GetNamedMetrics(metrics []string, ts time.Time, o QueryOption) []Metric {
|
|
var res []Metric
|
|
var mtx sync.Mutex
|
|
var wg sync.WaitGroup
|
|
|
|
opts := NewQueryOptions()
|
|
o.Apply(opts)
|
|
|
|
for _, metric := range metrics {
|
|
wg.Add(1)
|
|
go func(metric string) {
|
|
parsedResp := Metric{MetricName: metric}
|
|
|
|
value, _, err := p.client.Query(context.Background(), makeExpr(metric, *opts), ts)
|
|
if err != nil {
|
|
parsedResp.Error = err.Error()
|
|
} else {
|
|
parsedResp.MetricData = parseQueryResp(value, genMetricFilter(o))
|
|
}
|
|
|
|
mtx.Lock()
|
|
res = append(res, parsedResp)
|
|
mtx.Unlock()
|
|
|
|
wg.Done()
|
|
}(metric)
|
|
}
|
|
|
|
wg.Wait()
|
|
|
|
return res
|
|
}
|
|
func parseQueryResp(value model.Value, metricFilter func(metric model.Metric) bool) MetricData {
|
|
res := MetricData{MetricType: MetricTypeVector}
|
|
|
|
data, _ := value.(model.Vector)
|
|
|
|
for _, v := range data {
|
|
if metricFilter != nil && !metricFilter(v.Metric) {
|
|
continue
|
|
}
|
|
mv := MetricValue{
|
|
Metadata: make(map[string]string),
|
|
}
|
|
|
|
for k, v := range v.Metric {
|
|
mv.Metadata[string(k)] = string(v)
|
|
}
|
|
|
|
mv.Sample = &Point{float64(v.Timestamp) / 1000, float64(v.Value)}
|
|
|
|
res.MetricValues = append(res.MetricValues, mv)
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
func genMetricFilter(o QueryOption) func(metric model.Metric) bool {
|
|
if o != nil {
|
|
if po, ok := o.(PodOption); ok {
|
|
if po.NamespacedResourcesFilter != "" {
|
|
namespacedPodsMap := make(map[string]struct{})
|
|
for _, s := range strings.Split(po.NamespacedResourcesFilter, "|") {
|
|
namespacedPodsMap[s] = struct{}{}
|
|
}
|
|
return func(metric model.Metric) bool {
|
|
if len(metric) == 0 {
|
|
return false
|
|
}
|
|
_, ok := namespacedPodsMap[string(metric["namespace"])+"/"+string(metric["pod"])]
|
|
return ok
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return func(metric model.Metric) bool {
|
|
return true
|
|
}
|
|
}
|