diff --git a/src/models/busi_group.go b/src/models/busi_group.go index d275c0fbba8df99c61caf03c8fc0126e83d39d25..ef29ce4e93c22a66cb3ded2877bd4d19d8b8fb44 100644 --- a/src/models/busi_group.go +++ b/src/models/busi_group.go @@ -313,3 +313,15 @@ func BusiGroupAdd(name string, labelEnable int, labelValue string, members []Bus return nil }) } + +func BusiGroupStatistics() (*Statistics, error) { + session := DB().Model(&BusiGroup{}).Select("count(*) as total", "max(update_at) as last_updated") + + var stats []*Statistics + err := session.Find(&stats).Error + if err != nil { + return nil, err + } + + return stats[0], nil +} diff --git a/src/models/target.go b/src/models/target.go index 85ebc0c5e49eb7b6d96cdf7f9b3d3afe491c3d5c..5e94fd0c1f0e3d81071a937a1a3209aff5106abf 100644 --- a/src/models/target.go +++ b/src/models/target.go @@ -127,19 +127,6 @@ func TargetGetsByCluster(cluster string) ([]*Target, error) { var lst []*Target err := session.Find(&lst).Error - if err == nil { - bgcache, err := BusiGroupGetMap() - if err != nil { - return nil, err - } - - for i := 0; i < len(lst); i++ { - err = lst[i].FillGroup(bgcache) - if err != nil { - return nil, err - } - } - } return lst, err } diff --git a/src/server/memsto/busi_group_cache.go b/src/server/memsto/busi_group_cache.go new file mode 100644 index 0000000000000000000000000000000000000000..947baaa5fdbb6ff0d6e24856e74f34ccf0923d04 --- /dev/null +++ b/src/server/memsto/busi_group_cache.go @@ -0,0 +1,102 @@ +package memsto + +import ( + "fmt" + "sync" + "time" + + "github.com/pkg/errors" + "github.com/toolkits/pkg/logger" + + "github.com/didi/nightingale/v5/src/models" + "github.com/didi/nightingale/v5/src/server/config" + promstat "github.com/didi/nightingale/v5/src/server/stat" +) + +type BusiGroupCacheType struct { + statTotal int64 + statLastUpdated int64 + + sync.RWMutex + ugs map[int64]*models.BusiGroup // key: id +} + +var BusiGroupCache = BusiGroupCacheType{ + statTotal: -1, + statLastUpdated: -1, + ugs: make(map[int64]*models.BusiGroup), +} + +func (c *BusiGroupCacheType) StatChanged(total, lastUpdated int64) bool { + if c.statTotal == total && c.statLastUpdated == lastUpdated { + return false + } + + return true +} + +func (c *BusiGroupCacheType) Set(ugs map[int64]*models.BusiGroup, total, lastUpdated int64) { + c.Lock() + c.ugs = ugs + c.Unlock() + + // only one goroutine used, so no need lock + c.statTotal = total + c.statLastUpdated = lastUpdated +} + +func (c *BusiGroupCacheType) GetByBusiGroupId(id int64) *models.BusiGroup { + c.RLock() + defer c.RUnlock() + return c.ugs[id] +} + +func SyncBusiGroups() { + err := syncBusiGroups() + if err != nil { + fmt.Println("failed to sync busi groups:", err) + exit(1) + } + + go loopSyncBusiGroups() +} + +func loopSyncBusiGroups() { + duration := time.Duration(9000) * time.Millisecond + for { + time.Sleep(duration) + if err := syncBusiGroups(); err != nil { + logger.Warning("failed to sync busi groups:", err) + } + } +} + +func syncBusiGroups() error { + start := time.Now() + + stat, err := models.BusiGroupStatistics() + if err != nil { + return errors.WithMessage(err, "failed to exec BusiGroupStatistics") + } + + if !BusiGroupCache.StatChanged(stat.Total, stat.LastUpdated) { + promstat.GaugeCronDuration.WithLabelValues(config.C.ClusterName, "sync_busi_groups").Set(0) + promstat.GaugeSyncNumber.WithLabelValues(config.C.ClusterName, "sync_busi_groups").Set(0) + logger.Debug("busi_group not changed") + return nil + } + + m, err := models.BusiGroupGetMap() + if err != nil { + return errors.WithMessage(err, "failed to exec BusiGroupGetMap") + } + + BusiGroupCache.Set(m, stat.Total, stat.LastUpdated) + + ms := time.Since(start).Milliseconds() + promstat.GaugeCronDuration.WithLabelValues(config.C.ClusterName, "sync_busi_groups").Set(float64(ms)) + promstat.GaugeSyncNumber.WithLabelValues(config.C.ClusterName, "sync_busi_groups").Set(float64(len(m))) + logger.Infof("timer: sync busi groups done, cost: %dms, number: %d", ms, len(m)) + + return nil +} diff --git a/src/server/memsto/memsto.go b/src/server/memsto/memsto.go index 22eaf97cbcfa5a6fe67bb79d7d2b4e48dcac7bc4..ade3e744854ebb66cd21e185b1af89f37b32409d 100644 --- a/src/server/memsto/memsto.go +++ b/src/server/memsto/memsto.go @@ -12,10 +12,11 @@ func exit(code int) { } func Sync() { - SyncTargets() + SyncBusiGroups() SyncUsers() SyncUserGroups() SyncAlertMutes() SyncAlertSubscribes() SyncAlertRules() + SyncTargets() } diff --git a/src/server/memsto/target_cache.go b/src/server/memsto/target_cache.go index e8eb63abefede062c19120d3c8f259009ecb87e5..57f2278b5ff460bd64080bacc0106a15f7ebe1fc 100644 --- a/src/server/memsto/target_cache.go +++ b/src/server/memsto/target_cache.go @@ -125,8 +125,15 @@ func syncTargets() error { // handle BusiGroup's LabelValue // BusiGroup的LabelValue就相当于一个特殊的标签来对待 - if lst[i].GroupObj != nil && lst[i].GroupObj.LabelEnable == 1 { - lst[i].TagsMap["busigroup"] = lst[i].GroupObj.LabelValue + if lst[i].GroupId > 0 { + bg := BusiGroupCache.GetByBusiGroupId(lst[i].GroupId) + if bg == nil { + return errors.New("busi group cache not ready") + } + + if bg.LabelEnable == 1 { + lst[i].TagsMap["busigroup"] = bg.LabelValue + } } m[lst[i].Ident] = lst[i]