Commit 00d92526 authored by 李科's avatar 李科

fix: 批量推送

parent 84591f16
...@@ -51,6 +51,20 @@ type OpenSearchIds struct { ...@@ -51,6 +51,20 @@ type OpenSearchIds struct {
} `json:"ids"` } `json:"ids"`
} }
func (a *Alert) TableName() string { type PushRecord struct {
return "alert" Id int `json:"id" xorm:"'id' pk autoincr"` // 主键id(数组唯一标识)
AlertId int `json:"alert_id" xorm:"alert_id"` // 告警id
AlertRulesId string `json:"alert_rules_id" xorm:"'alert_rules_id'"` // 告警规则id
RiskLevel int `json:"risk_level" xorm:"'risk_level'"` // 风险等级,1:低风险,2:一般风险,3:较大风险,4:重大风险
NotifyMethod []string `json:"notify_method" xorm:"notify_method"` // 预警通知方式 dingtalk sms
SystemAccount string `json:"system_account" xorm:"system_account"` // 预警推送用户
PushTime jsontime.Time `json:"push_time" xorm:"'push_time'"` // 推送时间
PushType int `json:"push_type" xorm:"'push_type'"` // 推送类型,1:自动推送,2:手动推送
Status int `json:"status" xorm:"'status'"` // 推送状态,1:成功,2:失败
UserName string `json:"user_name" xorm:"user_name"` // 推送用户名称
Phone string `json:"phone" xorm:"phone"` // 推送手机号
CreatedBy string `json:"created_by" xorm:"'created_by'"` // 创建人
CreatedAt jsontime.Time `json:"created_at" xorm:"'created_at'"` // 创建时间
UpdatedBy string `json:"updated_by" xorm:"'updated_by'"` // 更新人
UpdatedAt jsontime.Time `json:"updated_at" xorm:"'updated_at'"` // 更新时间
} }
package entity
import "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime"
type PushRecord struct {
Id int `json:"id" xorm:"'id' pk autoincr"` // 主键id(数组唯一标识)
AlertId int `json:"alert_id" xorm:"alert_id"` // 告警id
AlertRulesId string `json:"alert_rules_id" xorm:"'alert_rules_id'"` // 告警规则id
RiskLevel int `json:"risk_level" xorm:"'risk_level'"` // 风险等级,1:低风险,2:一般风险,3:较大风险,4:重大风险
NotifyMethod []string `json:"notify_method" xorm:"notify_method"` // 预警通知方式 dingtalk sms
SystemAccount string `json:"system_account" xorm:"system_account"` // 预警推送用户
PushTime jsontime.Time `json:"push_time" xorm:"'push_time'"` // 推送时间
PushType int `json:"push_type" xorm:"'push_type'"` // 推送类型,1:自动推送,2:手动推送
Status int `json:"status" xorm:"'status'"` // 推送状态,1:成功,2:失败
UserName string `json:"user_name" xorm:"user_name"` // 推送用户名称
Phone string `json:"phone" xorm:"phone"` // 推送手机号
CreatedBy string `json:"created_by" xorm:"'created_by'"` // 创建人
CreatedAt jsontime.Time `json:"created_at" xorm:"'created_at'"` // 创建时间
UpdatedBy string `json:"updated_by" xorm:"'updated_by'"` // 更新人
UpdatedAt jsontime.Time `json:"updated_at" xorm:"'updated_at'"` // 更新时间
}
package request
import "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity"
type AddPushRecord struct {
ClassId int `json:"class_id" form:"class_id" binding:"required"` // 预警对象分类id
MetricName string `json:"metric_name" form:"metric_name" binding:"required"` // 指标名称
Expr string `json:"expr" form:"expr" binding:"required"` // 指标表达式(PromQL语句)
AlertRange []entity.AlertRange `json:"alert_range" form:"alert_range" binding:"required,dive"` // 预警范围 字典值
Duration int `json:"duration" form:"duration"` // 持续时间
DurationUnit string `json:"duration_unit" form:"duration_unit" binding:"required,oneof=s m h"` // 持续时间单位 s m h
CheckPeriod int `json:"check_period" form:"check_period" binding:"oneof=1 3 5 10 20 30"` // 检查周期 单位:分钟
IsEnabled int `json:"is_enabled" form:"is_enabled" binding:"omitempty,oneof=1 2"` // 是否开启 1:是 2:否
AlertRuleType string `json:"alert_rule_type" form:"alert_rule_type" binding:"required"` // 预警规则类型 关联字典表
SourceFrom int `json:"source_from" form:"source_from" binding:"omitempty,oneof=1 2"` // 数据来源 1:默认 2:自定义
}
type UpdatePushRecord struct {
Id string `json:"id" form:"id" binding:"required"` // 主键id
ClassId int `json:"class_id" form:"class_id"` // 预警对象分类id
MetricName string `json:"metric_name" form:"metric_name"` // 指标名称
Expr string `json:"expr" form:"expr"` // 指标表达式(PromQL语句)
AlertRange []entity.AlertRange `json:"alert_range" form:"alert_range"` // 预警范围 字典值
Duration int `json:"duration" form:"duration"` // 持续时间
DurationUnit string `json:"duration_unit" form:"duration_unit" binding:"omitempty,oneof=s m h"` // 持续时间单位 s m h
CheckPeriod int `json:"check_period" form:"check_period" binding:"omitempty,oneof=1 3 5 10 20 30"` // 检查周期 单位:分钟
IsEnabled int `json:"is_enabled" form:"is_enabled" binding:"omitempty,oneof=1 2"` // 是否开启 1:是 2:否
AlertRuleType string `json:"alert_rule_type" form:"alert_rule_type"` // 预警规则类型 关联字典表
SourceFrom int `json:"source_from" form:"source_from" binding:"omitempty,oneof=1 2"` // 数据来源 1:默认 2:自定义
}
type DeletePushRecord struct {
Id string `json:"id" form:"id"`
Ids []string `json:"ids" form:"ids" binding:"required_without=Id"`
}
type DetailPushRecord struct {
Id string `json:"id" form:"id" binding:"required"`
}
type ListPushRecord struct {
AlertListId int `json:"alert_list_id" form:"alert_list_id" binding:"required"` // 预警列表id
}
package controller
import (
"github.com/gin-gonic/gin"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/router/middleware/header"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/service"
)
// AddPushRecord 新增任务
func AddPushRecord(c *gin.Context) {
var req request.AddPushRecord
if err := c.ShouldBind(&req); err != nil {
SendJsonResponse(c, resp.InvalidParam.TranslateError(err), nil)
return
}
svc := service.PushRecordSvc{User: header.GetUser(c)}
db, err := client.GetDbClient()
if err != nil {
SendJsonResponse(c, resp.DbConnectError.WithError(err), nil)
return
}
_, err = svc.Add(db.NewSession(), req)
if err != nil {
SendJsonResponse(c, resp.FAIL.WithError(err), nil)
return
}
SendJsonResponse(c, resp.OK, nil)
}
func UpdatePushRecord(c *gin.Context) {
var req request.UpdatePushRecord
if err := c.ShouldBind(&req); err != nil {
SendJsonResponse(c, resp.InvalidParam.TranslateError(err), nil)
return
}
svc := service.PushRecordSvc{User: header.GetUser(c)}
db, err := client.GetDbClient()
if err != nil {
SendJsonResponse(c, resp.DbConnectError.WithError(err), nil)
return
}
err = svc.Update(db.NewSession(), req)
if err != nil {
SendJsonResponse(c, resp.FAIL.WithError(err), nil)
return
}
SendJsonResponse(c, resp.OK, nil)
}
func DeletePushRecord(c *gin.Context) {
var req request.DeletePushRecord
if err := c.ShouldBind(&req); err != nil {
SendJsonResponse(c, resp.InvalidParam.TranslateError(err), nil)
return
}
var ids []string
switch len(req.Ids) {
case 0:
ids = append(ids, req.Id)
default:
ids = req.Ids
}
svc := service.PushRecordSvc{User: header.GetUser(c)}
err := svc.Delete(ids)
if err != nil {
SendJsonResponse(c, resp.FAIL.WithError(err), nil)
return
}
SendJsonResponse(c, resp.OK, nil)
}
func DetailPushRecord(c *gin.Context) {
var req request.DetailPushRecord
if err := c.ShouldBind(&req); err != nil {
SendJsonResponse(c, resp.InvalidParam.TranslateError(err), nil)
return
}
svc := service.PushRecordSvc{User: header.GetUser(c)}
data, err := svc.GetDataById(req)
if err != nil {
SendJsonResponse(c, resp.FAIL.WithError(err), nil)
return
}
SendJsonResponse(c, resp.OK, data)
}
func ListPushRecord(c *gin.Context) {
var req request.ListPushRecord
if err := c.ShouldBind(&req); err != nil {
SendJsonResponse(c, resp.InvalidParam.TranslateError(err), nil)
return
}
svc := service.PushRecordSvc{User: header.GetUser(c)}
data, err := svc.List(req)
if err != nil {
SendJsonResponse(c, resp.FAIL.WithError(err), nil)
return
}
SendJsonResponse(c, resp.OK, data)
}
...@@ -49,6 +49,7 @@ func main() { ...@@ -49,6 +49,7 @@ func main() {
cron.StartCron() cron.StartCron()
service.PushWorkOrderMessage() service.PushWorkOrderMessage()
// server start... // server start...
conf.Logger.Info("config info", zap.Any("options", conf.Options))
conf.Logger.Error("server start err", zap.Error(newServer().ListenAndServe())) conf.Logger.Error("server start err", zap.Error(newServer().ListenAndServe()))
} }
......
package router
import (
"fmt"
"github.com/gin-gonic/gin"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/controller"
)
// InitPushRecordRouter 初始化推送记录配置路由
func InitPushRecordRouter(e *gin.Engine) {
group := e.Group(fmt.Sprintf("%s/push_record", conf.Options.Prefix))
{
group.GET("", controller.DetailPushRecord)
group.GET("list", controller.ListPushRecord)
group.PUT("", controller.UpdatePushRecord)
}
}
...@@ -63,8 +63,6 @@ func Load(r *gin.Engine, middleware ...gin.HandlerFunc) { ...@@ -63,8 +63,6 @@ func Load(r *gin.Engine, middleware ...gin.HandlerFunc) {
InitPrometheusRouter(r) InitPrometheusRouter(r)
// 初始化预警总览配置路由 // 初始化预警总览配置路由
InitAlertOverviewRouter(r) InitAlertOverviewRouter(r)
// 初始化推送记录配置路由
InitPushRecordRouter(r)
// 初始化工单管理路由 // 初始化工单管理路由
InitWorkOrderRouter(r) InitWorkOrderRouter(r)
} }
...@@ -451,6 +451,7 @@ func (a *AlertSvc) DocSearch(req request.ListAlert) (resp response.AlertList, er ...@@ -451,6 +451,7 @@ func (a *AlertSvc) DocSearch(req request.ListAlert) (resp response.AlertList, er
for _, hit := range sources.Hits.Hits { for _, hit := range sources.Hits.Hits {
resp.List = append(resp.List, hit.Source) resp.List = append(resp.List, hit.Source)
} }
resp.TotalCount = int64(len(resp.List))
return return
} }
...@@ -708,18 +709,25 @@ func (a *AlertSvc) Update(req request.UpdateAlert) error { ...@@ -708,18 +709,25 @@ func (a *AlertSvc) Update(req request.UpdateAlert) error {
func (a *AlertSvc) BatchPushAlert(req request.BatchPushAlert) (err error) { func (a *AlertSvc) BatchPushAlert(req request.BatchPushAlert) (err error) {
now := jsontime.Now() now := jsontime.Now()
resp, err := a.DocSearch(request.ListAlert{Ids: req.Ids}) alertList, err := a.DocSearch(request.ListAlert{Ids: req.Ids})
if err != nil { if err != nil {
return return
} }
for _, alert := range resp.List { for _, alert := range alertList.List {
pushRecords := alert.PushRecords pushRecords := alert.PushRecords
pushCount := len(alert.PushRecords) // TODO 批量推送短信
//alertRulesSvc := AlertRulesSvc{User: a.User}
/*var alertRulesItem response.AlertRulesItem
alertRulesItem, err = alertRulesSvc.GetDataById(request.DetailAlertRules{Id: alert.AlertRulesId})
if err != nil {
return
}*/
var phones []string
for _, v := range req.NotifyRecipients { for _, v := range req.NotifyRecipients {
pushCount++ phones = append(phones, v.Phone)
data := entity.PushRecord{ pushRecords = append(pushRecords, entity.PushRecord{
Id: pushCount,
AlertId: alert.Id, AlertId: alert.Id,
AlertRulesId: alert.AlertRulesId, AlertRulesId: alert.AlertRulesId,
RiskLevel: alert.RiskLevel, RiskLevel: alert.RiskLevel,
...@@ -727,19 +735,58 @@ func (a *AlertSvc) BatchPushAlert(req request.BatchPushAlert) (err error) { ...@@ -727,19 +735,58 @@ func (a *AlertSvc) BatchPushAlert(req request.BatchPushAlert) (err error) {
SystemAccount: v.SystemAccount, SystemAccount: v.SystemAccount,
PushTime: now, PushTime: now,
PushType: 2, PushType: 2,
Status: 0, // TODO 需要调用之后更新 Status: 1,
UserName: v.UserName, UserName: v.UserName,
Phone: v.Phone, Phone: v.Phone,
CreatedBy: a.User.SystemAccount, CreatedBy: a.User.SystemAccount,
CreatedAt: now, CreatedAt: now,
UpdatedBy: a.User.SystemAccount, UpdatedBy: a.User.SystemAccount,
UpdatedAt: now, UpdatedAt: now,
})
}
for _, method := range req.NotifyMethod {
switch method { // dingtalk sms
case "sms": // 发送短信
smsErr := a.Sms(
phones,
alert.ClassParentName,
alert.ClassName,
alert.AlertPoint,
alert.MetricConfigName,
cast.ToString(alert.CurrentValue),
constant.RiskLeveText(alert.RiskLevel))
if smsErr != nil { // 短信推送失败
for i := 0; i < len(pushRecords); i++ {
pushRecords[i].Status = 2
}
}
case "dingtalk":
smsErr := a.DingTalkMsg(
phones,
alert.ClassParentName,
alert.ClassName,
alert.AlertPoint,
alert.MetricConfigName,
cast.ToString(alert.CurrentValue),
constant.RiskLeveText(alert.RiskLevel))
if smsErr != nil { // 短信推送失败
for i := 0; i < len(pushRecords); i++ {
pushRecords[i].Status = 2
}
}
} }
pushRecords = append(pushRecords, data)
} }
for i := 0; i < len(pushRecords); i++ {
pushRecords[i].Id = i + 1
}
err = a.DocUpdate(request.UpdateAlert{ err = a.DocUpdate(request.UpdateAlert{
Id: alert.Id, Id: alert.Id,
PushCount: len(pushRecords),
PushRecords: pushRecords, PushRecords: pushRecords,
}) })
if err != nil { if err != nil {
......
...@@ -117,30 +117,30 @@ func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Messag ...@@ -117,30 +117,30 @@ func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Messag
pushRecords []entity.PushRecord pushRecords []entity.PushRecord
) )
for k, v := range alertRulesItem.NotifyRecipients {
phones = append(phones, v.Phone)
pushRecords = append(pushRecords, entity.PushRecord{
Id: k + 1,
AlertId: createAlert.Id,
AlertRulesId: createAlert.AlertRulesId,
RiskLevel: createAlert.RiskLevel,
NotifyMethod: alertRulesItem.NotifyMethod,
SystemAccount: v.SystemAccount,
PushTime: now,
PushType: 1,
Status: 1,
UserName: v.UserName,
Phone: v.Phone,
CreatedBy: a.User.SystemAccount,
CreatedAt: now,
UpdatedBy: a.User.SystemAccount,
UpdatedAt: now,
})
}
for _, method := range alertRulesItem.NotifyMethod { for _, method := range alertRulesItem.NotifyMethod {
for k, v := range alertRulesItem.NotifyRecipients {
phones = append(phones, v.Phone)
pushRecords = append(pushRecords, entity.PushRecord{
Id: k + 1,
AlertId: createAlert.Id,
AlertRulesId: createAlert.AlertRulesId,
RiskLevel: createAlert.RiskLevel,
NotifyMethod: alertRulesItem.NotifyMethod,
SystemAccount: v.SystemAccount,
PushTime: now,
PushType: 1,
Status: 1,
UserName: v.UserName,
Phone: v.Phone,
CreatedBy: a.User.SystemAccount,
CreatedAt: now,
UpdatedBy: a.User.SystemAccount,
UpdatedAt: now,
})
}
switch method { // dingtalk sms switch method { // dingtalk sms
case "sms": // 发送短信 case "sms": // 发送短信
smsErr := alertSvc.Sms( smsErr := alertSvc.Sms(
phones, phones,
createAlert.ClassParentName, createAlert.ClassParentName,
...@@ -157,7 +157,8 @@ func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Messag ...@@ -157,7 +157,8 @@ func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Messag
} }
case "dingtalk": case "dingtalk":
smsErr := alertSvc.DingTalkMsg(phones, smsErr := alertSvc.DingTalkMsg(
phones,
createAlert.ClassParentName, createAlert.ClassParentName,
createAlert.ClassName, createAlert.ClassName,
createAlert.AlertPoint, createAlert.AlertPoint,
...@@ -170,8 +171,8 @@ func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Messag ...@@ -170,8 +171,8 @@ func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Messag
} }
} }
} }
err = alertSvc.Update(request.UpdateAlert{Id: createAlert.Id, PushRecords: pushRecords})
} }
err = alertSvc.Update(request.UpdateAlert{Id: createAlert.Id, PushRecords: pushRecords})
default: // 旧数据,更新或解决 default: // 旧数据,更新或解决
......
package service
import (
"github.com/jinzhu/copier"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime"
"xorm.io/xorm"
)
type PushRecordSvc struct {
User entity.SystemUserInfo
}
func (m *PushRecordSvc) Add(session *xorm.Session, req request.AddPushRecord) (id string, err error) {
now := jsontime.Now()
data := entity.PushRecord{
CreatedBy: m.User.SystemAccount,
CreatedAt: now,
UpdatedBy: m.User.SystemAccount,
UpdatedAt: now,
}
_ = copier.Copy(&data, &req)
_, err = session.Insert(&data)
if err != nil {
return
}
return
}
func (m *PushRecordSvc) Update(session *xorm.Session, req request.UpdatePushRecord) error {
now := jsontime.Now()
data := entity.PushRecord{
UpdatedBy: m.User.SystemAccount,
UpdatedAt: now,
}
_ = copier.Copy(&data, &req)
_, err := session.ID(req.Id).Update(&data)
if err != nil {
return err
}
return nil
}
func (m *PushRecordSvc) GetDataById(req request.DetailPushRecord) (resp response.PushRecordItem, err error) {
now := jsontime.Time{}
data := response.PushRecordItem{
PushRecord: entity.PushRecord{
Id: 1,
AlertId: 1,
AlertRulesId: "83343ef6-4a99-47bd-abb4-bcff52feb2ec",
RiskLevel: 1,
NotifyMethod: []string{"dingtalk", "sms"},
SystemAccount: "xiaowang",
PushTime: now,
PushType: 1,
Status: 1,
CreatedBy: "admin",
CreatedAt: now,
UpdatedBy: "admin",
UpdatedAt: now,
},
}
resp = data
return
}
func (m *PushRecordSvc) List(req request.ListPushRecord) (resp response.PushRecordList, err error) {
now := jsontime.Time{}
data1 := response.PushRecordItem{
PushRecord: entity.PushRecord{
Id: 1,
AlertRulesId: "83343ef6-4a99-47bd-abb4-bcff52feb2ec",
RiskLevel: 1,
SystemAccount: "xiaowang",
PushTime: now,
PushType: 1,
Status: 1,
CreatedBy: "admin",
CreatedAt: now,
UpdatedBy: "admin",
UpdatedAt: now,
NotifyMethod: []string{"dingtalk", "sms"},
},
}
data2 := response.PushRecordItem{
PushRecord: entity.PushRecord{
Id: 1,
AlertRulesId: "83343ef6-4a99-47bd-abb4-bcff52feb2ec",
RiskLevel: 2,
SystemAccount: "xiaozhang",
PushTime: now,
PushType: 2,
Status: 2,
CreatedBy: "admin",
CreatedAt: now,
UpdatedBy: "admin",
UpdatedAt: now,
NotifyMethod: []string{"dingtalk", "sms"},
},
}
resp.List = append(resp.List, data1, data2)
resp.TotalCount = int64(len(resp.List))
return
}
func (m *PushRecordSvc) Delete(ids []string) (err error) {
db, err := client.GetDbClient()
if err != nil {
return
}
_, err = db.NewSession().In("id", ids).Delete(new(entity.PushRecord))
return
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment