主机找到主机所在组 根据组查找组的模板 根据模板(有继承关系)找到策略 并且合并策略
模本跟组绑定,不直接和主机绑定
//rpc接口 这个接口用来获取主机对应的所有策略
func (t *Hbs) GetStrategies(req model.NullRpcRequest, reply *model.StrategiesResponse) error {
reply.HostStrategies = []*model.HostStrategy{}
// 一个机器ID对应多个模板ID
hidTids := cache.HostTemplateIds.GetMap()
sz := len(hidTids)
if sz == 0 {
return nil
}
// Judge需要的是hostname,此处要把HostId转换为hostname
// 查出的hosts,是不处于维护时间内的
hosts := cache.MonitoredHosts.Get()
if len(hosts) == 0 {
// 所有机器都处于维护状态,汗
return nil
}
tpls := cache.TemplateCache.GetMap()
if len(tpls) == 0 {
return nil
}
strategies := cache.Strategies.GetMap()
if len(strategies) == 0 {
return nil
}
// 做个索引,给一个tplId,可以很方便的找到对应了哪些Strategy
tpl2Strategies := Tpl2Strategies(strategies)
hostStrategies := make([]*model.HostStrategy, 0, sz)
for hostId, tplIds := range hidTids {
h, exists := hosts[hostId]
if !exists {
continue
}
// 计算当前host配置了哪些监控策略
ss := CalcInheritStrategies(tpls, tplIds, tpl2Strategies)
if len(ss) <= 0 {
continue
}
hs := model.HostStrategy{
Hostname: h.Name,
Strategies: ss,
}
hostStrategies = append(hostStrategies, &hs)
}
reply.HostStrategies = hostStrategies
return nil
}
计算每个主机的模板,由于模板有继承关系,需要做合并
(最早建的模板) (最新建的模板)
A B C D
(SA,SE) (SC(metric+tag和SA相同),SH)
A的SA和SC要合并
E F
func CalcInheritStrategies(allTpls map[int]*model.Template, tids []int, tpl2Strategies map[int][]*model.Strategy) []model.Strategy {
// 根据模板的继承关系,找到每个机器对应的模板全量
/**
* host_id =>
* |a |d |a |a |a |
* | | |b |b |f |
* | | | |c | |
* | | | | | |
*/
tpl_buckets := [][]int{}
for _, tid := range tids {
ids := cache.ParentIds(allTpls, tid)
if len(ids) <= 0 {
continue
}
tpl_buckets = append(tpl_buckets, ids)
}
// 每个host 关联的模板,有继承关系的放到同一个bucket中,其他的放在各自单独的bucket中
/**
* host_id =>
* |a |d |a |
* |b | |f |
* |c | | |
* | | | |
*/
count := len(tpl_buckets)
uniq_tpl_buckets := [][]int{}
for i := 0; i < count; i++ {
var valid bool = true
for j := 0; j < count; j++ {
if i == j {
continue
}
if slice_int_eq(tpl_buckets[i], tpl_buckets[j]) {
break
}
if slice_int_lt(tpl_buckets[i], tpl_buckets[j]) {
valid = false
break
}
}
if valid {
uniq_tpl_buckets = append(uniq_tpl_buckets, tpl_buckets[i])
}
}
// 继承覆盖父模板策略,得到每个模板聚合后的策略列表
strategies := []model.Strategy{}
exists_by_id := make(map[int]struct{})
for _, bucket := range uniq_tpl_buckets {
// 开始计算一个桶,先计算老的tid,再计算新的,所以可以覆盖
// 该桶最终结果
bucket_stras_map := make(map[string][]*model.Strategy)
for _, tid := range bucket {
// 一个tid对应的策略列表
the_tid_stras := make(map[string][]*model.Strategy)
if stras, ok := tpl2Strategies[tid]; ok {
for _, s := range stras {
uuid := fmt.Sprintf("metric:%s/tags:%v", s.Metric, utils.SortedTags(s.Tags))
if _, ok2 := the_tid_stras[uuid]; ok2 {
the_tid_stras[uuid] = append(the_tid_stras[uuid], s)
} else {
the_tid_stras[uuid] = []*model.Strategy{s}
}
}
}
// 覆盖父模板
for uuid, ss := range the_tid_stras {
bucket_stras_map[uuid] = ss
}
}
last_tid := bucket[len(bucket)-1]
// 替换所有策略的模板为最年轻的模板
for _, ss := range bucket_stras_map {
for _, s := range ss {
valStrategy := *s
// exists_by_id[s.Id] 是根据策略ID去重,不太确定是否真的需要,不过加上肯定没问题
if _, exist := exists_by_id[valStrategy.Id]; !exist {
if valStrategy.Tpl.Id != last_tid {
valStrategy.Tpl = allTpls[last_tid]
}
strategies = append(strategies, valStrategy)
exists_by_id[valStrategy.Id] = struct{}{}
}
}
}
}
return strategies
}