* [feat(#984)] multiple cluster support * add stats ClusterAll handle
This commit is contained in:
parent
d508aef7e5
commit
9c69362650
|
@ -16,7 +16,7 @@ import (
|
||||||
type AlertRule struct {
|
type AlertRule struct {
|
||||||
Id int64 `json:"id" gorm:"primaryKey"`
|
Id int64 `json:"id" gorm:"primaryKey"`
|
||||||
GroupId int64 `json:"group_id"` // busi group id
|
GroupId int64 `json:"group_id"` // busi group id
|
||||||
Cluster string `json:"cluster"` // take effect by cluster
|
Cluster string `json:"cluster"` // take effect by clusters, seperated by space
|
||||||
Name string `json:"name"` // rule name
|
Name string `json:"name"` // rule name
|
||||||
Note string `json:"note"` // will sent in notify
|
Note string `json:"note"` // will sent in notify
|
||||||
Prod string `json:"prod"` // product empty means n9e
|
Prod string `json:"prod"` // product empty means n9e
|
||||||
|
@ -124,7 +124,7 @@ func (ar *AlertRule) Add() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
exists, err := AlertRuleExists("group_id=? and cluster=? and name=?", ar.GroupId, ar.Cluster, ar.Name)
|
exists, err := AlertRuleExists(0, ar.GroupId, ar.Cluster, ar.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@ func (ar *AlertRule) Add() error {
|
||||||
|
|
||||||
func (ar *AlertRule) Update(arf AlertRule) error {
|
func (ar *AlertRule) Update(arf AlertRule) error {
|
||||||
if ar.Name != arf.Name {
|
if ar.Name != arf.Name {
|
||||||
exists, err := AlertRuleExists("group_id=? and cluster=? and name=? and id <> ?", ar.GroupId, ar.Cluster, arf.Name, ar.Id)
|
exists, err := AlertRuleExists(ar.Id, ar.GroupId, ar.Cluster, arf.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -262,8 +262,25 @@ func AlertRuleDels(ids []int64, bgid ...int64) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func AlertRuleExists(where string, args ...interface{}) (bool, error) {
|
func AlertRuleExists(id, groupId int64, cluster, name string) (bool, error) {
|
||||||
return Exists(DB().Model(&AlertRule{}).Where(where, args...))
|
session := DB().Where("id <> ? and group_id = ? and name = ?", id, groupId, name)
|
||||||
|
|
||||||
|
var lst []AlertRule
|
||||||
|
err := session.Find(&lst).Error
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if len(lst) == 0 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// match cluster
|
||||||
|
for _, r := range lst {
|
||||||
|
if MatchCluster(r.Cluster, cluster) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func AlertRuleGets(groupId int64) ([]AlertRule, error) {
|
func AlertRuleGets(groupId int64) ([]AlertRule, error) {
|
||||||
|
@ -284,18 +301,35 @@ func AlertRuleGetsByCluster(cluster string) ([]*AlertRule, error) {
|
||||||
session := DB().Where("disabled = ? and prod = ?", 0, "")
|
session := DB().Where("disabled = ? and prod = ?", 0, "")
|
||||||
|
|
||||||
if cluster != "" {
|
if cluster != "" {
|
||||||
session = session.Where("cluster = ?", cluster)
|
session = session.Where("(cluster like ? or cluster like ?)", "%"+cluster+"%", "%"+ClusterAll+"%")
|
||||||
}
|
}
|
||||||
|
|
||||||
var lst []*AlertRule
|
var lst []*AlertRule
|
||||||
err := session.Find(&lst).Error
|
err := session.Find(&lst).Error
|
||||||
if err == nil {
|
if err != nil {
|
||||||
|
return lst, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(lst) == 0 {
|
||||||
|
return lst, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if cluster == "" {
|
||||||
for i := 0; i < len(lst); i++ {
|
for i := 0; i < len(lst); i++ {
|
||||||
lst[i].DB2FE()
|
lst[i].DB2FE()
|
||||||
}
|
}
|
||||||
|
return lst, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return lst, err
|
lr := make([]*AlertRule, 0, len(lst))
|
||||||
|
for _, r := range lst {
|
||||||
|
if MatchCluster(r.Cluster, cluster) {
|
||||||
|
r.DB2FE()
|
||||||
|
lr = append(lr, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func AlertRulesGetsBy(prods []string, query string) ([]*AlertRule, error) {
|
func AlertRulesGetsBy(prods []string, query string) ([]*AlertRule, error) {
|
||||||
|
@ -358,7 +392,8 @@ func AlertRuleStatistics(cluster string) (*Statistics, error) {
|
||||||
session := DB().Model(&AlertRule{}).Select("count(*) as total", "max(update_at) as last_updated").Where("disabled = ? and prod = ?", 0, "")
|
session := DB().Model(&AlertRule{}).Select("count(*) as total", "max(update_at) as last_updated").Where("disabled = ? and prod = ?", 0, "")
|
||||||
|
|
||||||
if cluster != "" {
|
if cluster != "" {
|
||||||
session = session.Where("cluster = ?", cluster)
|
// 简略的判断,当一个clustername是另一个clustername的substring的时候,会出现stats与预期不符,不影响使用
|
||||||
|
session = session.Where("(cluster like ? or cluster like ?)", "%"+cluster+"%", "%"+ClusterAll+"%")
|
||||||
}
|
}
|
||||||
|
|
||||||
var stats []*Statistics
|
var stats []*Statistics
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/toolkits/pkg/str"
|
"github.com/toolkits/pkg/str"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
@ -9,6 +11,9 @@ import (
|
||||||
|
|
||||||
const AdminRole = "Admin"
|
const AdminRole = "Admin"
|
||||||
|
|
||||||
|
// if rule's cluster field contains `ClusterAll`, means it take effect in all clusters
|
||||||
|
const ClusterAll = "$all"
|
||||||
|
|
||||||
func DB() *gorm.DB {
|
func DB() *gorm.DB {
|
||||||
return storage.DB
|
return storage.DB
|
||||||
}
|
}
|
||||||
|
@ -42,3 +47,16 @@ type Statistics struct {
|
||||||
Total int64 `gorm:"total"`
|
Total int64 `gorm:"total"`
|
||||||
LastUpdated int64 `gorm:"last_updated"`
|
LastUpdated int64 `gorm:"last_updated"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MatchCluster(ruleCluster, targetCluster string) bool {
|
||||||
|
if targetCluster == ClusterAll {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
clusters := strings.Fields(ruleCluster)
|
||||||
|
for _, c := range clusters {
|
||||||
|
if c == ClusterAll || c == targetCluster {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
type RecordingRule struct {
|
type RecordingRule struct {
|
||||||
Id int64 `json:"id" gorm:"primaryKey"`
|
Id int64 `json:"id" gorm:"primaryKey"`
|
||||||
GroupId int64 `json:"group_id"` // busi group id
|
GroupId int64 `json:"group_id"` // busi group id
|
||||||
Cluster string `json:"cluster"` // take effect by cluster
|
Cluster string `json:"cluster"` // take effect by cluster, seperated by space
|
||||||
Name string `json:"name"` // new metric name
|
Name string `json:"name"` // new metric name
|
||||||
Note string `json:"note"` // note
|
Note string `json:"note"` // note
|
||||||
Disabled int `json:"disabled"` // 0: enabled, 1: disabled
|
Disabled int `json:"disabled"` // 0: enabled, 1: disabled
|
||||||
|
@ -40,6 +40,7 @@ func (re *RecordingRule) DB2FE() {
|
||||||
//re.ClusterJSON = strings.Fields(re.Cluster)
|
//re.ClusterJSON = strings.Fields(re.Cluster)
|
||||||
re.AppendTagsJSON = strings.Fields(re.AppendTags)
|
re.AppendTagsJSON = strings.Fields(re.AppendTags)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (re *RecordingRule) Verify() error {
|
func (re *RecordingRule) Verify() error {
|
||||||
if re.GroupId < 0 {
|
if re.GroupId < 0 {
|
||||||
return fmt.Errorf("GroupId(%d) invalid", re.GroupId)
|
return fmt.Errorf("GroupId(%d) invalid", re.GroupId)
|
||||||
|
@ -78,7 +79,7 @@ func (re *RecordingRule) Add() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
exists, err := RecordingRuleExists("group_id=? and cluster=? and name=?", re.GroupId, re.Cluster, re.Name)
|
exists, err := RecordingRuleExists(0, re.GroupId, re.Cluster, re.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -96,7 +97,7 @@ func (re *RecordingRule) Add() error {
|
||||||
|
|
||||||
func (re *RecordingRule) Update(ref RecordingRule) error {
|
func (re *RecordingRule) Update(ref RecordingRule) error {
|
||||||
if re.Name != ref.Name {
|
if re.Name != ref.Name {
|
||||||
exists, err := RecordingRuleExists("group_id=? and cluster=? and name=? and id <> ?", re.GroupId, re.Cluster, ref.Name, re.Id)
|
exists, err := RecordingRuleExists(re.Id, re.GroupId, re.Cluster, ref.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -133,9 +134,27 @@ func RecordingRuleDels(ids []int64, groupId int64) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RecordingRuleExists(where string, regs ...interface{}) (bool, error) {
|
func RecordingRuleExists(id, groupId int64, cluster, name string) (bool, error) {
|
||||||
return Exists(DB().Model(&RecordingRule{}).Where(where, regs...))
|
session := DB().Where("id <> ? and group_id = ? and name =? ", id, groupId, name)
|
||||||
|
|
||||||
|
var lst []RecordingRule
|
||||||
|
err := session.Find(&lst).Error
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if len(lst) == 0 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// match cluster
|
||||||
|
for _, r := range lst {
|
||||||
|
if MatchCluster(r.Cluster, cluster) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RecordingRuleGets(groupId int64) ([]RecordingRule, error) {
|
func RecordingRuleGets(groupId int64) ([]RecordingRule, error) {
|
||||||
session := DB().Where("group_id=?", groupId).Order("name")
|
session := DB().Where("group_id=?", groupId).Order("name")
|
||||||
|
|
||||||
|
@ -171,26 +190,45 @@ func RecordingRuleGetById(id int64) (*RecordingRule, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func RecordingRuleGetsByCluster(cluster string) ([]*RecordingRule, error) {
|
func RecordingRuleGetsByCluster(cluster string) ([]*RecordingRule, error) {
|
||||||
session := DB()
|
session := DB().Where("disabled = ? and prod = ?", 0, "")
|
||||||
|
|
||||||
if cluster != "" {
|
if cluster != "" {
|
||||||
session = session.Where("cluster = ?", cluster)
|
session = session.Where("(cluster like ? or cluster like ?)", "%"+cluster+"%", "%"+ClusterAll+"%")
|
||||||
}
|
}
|
||||||
|
|
||||||
var lst []*RecordingRule
|
var lst []*RecordingRule
|
||||||
err := session.Find(&lst).Error
|
err := session.Find(&lst).Error
|
||||||
if err == nil {
|
if err != nil {
|
||||||
|
return lst, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(lst) == 0 {
|
||||||
|
return lst, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if cluster == "" {
|
||||||
for i := 0; i < len(lst); i++ {
|
for i := 0; i < len(lst); i++ {
|
||||||
lst[i].DB2FE()
|
lst[i].DB2FE()
|
||||||
}
|
}
|
||||||
|
return lst, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return lst, err
|
lr := make([]*RecordingRule, 0, len(lst))
|
||||||
|
for _, r := range lst {
|
||||||
|
if MatchCluster(r.Cluster, cluster) {
|
||||||
|
r.DB2FE()
|
||||||
|
lr = append(lr, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func RecordingRuleStatistics(cluster string) (*Statistics, error) {
|
func RecordingRuleStatistics(cluster string) (*Statistics, error) {
|
||||||
session := DB().Model(&RecordingRule{}).Select("count(*) as total", "max(update_at) as last_updated")
|
session := DB().Model(&RecordingRule{}).Select("count(*) as total", "max(update_at) as last_updated")
|
||||||
if cluster != "" {
|
if cluster != "" {
|
||||||
session = session.Where("cluster = ?", cluster)
|
// 简略的判断,当一个clustername是另一个clustername的substring的时候,会出现stats与预期不符,不影响使用
|
||||||
|
session = session.Where("(cluster like ? or cluster like ?)", "%"+cluster+"%", "%"+ClusterAll+"%")
|
||||||
}
|
}
|
||||||
|
|
||||||
var stats []*Statistics
|
var stats []*Statistics
|
||||||
|
|
Loading…
Reference in New Issue