query alerts card
This commit is contained in:
parent
e1bd7f0267
commit
7c8c961aef
|
@ -1,6 +1,7 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -50,6 +51,62 @@ func (e *AlertCurEvent) Add() error {
|
|||
return Insert(e)
|
||||
}
|
||||
|
||||
type AggrRule struct {
|
||||
Type string
|
||||
Value string
|
||||
}
|
||||
|
||||
func (e *AlertCurEvent) GenCardTitle(rules []*AggrRule) string {
|
||||
arr := make([]string, len(rules))
|
||||
for i := 0; i < len(rules); i++ {
|
||||
rule := rules[i]
|
||||
|
||||
if rule.Type == "field" {
|
||||
arr[i] = e.GetField(rule.Value)
|
||||
}
|
||||
|
||||
if rule.Type == "tagkey" {
|
||||
arr[i] = e.GetTagValue(rule.Value)
|
||||
}
|
||||
}
|
||||
return strings.Join(arr, "::")
|
||||
}
|
||||
|
||||
func (e *AlertCurEvent) GetTagValue(tagkey string) string {
|
||||
for _, tag := range e.TagsJSON {
|
||||
i := strings.Index(tag, tagkey+"=")
|
||||
if i >= 0 {
|
||||
return tag[len(tagkey+"="):]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (e *AlertCurEvent) GetField(field string) string {
|
||||
switch field {
|
||||
case "cluster":
|
||||
return e.Cluster
|
||||
case "group_id":
|
||||
return fmt.Sprint(e.GroupId)
|
||||
case "group_name":
|
||||
return e.GroupName
|
||||
case "rule_id":
|
||||
return fmt.Sprint(e.RuleId)
|
||||
case "rule_name":
|
||||
return e.RuleName
|
||||
case "severity":
|
||||
return fmt.Sprintf("S%d", e.Severity)
|
||||
case "runbook_url":
|
||||
return e.RunbookUrl
|
||||
case "target_ident":
|
||||
return e.TargetIdent
|
||||
case "target_note":
|
||||
return e.TargetNote
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (e *AlertCurEvent) IncRepeatStep(step int64) error {
|
||||
return DB().Model(e).Where("id=?", e.Id).Update("notify_repeat_next", time.Now().Unix()+step).Error
|
||||
}
|
||||
|
@ -155,7 +212,11 @@ func (e *AlertCurEvent) FillNotifyGroups(cache map[int64]*UserGroup) error {
|
|||
}
|
||||
|
||||
func AlertCurEventTotal(bgid, stime, etime int64, severity int, clusters []string, query string) (int64, error) {
|
||||
session := DB().Model(&AlertCurEvent{}).Where("trigger_time between ? and ? and group_id = ?", stime, etime, bgid)
|
||||
session := DB().Model(&AlertCurEvent{}).Where("trigger_time between ? and ?", stime, etime)
|
||||
|
||||
if bgid > 0 {
|
||||
session = session.Where("group_id = ?", bgid)
|
||||
}
|
||||
|
||||
if severity >= 0 {
|
||||
session = session.Where("severity = ?", severity)
|
||||
|
@ -177,7 +238,11 @@ func AlertCurEventTotal(bgid, stime, etime int64, severity int, clusters []strin
|
|||
}
|
||||
|
||||
func AlertCurEventGets(bgid, stime, etime int64, severity int, clusters []string, query string, limit, offset int) ([]AlertCurEvent, error) {
|
||||
session := DB().Where("trigger_time between ? and ? and group_id = ?", stime, etime, bgid)
|
||||
session := DB().Where("trigger_time between ? and ?", stime, etime)
|
||||
|
||||
if bgid > 0 {
|
||||
session = session.Where("group_id = ?", bgid)
|
||||
}
|
||||
|
||||
if severity >= 0 {
|
||||
session = session.Where("severity = ?", severity)
|
||||
|
|
|
@ -88,7 +88,11 @@ func (e *AlertHisEvent) FillNotifyGroups(cache map[int64]*UserGroup) error {
|
|||
}
|
||||
|
||||
func AlertHisEventTotal(bgid, stime, etime int64, severity int, recovered int, clusters []string, query string) (int64, error) {
|
||||
session := DB().Model(&AlertHisEvent{}).Where("last_eval_time between ? and ? and group_id = ?", stime, etime, bgid)
|
||||
session := DB().Model(&AlertHisEvent{}).Where("last_eval_time between ? and ?", stime, etime)
|
||||
|
||||
if bgid > 0 {
|
||||
session = session.Where("group_id = ?", bgid)
|
||||
}
|
||||
|
||||
if severity >= 0 {
|
||||
session = session.Where("severity = ?", severity)
|
||||
|
@ -114,7 +118,11 @@ func AlertHisEventTotal(bgid, stime, etime int64, severity int, recovered int, c
|
|||
}
|
||||
|
||||
func AlertHisEventGets(bgid, stime, etime int64, severity int, recovered int, clusters []string, query string, limit, offset int) ([]AlertHisEvent, error) {
|
||||
session := DB().Where("last_eval_time between ? and ? and group_id = ?", stime, etime, bgid)
|
||||
session := DB().Where("last_eval_time between ? and ?", stime, etime)
|
||||
|
||||
if bgid > 0 {
|
||||
session = session.Where("group_id = ?", bgid)
|
||||
}
|
||||
|
||||
if severity >= 0 {
|
||||
session = session.Where("severity = ?", severity)
|
||||
|
|
|
@ -205,9 +205,10 @@ func configRoute(r *gin.Engine, version string) {
|
|||
// pages.GET("/busi-group/:id/collect-rule/:crid", jwtAuth(), user(), bgro(), collectRuleGet)
|
||||
// pages.PUT("/busi-group/:id/collect-rule/:crid", jwtAuth(), user(), bgrw(), collectRulePut)
|
||||
|
||||
// card逻辑fe改造完之后,这三个方法可以删除
|
||||
pages.GET("/busi-group/:id/alert-his-events", jwtAuth(), user(), bgro(), alertHisEventGets)
|
||||
pages.GET("/busi-group/:id/alert-cur-events", jwtAuth(), user(), bgro(), alertCurEventGets)
|
||||
pages.DELETE("/busi-group/:id/alert-cur-events", jwtAuth(), user(), perm("/alert-cur-events/del"), bgrw(), alertCurEventDel)
|
||||
pages.DELETE("/busi-group/:id/alert-cur-events", jwtAuth(), user(), perm("/alert-cur-events/del"), alertCurEventDel)
|
||||
|
||||
if config.C.AnonymousAccess.AlertDetail {
|
||||
pages.GET("/alert-cur-event/:eid", alertCurEventGet)
|
||||
|
@ -217,6 +218,13 @@ func configRoute(r *gin.Engine, version string) {
|
|||
pages.GET("/alert-his-event/:eid", jwtAuth(), alertHisEventGet)
|
||||
}
|
||||
|
||||
// card logic
|
||||
pages.GET("/alert-cur-events/list", jwtAuth(), alertCurEventsList)
|
||||
pages.GET("/alert-cur-events/card", jwtAuth(), alertCurEventsCard)
|
||||
pages.GET("/alert-cur-events/card/details", jwtAuth(), alertCurEventsCardDetails)
|
||||
pages.GET("/alert-his-events/list", jwtAuth(), alertHisEventsList)
|
||||
pages.DELETE("/alert-cur-events", jwtAuth(), user(), perm("/alert-cur-events/del"), alertCurEventDel)
|
||||
|
||||
pages.GET("/alert-aggr-views", jwtAuth(), alertAggrViewGets)
|
||||
pages.DELETE("/alert-aggr-views", jwtAuth(), alertAggrViewDel)
|
||||
pages.POST("/alert-aggr-views", jwtAuth(), alertAggrViewAdd)
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package router
|
||||
|
||||
import (
|
||||
"time"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/toolkits/pkg/ginx"
|
||||
|
@ -9,20 +10,104 @@ import (
|
|||
"github.com/didi/nightingale/v5/src/models"
|
||||
)
|
||||
|
||||
func alertCurEventGets(c *gin.Context) {
|
||||
stime := ginx.QueryInt64(c, "stime", 0)
|
||||
etime := ginx.QueryInt64(c, "etime", 0)
|
||||
hours := ginx.QueryInt64(c, "hours", 0)
|
||||
now := time.Now().Unix()
|
||||
if hours != 0 {
|
||||
stime = now - 3600*hours
|
||||
etime = now + 3600*24
|
||||
func alertCurEventsCard(c *gin.Context) {
|
||||
stime, etime := getTimeRange(c)
|
||||
severity := ginx.QueryInt(c, "severity", -1)
|
||||
query := ginx.QueryStr(c, "query", "")
|
||||
busiGroupId := ginx.QueryInt64(c, "bgid", 0)
|
||||
clusters := queryClusters(c)
|
||||
aggrRules := strings.Fields(ginx.QueryStr(c, "rules", "")) // e.g. field:group_name field:severity tagkey:ident
|
||||
|
||||
if len(aggrRules) == 0 {
|
||||
ginx.NewRender(c).Message("rules empty")
|
||||
return
|
||||
}
|
||||
|
||||
if stime != 0 && etime == 0 {
|
||||
etime = now + 3600*24
|
||||
rules := make([]*models.AggrRule, len(aggrRules))
|
||||
for i := 0; i < len(aggrRules); i++ {
|
||||
pair := strings.Split(aggrRules[i], ":")
|
||||
if len(pair) != 2 {
|
||||
ginx.NewRender(c).Message("rules invalid")
|
||||
return
|
||||
}
|
||||
|
||||
if !(pair[0] == "field" || pair[0] == "tagkey") {
|
||||
ginx.NewRender(c).Message("rules invalid")
|
||||
return
|
||||
}
|
||||
|
||||
rules[i] = &models.AggrRule{
|
||||
Type: pair[0],
|
||||
Value: pair[1],
|
||||
}
|
||||
}
|
||||
|
||||
// 最多获取10000个,获取太多也没啥意义
|
||||
list, err := models.AlertCurEventGets(busiGroupId, stime, etime, severity, clusters, query, 10000, 0)
|
||||
ginx.Dangerous(err)
|
||||
|
||||
cardCount := make(map[string]int)
|
||||
for _, event := range list {
|
||||
title := event.GenCardTitle(rules)
|
||||
cardCount[title]++
|
||||
}
|
||||
|
||||
titles := make([]string, 0, len(cardCount))
|
||||
for title := range cardCount {
|
||||
titles = append(titles, title)
|
||||
}
|
||||
|
||||
sort.Strings(titles)
|
||||
|
||||
cards := make([]AlertCard, len(titles))
|
||||
for i := 0; i < len(titles); i++ {
|
||||
cards[i] = AlertCard{
|
||||
Title: titles[i],
|
||||
Total: cardCount[titles[i]],
|
||||
}
|
||||
}
|
||||
|
||||
ginx.NewRender(c).Data(cards, nil)
|
||||
}
|
||||
|
||||
type AlertCard struct {
|
||||
Title string `json:"title"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
func alertCurEventsCardDetails(c *gin.Context) {
|
||||
|
||||
}
|
||||
|
||||
// 列表方式,拉取活跃告警
|
||||
func alertCurEventsList(c *gin.Context) {
|
||||
stime, etime := getTimeRange(c)
|
||||
severity := ginx.QueryInt(c, "severity", -1)
|
||||
query := ginx.QueryStr(c, "query", "")
|
||||
limit := ginx.QueryInt(c, "limit", 20)
|
||||
busiGroupId := ginx.QueryInt64(c, "bgid", 0)
|
||||
clusters := queryClusters(c)
|
||||
|
||||
total, err := models.AlertCurEventTotal(busiGroupId, stime, etime, severity, clusters, query)
|
||||
ginx.Dangerous(err)
|
||||
|
||||
list, err := models.AlertCurEventGets(busiGroupId, stime, etime, severity, clusters, query, limit, ginx.Offset(c, limit))
|
||||
ginx.Dangerous(err)
|
||||
|
||||
cache := make(map[int64]*models.UserGroup)
|
||||
for i := 0; i < len(list); i++ {
|
||||
list[i].FillNotifyGroups(cache)
|
||||
}
|
||||
|
||||
ginx.NewRender(c).Data(gin.H{
|
||||
"list": list,
|
||||
"total": total,
|
||||
}, nil)
|
||||
}
|
||||
|
||||
func alertCurEventGets(c *gin.Context) {
|
||||
stime, etime := getTimeRange(c)
|
||||
|
||||
severity := ginx.QueryInt(c, "severity", -1)
|
||||
query := ginx.QueryStr(c, "query", "")
|
||||
limit := ginx.QueryInt(c, "limit", 20)
|
||||
|
@ -51,6 +136,18 @@ func alertCurEventDel(c *gin.Context) {
|
|||
ginx.BindJSON(c, &f)
|
||||
f.Verify()
|
||||
|
||||
set := make(map[int64]struct{})
|
||||
|
||||
for i := 0; i < len(f.Ids); i++ {
|
||||
event, err := models.AlertCurEventGetById(f.Ids[i])
|
||||
ginx.Dangerous(err)
|
||||
|
||||
if _, has := set[event.GroupId]; !has {
|
||||
bgrwCheck(c, event.GroupId)
|
||||
set[event.GroupId] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
ginx.NewRender(c).Message(models.AlertCurEventDel(f.Ids))
|
||||
}
|
||||
|
||||
|
|
|
@ -9,9 +9,9 @@ import (
|
|||
"github.com/didi/nightingale/v5/src/models"
|
||||
)
|
||||
|
||||
func alertHisEventGets(c *gin.Context) {
|
||||
stime := ginx.QueryInt64(c, "stime", 0)
|
||||
etime := ginx.QueryInt64(c, "etime", 0)
|
||||
func getTimeRange(c *gin.Context) (stime, etime int64) {
|
||||
stime = ginx.QueryInt64(c, "stime", 0)
|
||||
etime = ginx.QueryInt64(c, "etime", 0)
|
||||
hours := ginx.QueryInt64(c, "hours", 0)
|
||||
now := time.Now().Unix()
|
||||
if hours != 0 {
|
||||
|
@ -22,6 +22,38 @@ func alertHisEventGets(c *gin.Context) {
|
|||
if stime != 0 && etime == 0 {
|
||||
etime = now + 3600*24
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func alertHisEventsList(c *gin.Context) {
|
||||
stime, etime := getTimeRange(c)
|
||||
|
||||
severity := ginx.QueryInt(c, "severity", -1)
|
||||
recovered := ginx.QueryInt(c, "is_recovered", -1)
|
||||
query := ginx.QueryStr(c, "query", "")
|
||||
limit := ginx.QueryInt(c, "limit", 20)
|
||||
busiGroupId := ginx.QueryInt64(c, "bgid", 0)
|
||||
clusters := queryClusters(c)
|
||||
|
||||
total, err := models.AlertHisEventTotal(busiGroupId, stime, etime, severity, recovered, clusters, query)
|
||||
ginx.Dangerous(err)
|
||||
|
||||
list, err := models.AlertHisEventGets(busiGroupId, stime, etime, severity, recovered, clusters, query, limit, ginx.Offset(c, limit))
|
||||
ginx.Dangerous(err)
|
||||
|
||||
cache := make(map[int64]*models.UserGroup)
|
||||
for i := 0; i < len(list); i++ {
|
||||
list[i].FillNotifyGroups(cache)
|
||||
}
|
||||
|
||||
ginx.NewRender(c).Data(gin.H{
|
||||
"list": list,
|
||||
"total": total,
|
||||
}, nil)
|
||||
}
|
||||
|
||||
func alertHisEventGets(c *gin.Context) {
|
||||
stime, etime := getTimeRange(c)
|
||||
|
||||
severity := ginx.QueryInt(c, "severity", -1)
|
||||
recovered := ginx.QueryInt(c, "is_recovered", -1)
|
||||
|
|
Loading…
Reference in New Issue