From 616c320058563bbb049d906698da70a664884702 Mon Sep 17 00:00:00 2001 From: zhengya Date: Mon, 25 Sep 2023 18:58:04 +0800 Subject: [PATCH] [CONTROLLER/PROMETHEUS] optimizes memory --- message/controller.proto | 6 ++ server/controller/prometheus/cache/cache.go | 42 ++++------ server/controller/prometheus/cache/label.go | 25 +++--- .../prometheus/cache/metric_label.go | 83 +++++++++---------- .../prometheus/cache/metric_name.go | 10 +++ .../controller/prometheus/encoder/encoder.go | 10 ++- .../prometheus/encoder/metric_label.go | 81 +++++++++++++----- .../prometheus/encoder/metric_name.go | 15 ++-- server/controller/prometheus/label.go | 38 +++++---- server/controller/prometheus/synchronizer.go | 15 +++- server/controller/prometheus/updater.go | 18 ++-- 11 files changed, 202 insertions(+), 141 deletions(-) diff --git a/message/controller.proto b/message/controller.proto index 18446752475..7746f8c7f77 100644 --- a/message/controller.proto +++ b/message/controller.proto @@ -214,6 +214,11 @@ message PrometheusMetricLabelRequest { repeated PrometheusLabelRequest labels = 2; } +message PrometheusMetricLabel { + optional uint32 metric_name_id = 1; + repeated uint32 label_ids = 2; +} + message PrometheusMetricAPPLabelLayout { required string metric_name = 1; required string app_label_name = 2; @@ -282,6 +287,7 @@ message SyncPrometheusResponse { repeated PrometheusLabel labels = 6; repeated PrometheusMetricTarget metric_targets = 7; repeated PrometheusTarget targets = 8; + repeated PrometheusMetricLabel metric_labels = 9; } service PrometheusDebug { diff --git a/server/controller/prometheus/cache/cache.go b/server/controller/prometheus/cache/cache.go index d8dd5226668..2e679f9ad56 100644 --- a/server/controller/prometheus/cache/cache.go +++ b/server/controller/prometheus/cache/cache.go @@ -23,6 +23,7 @@ import ( "sync" "time" + mapset "github.com/deckarep/golang-set/v2" "github.com/op/go-logging" "golang.org/x/sync/errgroup" @@ -67,7 +68,7 @@ func GetSingleton() *Cache { MetricAndAPPLabelLayout: new(metricAndAPPLabelLayout), Target: t, Label: l, - MetricLabel: newMetricLabel(l), + MetricLabel: newMetricLabel(mn, l), MetricTarget: newMetricTarget(mn, t), } }) @@ -216,47 +217,34 @@ func GetDebugCache(t controller.PrometheusCacheType) []byte { } getLabel := func() { temp := map[string]interface{}{ - "keys": make(map[string]interface{}), + "key_to_id": make(map[string]interface{}), "id_to_key": make(map[int]string), } + tempCache.Label.idToKey.Range(func(key, value any) bool { + temp["key_to_id"].(map[string]interface{})[marshal(key)] = value + return true + }) tempCache.Label.idToKey.Range(func(key, value any) bool { temp["id_to_key"].(map[int]string)[key.(int)] = marshal(value) return true }) - for item := range tempCache.Label.keys.Iterator().C { - temp["keys"].(map[string]interface{})[marshal(item)] = struct{}{} - } - if len(temp["keys"].(map[string]interface{})) > 0 || + + if len(temp["key_to_id"].(map[string]interface{})) > 0 || len(temp["id_to_key"].(map[int]string)) > 0 { content["label"] = temp } } getMetricLabel := func() { temp := map[string]interface{}{ - "label_cache": map[string]interface{}{ - "keys": make(map[string]interface{}), - "id_to_key": make(map[int]string), - }, - "metric_name_to_label_ids": make(map[string][]int), - "metric_label_detail_keys": make(map[string]interface{}), + "metric_name_id_to_label_ids": make(map[int][]int), } - for item := range tempCache.MetricLabel.labelCache.keys.Iterator().C { - temp["label_cache"].(map[string]interface{})["keys"].(map[string]interface{})[marshal(item)] = struct{}{} - } - tempCache.MetricLabel.labelCache.idToKey.Range(func(key, value any) bool { - temp["label_cache"].(map[string]interface{})["id_to_key"].(map[int]string)[key.(int)] = marshal(value) + + tempCache.MetricLabel.metricNameIDToLabelIDs.Range(func(i int, s mapset.Set[int]) bool { + temp["metric_name_id_to_label_ids"].(map[int][]int)[i] = s.ToSlice() return true }) - for k, v := range tempCache.MetricLabel.metricNameToLabelIDs { - temp["metric_name_to_label_ids"].(map[string][]int)[k] = v - } - for item := range tempCache.MetricLabel.metricLabelDetailKeys.Iterator().C { - temp["metric_label_detail_keys"].(map[string]interface{})[marshal(item)] = struct{}{} - } - if len(temp["label_cache"].(map[string]interface{})["keys"].(map[string]interface{})) > 0 || - len(temp["label_cache"].(map[string]interface{})["id_to_key"].(map[int]string)) > 0 || - len(temp["metric_name_to_label_ids"].(map[string][]int)) > 0 || - len(temp["metric_label_detail_keys"].(map[string]interface{})) > 0 { + + if len(temp["metric_name_id_to_label_ids"].(map[int][]int)) > 0 { content["metric_label"] = temp } } diff --git a/server/controller/prometheus/cache/label.go b/server/controller/prometheus/cache/label.go index fd846401acc..9ba21e2c821 100644 --- a/server/controller/prometheus/cache/label.go +++ b/server/controller/prometheus/cache/label.go @@ -19,8 +19,6 @@ package cache import ( "sync" - mapset "github.com/deckarep/golang-set/v2" - "github.com/deepflowio/deepflow/message/controller" "github.com/deepflowio/deepflow/server/controller/db/mysql" ) @@ -38,18 +36,19 @@ func NewLabelKey(name, value string) LabelKey { } type label struct { - keys mapset.Set[LabelKey] idToKey sync.Map + keyToID sync.Map } func newLabel() *label { - return &label{ - keys: mapset.NewSet[LabelKey](), - } + return &label{} } -func (l *label) IfKeyExists(key LabelKey) bool { - return l.keys.Contains(key) +func (l *label) GetIDByKey(key LabelKey) (int, bool) { + if item, ok := l.keyToID.Load(key); ok { + return item.(int), true + } + return 0, false } func (l *label) GetKeyByID(id int) (LabelKey, bool) { @@ -61,8 +60,9 @@ func (l *label) GetKeyByID(id int) (LabelKey, bool) { func (l *label) Add(batch []*controller.PrometheusLabel) { for _, item := range batch { - l.keys.Add(NewLabelKey(item.GetName(), item.GetValue())) - l.idToKey.Store(int(item.GetId()), NewLabelKey(item.GetName(), item.GetValue())) + k := NewLabelKey(item.GetName(), item.GetValue()) + l.keyToID.Store(k, int(item.GetId())) + l.idToKey.Store(int(item.GetId()), k) } } @@ -72,8 +72,9 @@ func (l *label) refresh(args ...interface{}) error { return err } for _, item := range ls { - l.keys.Add(NewLabelKey(item.Name, item.Value)) - l.idToKey.Store(item.ID, NewLabelKey(item.Name, item.Value)) + k := NewLabelKey(item.Name, item.Value) + l.keyToID.Store(k, item.ID) + l.idToKey.Store(item.ID, k) } return nil } diff --git a/server/controller/prometheus/cache/metric_label.go b/server/controller/prometheus/cache/metric_label.go index 37a2400aca3..1d9507e995e 100644 --- a/server/controller/prometheus/cache/metric_label.go +++ b/server/controller/prometheus/cache/metric_label.go @@ -17,63 +17,59 @@ package cache import ( + "github.com/cornelk/hashmap" mapset "github.com/deckarep/golang-set/v2" + "github.com/deepflowio/deepflow/message/controller" "github.com/deepflowio/deepflow/server/controller/db/mysql" ) -type MetricLabelDetailKey struct { - MetricName string - LabelName string - LabelValue string -} - -func NewMetricLabelDetailKey(metricName, labelName, labelValue string) MetricLabelDetailKey { - return MetricLabelDetailKey{ - MetricName: metricName, - LabelName: labelName, - LabelValue: labelValue, - } -} - type metricLabel struct { - labelCache *label - metricLabelDetailKeys mapset.Set[MetricLabelDetailKey] // for metric_label check - metricNameToLabelIDs map[string][]int // only for fully assembled + metricNameCache *metricName + labelCache *label + + metricNameIDToLabelIDs *hashmap.Map[int, mapset.Set[int]] } -func newMetricLabel(l *label) *metricLabel { +func newMetricLabel(mn *metricName, l *label) *metricLabel { return &metricLabel{ - labelCache: l, - metricLabelDetailKeys: mapset.NewSet[MetricLabelDetailKey](), - metricNameToLabelIDs: make(map[string][]int), + metricNameCache: mn, + labelCache: l, + + metricNameIDToLabelIDs: hashmap.New[int, mapset.Set[int]](), } } -func (ml *metricLabel) IfKeyExists(k MetricLabelDetailKey) bool { - return ml.metricLabelDetailKeys.Contains(k) +func (ml *metricLabel) IfLinked(metricID, labelID int) bool { + if labelIDs, ok := ml.metricNameIDToLabelIDs.Get(metricID); ok { + return labelIDs.(mapset.Set[int]).Contains(labelID) + } + return false } -func (ml *metricLabel) GetLabelsByMetricName(metricName string) []LabelKey { - var ret []LabelKey - if labelIDs, ok := ml.metricNameToLabelIDs[metricName]; ok { - for _, labelID := range labelIDs { - if labelKey, ok := ml.labelCache.GetKeyByID(labelID); ok { - ret = append(ret, labelKey) - } - } +func (ml *metricLabel) GetLabelsByMetricName(metricName string) []int { + mni, ok := ml.metricNameCache.GetIDByName(metricName) + if !ok { + log.Debugf("metric_name: %s id not found", metricName) + return nil + } + if labelIDs, ok := ml.metricNameIDToLabelIDs.Get(mni); ok { + return labelIDs.ToSlice() } - return ret + log.Debugf("metric_name: %s label_ids not found", metricName) + return []int{} } -func (ml *metricLabel) Add(batch []MetricLabelDetailKey) { - for _, item := range batch { - ml.metricLabelDetailKeys.Add(item) - } +func (mi *metricLabel) GetMetricNameIDToLabelIDs() *hashmap.Map[int, mapset.Set[int]] { + return mi.metricNameIDToLabelIDs } -func (ml *metricLabel) GetMetricLabelDetailKeys() mapset.Set[MetricLabelDetailKey] { - return ml.metricLabelDetailKeys +func (ml *metricLabel) Add(batch []*controller.PrometheusMetricLabel) { + for _, item := range batch { + for _, li := range item.GetLabelIds() { + ml.metricNameIDToLabelIDs.GetOrInsert(int(item.GetMetricNameId()), mapset.NewSet(int(li))) + } + } } func (ml *metricLabel) refresh(args ...interface{}) error { @@ -81,21 +77,16 @@ func (ml *metricLabel) refresh(args ...interface{}) error { if err != nil { return err } - metricNameToLabelIDs := make(map[string][]int) for _, item := range metricLabels { - if lk, ok := ml.labelCache.GetKeyByID(item.LabelID); ok { - ml.metricLabelDetailKeys.Add(NewMetricLabelDetailKey(item.MetricName, lk.Name, lk.Value)) - } - if _, ok := ml.labelCache.GetKeyByID(item.LabelID); ok { - metricNameToLabelIDs[item.MetricName] = append(metricNameToLabelIDs[item.MetricName], item.LabelID) + if mni, ok := ml.metricNameCache.GetIDByName(item.MetricName); ok { + ml.metricNameIDToLabelIDs.GetOrInsert(mni, mapset.NewSet(item.LabelID)) } } - ml.metricNameToLabelIDs = metricNameToLabelIDs return nil } func (ml *metricLabel) load() ([]*mysql.PrometheusMetricLabel, error) { var metricLabels []*mysql.PrometheusMetricLabel - err := mysql.Db.Find(&metricLabels).Error + err := mysql.Db.Select("metric_name", "label_id").Find(&metricLabels).Error return metricLabels, err } diff --git a/server/controller/prometheus/cache/metric_name.go b/server/controller/prometheus/cache/metric_name.go index c7239d5e4e1..6f0e883983f 100644 --- a/server/controller/prometheus/cache/metric_name.go +++ b/server/controller/prometheus/cache/metric_name.go @@ -25,6 +25,7 @@ import ( type metricName struct { nameToID sync.Map + idToName sync.Map } func (mn *metricName) Get() *sync.Map { @@ -38,9 +39,17 @@ func (mn *metricName) GetIDByName(n string) (int, bool) { return 0, false } +func (mn *metricName) GetNameByID(id int) (string, bool) { + if name, ok := mn.idToName.Load(id); ok { + return name.(string), true + } + return "", false +} + func (mn *metricName) Add(batch []*controller.PrometheusMetricName) { for _, item := range batch { mn.nameToID.Store(item.GetName(), int(item.GetId())) + mn.idToName.Store(int(item.GetId()), item.GetName()) } } @@ -51,6 +60,7 @@ func (mn *metricName) refresh(args ...interface{}) error { } for _, item := range metricNames { mn.nameToID.Store(item.Name, item.ID) + mn.idToName.Store(item.ID, item.Name) } return nil } diff --git a/server/controller/prometheus/encoder/encoder.go b/server/controller/prometheus/encoder/encoder.go index 71af88163bb..26ba3482b31 100644 --- a/server/controller/prometheus/encoder/encoder.go +++ b/server/controller/prometheus/encoder/encoder.go @@ -71,7 +71,7 @@ func (e *Encoder) Init(ctx context.Context, cfg *prometheuscfg.Config) { e.labelValue = newLabelValue(cfg.ResourceMaxID1) e.label = newLabel() e.LabelLayout = newLabelLayout(cfg) - e.metricLabel = newMetricLabel(e.label) + e.metricLabel = newMetricLabel(e.metricName, e.label) e.target = newTarget(cfg.ResourceMaxID1) e.metricTarget = newMetricTarget(e.target) e.refreshInterval = time.Duration(cfg.EncoderCacheRefreshInterval) * time.Second @@ -143,7 +143,7 @@ func (e *Encoder) Encode(req *controller.SyncPrometheusRequest) (*controller.Syn AppendErrGroup(eg, e.encodeMetricName, resp, req.GetMetricNames()) AppendErrGroup(eg, e.encodeLabelName, resp, req.GetLabelNames()) AppendErrGroup(eg, e.encodeLabelValue, resp, req.GetLabelValues()) - AppendErrGroup(eg, e.encodeMetricLabel, req.GetMetricLabels()) + AppendErrGroup(eg, e.encodeMetricLabel, resp, req.GetMetricLabels()) AppendErrGroup(eg, e.encodeMetricTarget, resp, req.GetMetricTargets()) err = eg.Wait() return resp, err @@ -205,11 +205,13 @@ func (e *Encoder) encodeLabel(args ...interface{}) error { } func (e *Encoder) encodeMetricLabel(args ...interface{}) error { - mls := args[0].([]*controller.PrometheusMetricLabelRequest) - err := e.metricLabel.encode(mls) + resp := args[0].(*controller.SyncPrometheusResponse) + metricLabels := args[1].([]*controller.PrometheusMetricLabelRequest) + mls, err := e.metricLabel.encode(metricLabels) if err != nil { return err } + resp.MetricLabels = mls return nil } diff --git a/server/controller/prometheus/encoder/metric_label.go b/server/controller/prometheus/encoder/metric_label.go index 898e7ff2ebc..171d70fb4e7 100644 --- a/server/controller/prometheus/encoder/metric_label.go +++ b/server/controller/prometheus/encoder/metric_label.go @@ -20,30 +20,47 @@ import ( "sync" mapset "github.com/deckarep/golang-set/v2" + "github.com/golang/protobuf/proto" "github.com/deepflowio/deepflow/message/controller" "github.com/deepflowio/deepflow/server/controller/db/mysql" "github.com/deepflowio/deepflow/server/controller/prometheus/cache" ) +type metricLabelKey struct { + MetricNameID int + LabelID int +} + +func newMetricLabelKey(metricNameID, labelID int) metricLabelKey { + return metricLabelKey{ + MetricNameID: metricNameID, + LabelID: labelID, + } +} + type metricLabel struct { - lock sync.Mutex - resourceType string - labelEncoder *label - metricLabelDetailKeys mapset.Set[cache.MetricLabelDetailKey] + lock sync.Mutex + resourceType string + + metricNameEncoder *metricName + labelEncoder *label + + metricLabelKeys mapset.Set[metricLabelKey] } -func newMetricLabel(l *label) *metricLabel { +func newMetricLabel(mn *metricName, l *label) *metricLabel { return &metricLabel{ - resourceType: "metric_label", - labelEncoder: l, - metricLabelDetailKeys: mapset.NewSet[cache.MetricLabelDetailKey](), + resourceType: "metric_label", + metricNameEncoder: mn, + labelEncoder: l, + metricLabelKeys: mapset.NewSet[metricLabelKey](), } } func (ml *metricLabel) store(item *mysql.PrometheusMetricLabel) { - if labelKey, ok := ml.labelEncoder.getKey(item.LabelID); ok { - ml.metricLabelDetailKeys.Add(cache.NewMetricLabelDetailKey(item.MetricName, labelKey.Name, labelKey.Value)) + if mni, ok := ml.metricNameEncoder.getID(item.MetricName); ok { + ml.metricLabelKeys.Add(newMetricLabelKey(mni, item.LabelID)) } } @@ -59,36 +76,60 @@ func (ml *metricLabel) refresh(args ...interface{}) error { return nil } -func (ml *metricLabel) encode(rMLs []*controller.PrometheusMetricLabelRequest) error { +func (ml *metricLabel) encode(rMLs []*controller.PrometheusMetricLabelRequest) ([]*controller.PrometheusMetricLabel, error) { ml.lock.Lock() defer ml.lock.Unlock() + resp := make([]*controller.PrometheusMetricLabel, 0) var dbToAdd []*mysql.PrometheusMetricLabel + respToAdd := make([]*controller.PrometheusMetricLabel, 0) for _, rML := range rMLs { mn := rML.GetMetricName() + mni, ok := ml.metricNameEncoder.getID(mn) + if !ok { + log.Warningf("%s metric_name: %s id not found", ml.resourceType, mn) + continue + } + lis := make([]uint32, 0) + lisToAdd := make([]uint32, 0) for _, l := range rML.GetLabels() { ln := l.GetName() lv := l.GetValue() - if ok := ml.metricLabelDetailKeys.Contains(cache.NewMetricLabelDetailKey(mn, ln, lv)); ok { + li, ok := ml.labelEncoder.getID(cache.NewLabelKey(ln, lv)) + if !ok { + log.Warningf("%s label (name: %s, value: %s) id not found", ml.resourceType, ln, lv) continue } - if li, ok := ml.labelEncoder.getID(cache.NewLabelKey(ln, lv)); ok { - dbToAdd = append(dbToAdd, &mysql.PrometheusMetricLabel{ - MetricName: mn, - LabelID: li, - }) + if ok := ml.metricLabelKeys.Contains(newMetricLabelKey(mni, li)); ok { + lis = append(lis, uint32(li)) continue } - log.Warningf("%s label_id (name: %s, value: %s) not found", ml.resourceType, ln, lv) + dbToAdd = append(dbToAdd, &mysql.PrometheusMetricLabel{ + MetricName: mn, + LabelID: li, + }) + lisToAdd = append(lisToAdd, uint32(li)) + } + if len(lis) != 0 { + resp = append(resp, &controller.PrometheusMetricLabel{ + MetricNameId: proto.Uint32(uint32(mni)), + LabelIds: lis, + }) + } + if len(lisToAdd) != 0 { + respToAdd = append(respToAdd, &controller.PrometheusMetricLabel{ + MetricNameId: proto.Uint32(uint32(mni)), + LabelIds: lisToAdd, + }) } } err := addBatch(dbToAdd, ml.resourceType) if err != nil { log.Errorf("add %s error: %s", ml.resourceType, err.Error()) - return err + return resp, err } for _, item := range dbToAdd { ml.store(item) } - return nil + return append(resp, respToAdd...), nil } diff --git a/server/controller/prometheus/encoder/metric_name.go b/server/controller/prometheus/encoder/metric_name.go index 121c6446279..12fa376bfec 100644 --- a/server/controller/prometheus/encoder/metric_name.go +++ b/server/controller/prometheus/encoder/metric_name.go @@ -19,6 +19,7 @@ package encoder import ( "sync" + "github.com/cornelk/hashmap" mapset "github.com/deckarep/golang-set/v2" "github.com/golang/protobuf/proto" @@ -30,20 +31,24 @@ import ( type metricName struct { lock sync.Mutex resourceType string - strToID map[string]int + strToID *hashmap.Map[string, int] ascIDAllocator } func newMetricName(max int) *metricName { mn := &metricName{ resourceType: "metric_name", - strToID: make(map[string]int), + strToID: hashmap.New[string, int](), } mn.ascIDAllocator = newAscIDAllocator(mn.resourceType, 1, max) mn.rawDataProvider = mn return mn } +func (mn *metricName) getID(str string) (int, bool) { + return mn.strToID.Get(str) +} + func (mn *metricName) refresh(args ...interface{}) error { mn.lock.Lock() defer mn.lock.Unlock() @@ -59,7 +64,7 @@ func (mn *metricName) encode(strs []string) ([]*controller.PrometheusMetricName, dbToAdd := make([]*mysql.PrometheusMetricName, 0) for i := range strs { str := strs[i] - if id, ok := mn.strToID[str]; ok { + if id, ok := mn.strToID.Get(str); ok { resp = append(resp, &controller.PrometheusMetricName{Name: &str, Id: proto.Uint32(uint32(id))}) continue } @@ -83,7 +88,7 @@ func (mn *metricName) encode(strs []string) ([]*controller.PrometheusMetricName, for i := range dbToAdd { id := dbToAdd[i].ID str := dbToAdd[i].Name - mn.strToID[str] = id + mn.strToID.Set(str, id) resp = append(resp, &controller.PrometheusMetricName{Name: &str, Id: proto.Uint32(uint32(id))}) } return resp, nil @@ -99,7 +104,7 @@ func (mn *metricName) load() (ids mapset.Set[int], err error) { inUseIDsSet := mapset.NewSet[int]() for _, item := range items { inUseIDsSet.Add(item.ID) - mn.strToID[item.Name] = item.ID + mn.strToID.Set(item.Name, item.ID) } return inUseIDsSet, nil } diff --git a/server/controller/prometheus/label.go b/server/controller/prometheus/label.go index 124503586e0..f7920a83a78 100644 --- a/server/controller/prometheus/label.go +++ b/server/controller/prometheus/label.go @@ -100,7 +100,7 @@ func (s *LabelSynchronizer) prepare(req *trident.PrometheusLabelRequest) error { AppendErrGroup(eg, s.addLabelValueCache, syncResp.GetLabelValues()) AppendErrGroup(eg, s.addMetricAPPLabelLayoutCache, syncResp.GetMetricAppLabelLayouts()) AppendErrGroup(eg, s.addLabelCache, syncResp.GetLabels()) - AppendErrGroup(eg, s.addMetricLabelCache, toEncode.metricToMetricLabels) + AppendErrGroup(eg, s.addMetricLabelCache, syncResp.GetMetricLabels()) AppendErrGroup(eg, s.addMetricTargetCache, syncResp.GetMetricTargets()) AppendErrGroup(eg, s.addTargetCache, syncResp.GetTargets()) return eg.Wait() @@ -170,7 +170,7 @@ func (s *LabelSynchronizer) generateSyncRequest(toEncode *dataToEncode) *control return res }(toEncode.labels.ToSlice()), - MetricLabels: func(m map[string]mapset.Set[cache.MetricLabelDetailKey]) []*controller.PrometheusMetricLabelRequest { + MetricLabels: func(m map[string]mapset.Set[cache.LabelKey]) []*controller.PrometheusMetricLabelRequest { res := make([]*controller.PrometheusMetricLabelRequest, 0, len(m)) for mn, lks := range m { rmn := mn @@ -178,8 +178,8 @@ func (s *LabelSynchronizer) generateSyncRequest(toEncode *dataToEncode) *control lkl := lks.ToSlice() for i := range lkl { ls = append(ls, &controller.PrometheusLabelRequest{ - Name: &lkl[i].LabelName, - Value: &lkl[i].LabelValue, + Name: &lkl[i].Name, + Value: &lkl[i].Value, }) } res = append(res, &controller.PrometheusMetricLabelRequest{ @@ -188,7 +188,7 @@ func (s *LabelSynchronizer) generateSyncRequest(toEncode *dataToEncode) *control }) } return res - }(toEncode.metricToMetricLabels), + }(toEncode.metricNameToLabelKeys), MetricTargets: func(ks []cache.MetricTargetKey, iks map[string]mapset.Set[cache.TargetKey]) []*controller.PrometheusMetricTargetRequest { res := make([]*controller.PrometheusMetricTargetRequest, 0, len(ks)) @@ -408,10 +408,8 @@ func (s *LabelSynchronizer) addLabelCache(arg ...interface{}) error { } func (s *LabelSynchronizer) addMetricLabelCache(arg ...interface{}) error { - m := arg[0].(map[string]mapset.Set[cache.MetricLabelDetailKey]) - for _, ks := range m { - s.cache.MetricLabel.Add(ks.ToSlice()) - } + mls := arg[0].([]*controller.PrometheusMetricLabel) + s.cache.MetricLabel.Add(mls) return nil } @@ -435,7 +433,7 @@ type dataToEncode struct { labelValues mapset.Set[string] metricAPPLabelLayouts mapset.Set[cache.LayoutKey] labels mapset.Set[cache.LabelKey] - metricToMetricLabels map[string]mapset.Set[cache.MetricLabelDetailKey] + metricNameToLabelKeys map[string]mapset.Set[cache.LabelKey] metricTargets mapset.Set[cache.MetricTargetKey] metricToTargets map[string]mapset.Set[cache.TargetKey] targets mapset.Set[cache.TargetKey] @@ -450,7 +448,7 @@ func newDataToEncode() *dataToEncode { labelValues: mapset.NewSet[string](), metricAPPLabelLayouts: mapset.NewSet[cache.LayoutKey](), labels: mapset.NewSet[cache.LabelKey](), - metricToMetricLabels: make(map[string]mapset.Set[cache.MetricLabelDetailKey], 0), + metricNameToLabelKeys: make(map[string]mapset.Set[cache.LabelKey], 0), metricTargets: mapset.NewSet[cache.MetricTargetKey](), metricToTargets: make(map[string]mapset.Set[cache.TargetKey], 0), targets: mapset.NewSet[cache.TargetKey](), @@ -459,7 +457,7 @@ func newDataToEncode() *dataToEncode { func (d *dataToEncode) cardinality() int { return d.metricNames.Cardinality() + d.labelNames.Cardinality() + d.labelValues.Cardinality() + - d.metricAPPLabelLayouts.Cardinality() + d.labels.Cardinality() + len(d.metricToMetricLabels) + + d.metricAPPLabelLayouts.Cardinality() + d.labels.Cardinality() + len(d.metricNameToLabelKeys) + d.metricTargets.Cardinality() + len(d.metricToTargets) + d.targets.Cardinality() } @@ -496,19 +494,23 @@ func (d *dataToEncode) appendMetricAPPLabelLayout(metricName, labelName string) } func (d *dataToEncode) tryAppendLabel(name, value string) { - if ok := d.cache.Label.IfKeyExists(cache.NewLabelKey(name, value)); !ok { + if _, ok := d.cache.Label.GetIDByKey(cache.NewLabelKey(name, value)); !ok { d.labels.Add(cache.NewLabelKey(name, value)) } } func (d *dataToEncode) tryAppendMetricLabel(metricName, labelName, labelValue string) { - mlk := cache.NewMetricLabelDetailKey(metricName, labelName, labelValue) - if ok := d.cache.MetricLabel.IfKeyExists(mlk); !ok { - if _, ok := d.metricToMetricLabels[metricName]; !ok { - d.metricToMetricLabels[metricName] = mapset.NewSet[cache.MetricLabelDetailKey]() + if mi, ok := d.cache.MetricName.GetIDByName(metricName); ok { + if li, ok := d.cache.Label.GetIDByKey(cache.NewLabelKey(labelName, labelValue)); ok { + if ok := d.cache.MetricLabel.IfLinked(mi, li); ok { + return + } } - d.metricToMetricLabels[metricName].Add(mlk) } + if _, ok := d.metricNameToLabelKeys[metricName]; !ok { + d.metricNameToLabelKeys[metricName] = mapset.NewSet[cache.LabelKey]() + } + d.metricNameToLabelKeys[metricName].Add(cache.NewLabelKey(labelName, labelValue)) } func (d *dataToEncode) tryAppendMetricTarget(metricName string, targetID int) { diff --git a/server/controller/prometheus/synchronizer.go b/server/controller/prometheus/synchronizer.go index 0c3c71f8df6..ec7f08ffe7c 100644 --- a/server/controller/prometheus/synchronizer.go +++ b/server/controller/prometheus/synchronizer.go @@ -52,14 +52,20 @@ func (s *Synchronizer) assembleMetricLabelFully() ([]*trident.MetricLabelRespons var err error nonLabelNames := mapset.NewSet[string]() nonLabelValues := mapset.NewSet[string]() + nonLabelIDs := mapset.NewSet[int]() mLabels := make([]*trident.MetricLabelResponse, 0) s.cache.MetricName.Get().Range(func(k, v interface{}) bool { var labels []*trident.LabelResponse metricName := k.(string) metricID := v.(int) - labelKeys := s.cache.MetricLabel.GetLabelsByMetricName(metricName) - for i := range labelKeys { - lk := labelKeys[i] + labelIDs := s.cache.MetricLabel.GetLabelsByMetricName(metricName) + for i := range labelIDs { + li := labelIDs[i] + lk, ok := s.cache.Label.GetKeyByID(li) + if !ok { + nonLabelIDs.Add(li) + continue + } if slices.Contains([]string{TargetLabelInstance, TargetLabelJob}, lk.Name) { continue } @@ -98,6 +104,9 @@ func (s *Synchronizer) assembleMetricLabelFully() ([]*trident.MetricLabelRespons if nonLabelValues.Cardinality() > 0 { log.Warningf("label value id not found, values: %v", nonLabelValues.ToSlice()) } + if nonLabelIDs.Cardinality() > 0 { + log.Warningf("label id not found, ids: %v", nonLabelIDs.ToSlice()) + } return mLabels, err } diff --git a/server/controller/prometheus/updater.go b/server/controller/prometheus/updater.go index db24addd97b..7eb813411e4 100644 --- a/server/controller/prometheus/updater.go +++ b/server/controller/prometheus/updater.go @@ -174,12 +174,18 @@ func (td *toolData) load() error { td.layoutKeyToIndex[cache.NewLayoutKey(item.MetricName, item.APPLabelName)] = item.APPLabelColumnIndex } - metricLabelKeys := td.cache.MetricLabel.GetMetricLabelDetailKeys().ToSlice() - for _, item := range metricLabelKeys { - if _, ok := td.metricNameToLabelNames[item.MetricName]; !ok { - td.metricNameToLabelNames[item.MetricName] = mapset.NewSet[string]() + td.cache.MetricLabel.GetMetricNameIDToLabelIDs().Range(func(mni int, lis mapset.Set[int]) bool { + if mn, ok := td.cache.MetricName.GetNameByID(mni); ok { + for _, li := range lis.ToSlice() { + if lk, ok := td.cache.Label.GetKeyByID(li); ok { + if _, ok := td.metricNameToLabelNames[mn]; !ok { + td.metricNameToLabelNames[mn] = mapset.NewSet[string]() + } + td.metricNameToLabelNames[mn].Add(lk.Name) + } + } } - td.metricNameToLabelNames[item.MetricName].Add(item.LabelName) - } + return true + }) return nil }