feat: alert rule api fill users and groups (#723)
This commit is contained in:
parent
4585519943
commit
6440645c5a
|
@ -0,0 +1,41 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
type UserGroupMap struct {
|
||||
sync.RWMutex
|
||||
Data map[int64]*models.UserGroup
|
||||
}
|
||||
|
||||
var UserGroupCache = &UserGroupMap{Data: make(map[int64]*models.UserGroup)}
|
||||
|
||||
func (s *UserGroupMap) GetBy(id int64) *models.UserGroup {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
|
||||
return s.Data[id]
|
||||
}
|
||||
|
||||
func (s *UserGroupMap) GetByIds(ids []int64) []*models.UserGroup {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
var userGroups []*models.UserGroup
|
||||
for _, id := range ids {
|
||||
if s.Data[id] == nil {
|
||||
continue
|
||||
}
|
||||
userGroups = append(userGroups, s.Data[id])
|
||||
}
|
||||
|
||||
return userGroups
|
||||
}
|
||||
|
||||
func (s *UserGroupMap) SetAll(userGroups map[int64]*models.UserGroup) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
s.Data = userGroups
|
||||
}
|
|
@ -3,16 +3,21 @@ package http
|
|||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/didi/nightingale/v5/cache"
|
||||
"github.com/didi/nightingale/v5/config"
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
func alertRuleGet(c *gin.Context) {
|
||||
renderData(c, AlertRule(urlParamInt64(c, "id")), nil)
|
||||
alertRule := AlertRule(urlParamInt64(c, "id"))
|
||||
alertRuleFillUserAndGroups(alertRule)
|
||||
renderData(c, alertRule, nil)
|
||||
}
|
||||
|
||||
type alertRuleForm struct {
|
||||
|
@ -163,3 +168,22 @@ func alertRuleDel(c *gin.Context) {
|
|||
func notifyChannelsGet(c *gin.Context) {
|
||||
renderData(c, config.Config.NotifyChannels, nil)
|
||||
}
|
||||
|
||||
func alertRuleFillUserAndGroups(alertRule *models.AlertRule) {
|
||||
uidStrs := strings.Fields(alertRule.NotifyUsers)
|
||||
var uids []int64
|
||||
for _, uidStr := range uidStrs {
|
||||
uid, _ := strconv.ParseInt(uidStr, 10, 64)
|
||||
uids = append(uids, uid)
|
||||
}
|
||||
alertRule.NotifyUsersDetail = cache.UserCache.GetByIds(uids)
|
||||
|
||||
gidStrs := strings.Fields(alertRule.NotifyGroups)
|
||||
var gids []int64
|
||||
for _, gidStr := range gidStrs {
|
||||
gid, _ := strconv.ParseInt(gidStr, 10, 64)
|
||||
gids = append(gids, gid)
|
||||
}
|
||||
|
||||
alertRule.NotifyGroupsDetail = cache.UserGroupCache.GetByIds(gids)
|
||||
}
|
||||
|
|
|
@ -68,6 +68,10 @@ func alertRuleGroupGet(c *gin.Context) {
|
|||
|
||||
func alertRuleOfGroupGet(c *gin.Context) {
|
||||
ars, err := models.AlertRulesOfGroup(urlParamInt64(c, "id"))
|
||||
for i := range ars {
|
||||
alertRuleFillUserAndGroups(&ars[i])
|
||||
}
|
||||
|
||||
renderData(c, ars, err)
|
||||
}
|
||||
|
||||
|
|
1
main.go
1
main.go
|
@ -71,6 +71,7 @@ func main() {
|
|||
|
||||
timer.SyncResourceTags()
|
||||
timer.SyncUsers()
|
||||
timer.SyncUserGroups()
|
||||
timer.SyncUserGroupMember()
|
||||
timer.SyncClasspathReses()
|
||||
timer.SyncCollectRules()
|
||||
|
|
|
@ -19,32 +19,34 @@ const ALERT_RULE_ACTIVE = 0
|
|||
const ALERT_RULE_DISABLED = 1
|
||||
|
||||
type AlertRule struct {
|
||||
Id int64 `json:"id"`
|
||||
GroupId int64 `json:"group_id"`
|
||||
Name string `json:"name"`
|
||||
Type int `json:"type"` // 0: nightingale, 1: prometheus
|
||||
Expression json.RawMessage `json:"expression"`
|
||||
Status int `json:"status"` // 0: active, 1: disabled
|
||||
AppendTags string `json:"append_tags"`
|
||||
EnableStime string `json:"enable_stime"`
|
||||
EnableEtime string `json:"enable_etime"`
|
||||
EnableDaysOfWeek string `json:"enable_days_of_week"`
|
||||
RecoveryNotify int `json:"recovery_notify"`
|
||||
Priority int `json:"priority"`
|
||||
NotifyChannels string `json:"notify_channels"`
|
||||
NotifyGroups string `json:"notify_groups"`
|
||||
NotifyUsers string `json:"notify_users"`
|
||||
Callbacks string `json:"callbacks"`
|
||||
RunbookUrl string `json:"runbook_url"`
|
||||
Note string `json:"note"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
CreateBy string `json:"create_by"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
UpdateBy string `json:"update_by"`
|
||||
AlertDuration int `json:"alert_duration"` // 告警统计周期,PULL模型会当做P8S的for时间
|
||||
PushExpr PushExpression `xorm:"-" json:"-"`
|
||||
PullExpr PullExpression `xorm:"-" json:"-"`
|
||||
FirstMetric string `xorm:"-" json:"-"` // Exps里可能有多个metric,只取第一个,给后续制作map使用
|
||||
Id int64 `json:"id"`
|
||||
GroupId int64 `json:"group_id"`
|
||||
Name string `json:"name"`
|
||||
Type int `json:"type"` // 0: nightingale, 1: prometheus
|
||||
Expression json.RawMessage `json:"expression"`
|
||||
Status int `json:"status"` // 0: active, 1: disabled
|
||||
AppendTags string `json:"append_tags"`
|
||||
EnableStime string `json:"enable_stime"`
|
||||
EnableEtime string `json:"enable_etime"`
|
||||
EnableDaysOfWeek string `json:"enable_days_of_week"`
|
||||
RecoveryNotify int `json:"recovery_notify"`
|
||||
Priority int `json:"priority"`
|
||||
NotifyChannels string `json:"notify_channels"`
|
||||
NotifyGroups string `json:"notify_groups"`
|
||||
NotifyUsers string `json:"notify_users"`
|
||||
Callbacks string `json:"callbacks"`
|
||||
RunbookUrl string `json:"runbook_url"`
|
||||
Note string `json:"note"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
CreateBy string `json:"create_by"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
UpdateBy string `json:"update_by"`
|
||||
AlertDuration int `json:"alert_duration"` // 告警统计周期,PULL模型会当做P8S的for时间
|
||||
PushExpr PushExpression `xorm:"-" json:"-"`
|
||||
PullExpr PullExpression `xorm:"-" json:"-"`
|
||||
FirstMetric string `xorm:"-" json:"-"` // Exps里可能有多个metric,只取第一个,给后续制作map使用
|
||||
NotifyUsersDetail []*User `xorm:"-" json:"notify_users_detail"`
|
||||
NotifyGroupsDetail []*UserGroup `xorm:"-" json:"notify_groups_detail"`
|
||||
}
|
||||
|
||||
type PushExpression struct {
|
||||
|
|
|
@ -204,3 +204,19 @@ func (ug *UserGroup) Del() error {
|
|||
|
||||
return session.Commit()
|
||||
}
|
||||
|
||||
func UserGroupGetAll() ([]UserGroup, error) {
|
||||
var userGroups []UserGroup
|
||||
|
||||
err := DB.Find(&userGroups)
|
||||
if err != nil {
|
||||
logger.Errorf("mysql.error: select user_group fail: %v", err)
|
||||
return userGroups, internalServerError
|
||||
}
|
||||
|
||||
if len(userGroups) == 0 {
|
||||
return []UserGroup{}, nil
|
||||
}
|
||||
|
||||
return userGroups, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package timer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/didi/nightingale/v5/cache"
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
|
||||
"github.com/toolkits/pkg/logger"
|
||||
)
|
||||
|
||||
// user_group_id->user_group 将数据库中的用户信息缓存在内存里,
|
||||
// 在生成告警事件的时候,根据用户ID快速找到用户的详情
|
||||
func SyncUserGroups() {
|
||||
err := syncUserGroups()
|
||||
if err != nil {
|
||||
fmt.Println("timer: sync users fail:", err)
|
||||
exit(1)
|
||||
}
|
||||
|
||||
go loopSyncUserGroups()
|
||||
}
|
||||
|
||||
func loopSyncUserGroups() {
|
||||
randtime := rand.Intn(9000)
|
||||
fmt.Printf("timer: sync users: random sleep %dms\n", randtime)
|
||||
time.Sleep(time.Duration(randtime) * time.Millisecond)
|
||||
|
||||
for {
|
||||
time.Sleep(time.Second * time.Duration(9))
|
||||
err := syncUserGroups()
|
||||
if err != nil {
|
||||
logger.Warning("timer: sync users fail:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func syncUserGroups() error {
|
||||
start := time.Now()
|
||||
|
||||
userGroups, err := models.UserGroupGetAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userGroupsMap := make(map[int64]*models.UserGroup)
|
||||
for i := range userGroups {
|
||||
userGroupsMap[userGroups[i].Id] = &userGroups[i]
|
||||
}
|
||||
|
||||
cache.UserGroupCache.SetAll(userGroupsMap)
|
||||
logger.Debugf("timer: sync userGroups done, cost: %dms", time.Since(start).Milliseconds())
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue