Browse Source

add alert_aggr_view crud

tags/v5.8.0
Ulric Qin 4 years ago
parent
commit
025c5809be
7 changed files with 252 additions and 83 deletions
  1. +16
    -0
      docker/initsql/a-n9e.sql
  2. +96
    -0
      src/models/alert_aggr_view.go
  3. +5
    -0
      src/webapi/router/router.go
  4. +55
    -0
      src/webapi/router/router_alert_aggr_view.go
  5. +77
    -77
      src/webapi/router/router_collect_rule.go
  6. +0
    -4
      src/webapi/router/router_dashboard.go
  7. +3
    -2
      src/webapi/router/router_task_tpl.go

+ 16
- 0
docker/initsql/a-n9e.sql View File

@@ -296,6 +296,22 @@ CREATE TABLE `target` (
-- KEY (`group_id`, `type`, `name`)
-- ) ENGINE=InnoDB DEFAULT CHARSET = utf8mb4;

CREATE TABLE `alert_aggr_view` (
`id` bigint unsigned not null auto_increment,
`name` varchar(191) not null default '',
`rule` varchar(2048) not null default '',
`cate` tinyint(1) not null comment '0: preset 1: custom',
`user_id` bigint not null default 0,
`create_at` bigint not null default 0,
`create_by` varchar(64) not null default '',
`update_at` bigint not null default 0,
PRIMARY KEY (`id`),
KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET = utf8mb4;

insert into alert_aggr_view(name, rule, cate) values('GroupBy BusiGroup, Severity', 'field:group_name field:severity', 0);
insert into alert_aggr_view(name, rule, cate) values('GroupBy Metric', 'tagkey:__name__', 0);

CREATE TABLE `alert_cur_event` (
`id` bigint unsigned not null comment 'use alert_his_event.id',
`cluster` varchar(128) not null,


+ 96
- 0
src/models/alert_aggr_view.go View File

@@ -0,0 +1,96 @@
package models

import (
"errors"
"sort"
"strings"
"time"
)

// AlertAggrView 在告警聚合视图查看的时候,要存储一些聚合规则
type AlertAggrView struct {
Id int64 `json:"id" gorm:"primaryKey"`
Name string `json:"name"`
Rule string `json:"rule"`
Cate int `json:"cate"`
UserId int64 `json:"user_id"`
CreateAt int64 `json:"create_at"`
CreateBy string `json:"create_by"`
UpdateAt int64 `json:"update_at"`
}

func (v *AlertAggrView) TableName() string {
return "alert_aggr_view"
}

func (v *AlertAggrView) Verify() error {
v.Name = strings.TrimSpace(v.Name)
if v.Name == "" {
return errors.New("name is blank")
}

v.Rule = strings.TrimSpace(v.Rule)
if v.Rule == "" {
return errors.New("rule is blank")
}

return nil
}

func (v *AlertAggrView) Add() error {
if err := v.Verify(); err != nil {
return err
}

now := time.Now().Unix()
v.CreateAt = now
v.UpdateAt = now
v.Cate = 1
return Insert(v)
}

func (v *AlertAggrView) Update(name, rule string) error {
if err := v.Verify(); err != nil {
return err
}

v.UpdateAt = time.Now().Unix()
v.Name = name
v.Rule = rule

return DB().Model(v).Select("name", "rule", "update_at").Updates(v).Error
}

// AlertAggrViewDel: userid for safe delete
func AlertAggrViewDel(ids []int64, userId interface{}) error {
if len(ids) == 0 {
return nil
}

return DB().Where("id in ? and user_id = ?", ids, userId).Delete(new(AlertAggrView)).Error
}

func AlertAggrViewGets(userId interface{}) ([]AlertAggrView, error) {
var lst []AlertAggrView
err := DB().Where("user_id = ? or cate = 0", userId).Find(&lst).Error
if err == nil && len(lst) > 0 {
sort.Slice(lst, func(i, j int) bool {
return lst[i].Name < lst[j].Name
})
}
return lst, err
}

func AlertAggrViewGet(where string, args ...interface{}) (*AlertAggrView, error) {
var lst []*AlertAggrView
err := DB().Where(where, args...).Find(&lst).Error
if err != nil {
return nil, err
}

if len(lst) == 0 {
return nil, nil
}

return lst[0], nil
}

+ 5
- 0
src/webapi/router/router.go View File

@@ -217,6 +217,11 @@ func configRoute(r *gin.Engine, version string) {
pages.GET("/alert-his-event/:eid", jwtAuth(), alertHisEventGet)
}

pages.GET("/alert-aggr-views", jwtAuth(), alertAggrViewGets)
pages.DELETE("/alert-aggr-views", jwtAuth(), alertAggrViewDel)
pages.POST("/alert-aggr-views", jwtAuth(), alertAggrViewAdd)
pages.PUT("/alert-aggr-views", jwtAuth(), alertAggrViewPut)

pages.GET("/busi-group/:id/task-tpls", jwtAuth(), user(), perm("/job-tpls"), bgro(), taskTplGets)
pages.POST("/busi-group/:id/task-tpls", jwtAuth(), user(), perm("/job-tpls/add"), bgrw(), taskTplAdd)
pages.DELETE("/busi-group/:id/task-tpl/:tid", jwtAuth(), user(), perm("/job-tpls/del"), bgrw(), taskTplDel)


+ 55
- 0
src/webapi/router/router_alert_aggr_view.go View File

@@ -0,0 +1,55 @@
package router

import (
"net/http"

"github.com/didi/nightingale/v5/src/models"
"github.com/gin-gonic/gin"
"github.com/toolkits/pkg/ginx"
)

func alertAggrViewGets(c *gin.Context) {
lst, err := models.AlertAggrViewGets(c.MustGet("userid"))
ginx.NewRender(c).Data(lst, err)
}

// name and rule is necessary
func alertAggrViewAdd(c *gin.Context) {
var f models.AlertAggrView
ginx.BindJSON(c, &f)

f.Id = 0
f.CreateBy = c.MustGet("username").(string)
f.UserId = c.MustGet("userid").(int64)

ginx.NewRender(c).Message(f.Add())
}

func alertAggrViewDel(c *gin.Context) {
var f idsForm
ginx.BindJSON(c, &f)

ginx.NewRender(c).Message(models.AlertAggrViewDel(f.Ids, c.MustGet("userid")))
}

// id / name / rule is necessary
func alertAggrViewPut(c *gin.Context) {
var f models.AlertAggrView
ginx.BindJSON(c, &f)

view, err := models.AlertAggrViewGet("id = ?", f.Id)
ginx.Dangerous(err)

if view == nil {
ginx.NewRender(c).Message("no such item(id: %d)", f.Id)
return
}

userid := c.MustGet("userid").(int64)
if view.UserId != userid {
ginx.NewRender(c, http.StatusForbidden).Message("forbidden")
return
}

ginx.NewRender(c).Message(view.Update(f.Name, f.Rule))
}

+ 77
- 77
src/webapi/router/router_collect_rule.go View File

@@ -1,79 +1,79 @@
package router

import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/toolkits/pkg/ginx"
"github.com/didi/nightingale/v5/src/models"
)
func collectRuleGets(c *gin.Context) {
busiGroupId := ginx.UrlParamInt64(c, "id")
crs, err := models.CollectRuleGets(busiGroupId, ginx.QueryStr(c, "type", ""))
ginx.NewRender(c).Data(crs, err)
}
func collectRuleAdd(c *gin.Context) {
var lst []models.CollectRule
ginx.BindJSON(c, &lst)
count := len(lst)
if count == 0 {
ginx.Bomb(http.StatusBadRequest, "input json is empty")
}
username := c.MustGet("username").(string)
bgid := ginx.UrlParamInt64(c, "id")
// collect rule name -> error string
reterr := make(map[string]string)
for i := 0; i < count; i++ {
lst[i].Id = 0
lst[i].GroupId = bgid
lst[i].CreateBy = username
lst[i].UpdateBy = username
lst[i].FE2DB()
if err := lst[i].Add(); err != nil {
reterr[lst[i].Name] = err.Error()
} else {
reterr[lst[i].Name] = ""
}
}
ginx.NewRender(c).Data(reterr, nil)
}
func collectRuleDel(c *gin.Context) {
var f idsForm
ginx.BindJSON(c, &f)
f.Verify()
// param(busiGroupId) for protect
ginx.NewRender(c).Message(models.CollectRuleDels(f.Ids, ginx.UrlParamInt64(c, "id")))
}
func collectRuleGet(c *gin.Context) {
crid := ginx.UrlParamInt64(c, "crid")
cr, err := models.CollectRuleGetById(crid)
ginx.NewRender(c).Data(cr, err)
}
func collectRulePut(c *gin.Context) {
var f models.CollectRule
ginx.BindJSON(c, &f)
crid := ginx.UrlParamInt64(c, "crid")
cr, err := models.CollectRuleGetById(crid)
ginx.Dangerous(err)
if cr == nil {
ginx.NewRender(c, http.StatusNotFound).Message("No such CollectRule")
return
}
f.UpdateBy = c.MustGet("username").(string)
ginx.NewRender(c).Message(cr.Update(f))
}
// import (
// "net/http"
// "github.com/gin-gonic/gin"
// "github.com/toolkits/pkg/ginx"
// "github.com/didi/nightingale/v5/src/models"
// )
// func collectRuleGets(c *gin.Context) {
// busiGroupId := ginx.UrlParamInt64(c, "id")
// crs, err := models.CollectRuleGets(busiGroupId, ginx.QueryStr(c, "type", ""))
// ginx.NewRender(c).Data(crs, err)
// }
// func collectRuleAdd(c *gin.Context) {
// var lst []models.CollectRule
// ginx.BindJSON(c, &lst)
// count := len(lst)
// if count == 0 {
// ginx.Bomb(http.StatusBadRequest, "input json is empty")
// }
// username := c.MustGet("username").(string)
// bgid := ginx.UrlParamInt64(c, "id")
// // collect rule name -> error string
// reterr := make(map[string]string)
// for i := 0; i < count; i++ {
// lst[i].Id = 0
// lst[i].GroupId = bgid
// lst[i].CreateBy = username
// lst[i].UpdateBy = username
// lst[i].FE2DB()
// if err := lst[i].Add(); err != nil {
// reterr[lst[i].Name] = err.Error()
// } else {
// reterr[lst[i].Name] = ""
// }
// }
// ginx.NewRender(c).Data(reterr, nil)
// }
// func collectRuleDel(c *gin.Context) {
// var f idsForm
// ginx.BindJSON(c, &f)
// f.Verify()
// // param(busiGroupId) for protect
// ginx.NewRender(c).Message(models.CollectRuleDels(f.Ids, ginx.UrlParamInt64(c, "id")))
// }
// func collectRuleGet(c *gin.Context) {
// crid := ginx.UrlParamInt64(c, "crid")
// cr, err := models.CollectRuleGetById(crid)
// ginx.NewRender(c).Data(cr, err)
// }
// func collectRulePut(c *gin.Context) {
// var f models.CollectRule
// ginx.BindJSON(c, &f)
// crid := ginx.UrlParamInt64(c, "crid")
// cr, err := models.CollectRuleGetById(crid)
// ginx.Dangerous(err)
// if cr == nil {
// ginx.NewRender(c, http.StatusNotFound).Message("No such CollectRule")
// return
// }
// f.UpdateBy = c.MustGet("username").(string)
// ginx.NewRender(c).Message(cr.Update(f))
// }

+ 0
- 4
src/webapi/router/router_dashboard.go View File

@@ -223,10 +223,6 @@ func dashboardImport(c *gin.Context) {
ginx.NewRender(c).Data(ret, nil)
}

type idForm struct {
Id int64 `json:"id" binding:"required"`
}

func dashboardClone(c *gin.Context) {
dash := Dashboard(ginx.UrlParamInt64(c, "did"))
user := c.MustGet("user").(*models.User)


+ 3
- 2
src/webapi/router/router_task_tpl.go View File

@@ -45,7 +45,7 @@ func taskTplGet(c *gin.Context) {
ginx.NewRender(c).Data(gin.H{
"tpl": tpl,
"hosts": hosts,
}, nil)
}, err)
}

type taskTplForm struct {
@@ -97,7 +97,8 @@ func taskTplPut(c *gin.Context) {
ginx.Dangerous(err)

if tpl == nil {
ginx.Dangerous("no such task template")
ginx.NewRender(c).Message("no such task template")
return
}

user := c.MustGet("user").(*models.User)


Loading…
Cancel
Save