feat: alert rule api fill users and groups (#723)

This commit is contained in:
qinyening 2021-07-06 21:33:19 +08:00 committed by GitHub
parent 4585519943
commit 6440645c5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 172 additions and 27 deletions

41
cache/user_group.go vendored Normal file
View File

@ -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
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -71,6 +71,7 @@ func main() {
timer.SyncResourceTags()
timer.SyncUsers()
timer.SyncUserGroups()
timer.SyncUserGroupMember()
timer.SyncClasspathReses()
timer.SyncCollectRules()

View File

@ -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 {

View File

@ -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
}

57
timer/user_group.go Normal file
View File

@ -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
}