Commit 84591f16 authored by 李科's avatar 李科

feat: 预警消息

parent add99f25
...@@ -3,7 +3,7 @@ package entity ...@@ -3,7 +3,7 @@ package entity
import "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime" import "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime"
type PushRecord struct { type PushRecord struct {
Id int `json:"id" xorm:"'id' pk autoincr"` // 主键id Id int `json:"id" xorm:"'id' pk autoincr"` // 主键id(数组唯一标识)
AlertId int `json:"alert_id" xorm:"alert_id"` // 告警id AlertId int `json:"alert_id" xorm:"alert_id"` // 告警id
AlertRulesId string `json:"alert_rules_id" xorm:"'alert_rules_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:重大风险 RiskLevel int `json:"risk_level" xorm:"'risk_level'"` // 风险等级,1:低风险,2:一般风险,3:较大风险,4:重大风险
......
...@@ -42,6 +42,7 @@ type Config struct { ...@@ -42,6 +42,7 @@ type Config struct {
SmsAccessKeyId string SmsAccessKeyId string
SmsAccessSecret string SmsAccessSecret string
SmsTemplateLogin string SmsTemplateLogin string
SmsTemplateAlert string
SmsWorkOrderTemplate string SmsWorkOrderTemplate string
SmsSignName string SmsSignName string
......
This diff is collapsed.
...@@ -4,11 +4,13 @@ import ( ...@@ -4,11 +4,13 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi"
json "github.com/json-iterator/go" json "github.com/json-iterator/go"
"github.com/olivere/elastic/v7" "github.com/olivere/elastic/v7"
"github.com/opensearch-project/opensearch-go/opensearchapi" "github.com/opensearch-project/opensearch-go/opensearchapi"
"github.com/spf13/cast" "github.com/spf13/cast"
"github.com/thoas/go-funk" "github.com/thoas/go-funk"
"github.com/wanghuiyt/ding"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity" "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/request"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response"
...@@ -16,6 +18,7 @@ import ( ...@@ -16,6 +18,7 @@ import (
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/constant" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/constant"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp"
"go.uber.org/zap" "go.uber.org/zap"
"io" "io"
"log" "log"
...@@ -873,3 +876,75 @@ func (a *AlertSvc) DisposeAlert(req request.DisposeAlert) (err error) { ...@@ -873,3 +876,75 @@ func (a *AlertSvc) DisposeAlert(req request.DisposeAlert) (err error) {
time.Sleep(time.Second) time.Sleep(time.Second)
return nil return nil
} }
func (a *AlertSvc) Sms(phone []string, classParentName, className, alertPoint, metricConfigName, currentValue, riskLevel string) (err error) {
var smsClient *dysmsapi.Client
smsClient, err = dysmsapi.NewClientWithAccessKey("cn-hangzhou", conf.Options.SmsAccessKeyId, conf.Options.SmsAccessSecret)
if err != nil {
conf.Logger.Error("dysmsapi client error", zap.Error(err))
}
/*
您有一条${tickettype}需要处理:预警分类:${classparentname},预警对象:${classname},预警点:${alertpoint},预警指标:${metricconfigname},预警值:${currentvalue},风险程度:${risklevel},请及时前往智能运维平台处理!
*/
params := map[string]interface{}{
"tickettype": "预警工单",
"classparentname": classParentName,
"classname": className,
"alertpoint": alertPoint,
"metricconfigname": metricConfigName,
"currentvalue": currentValue,
"risklevel": riskLevel,
}
templateParam, err := json.Marshal(params)
if err != nil {
conf.Logger.Error("序列化模板失败!", zap.Error(err))
err = resp.FAIL.ErrorDetail(err)
return
}
smsRequest := dysmsapi.CreateSendSmsRequest()
smsRequest.Scheme = "https"
smsRequest.PhoneNumbers = strings.Join(phone, ",")
smsRequest.TemplateCode = conf.Options.SmsTemplateAlert
smsRequest.SignName = conf.Options.SmsSignName
smsRequest.TemplateParam = string(templateParam)
req, err := smsClient.SendSms(smsRequest)
if err != nil {
err = resp.FAIL.ErrorDetail(err)
return
}
conf.Logger.Info("send SMS", zap.Any("req", req))
return
}
// DingTalkMsg 推送钉钉消息
func (a *AlertSvc) DingTalkMsg(phone []string, classParentName, className, alertPoint, metricConfigName, currentValue, riskLevel string) (err error) {
d := ding.Webhook{
AccessToken: conf.Options.OrderDingTalkAccessToken,
Secret: conf.Options.OrderDingTalkSecret,
}
msg := "您有一条${tickettype}需要处理:预警分类:${classparentname},预警对象:${classname},预警点:${alertpoint},预警指标:${metricconfigname},预警值:${currentvalue},风险程度:${risklevel},请及时前往智能运维平台处理!"
params := map[string]interface{}{
"tickettype": "预警工单",
"classparentname": classParentName,
"classname": className,
"alertpoint": alertPoint,
"metricconfigname": metricConfigName,
"currentvalue": currentValue,
"risklevel": riskLevel,
}
for key, value := range params {
placeholder := "${" + key + "}"
msg = strings.Replace(msg, placeholder, fmt.Sprintf("%v", value), -1)
}
err = d.SendMessageText(msg, phone...)
if err != nil {
err = resp.FAIL.ErrorDetail(err)
return
}
return
}
...@@ -60,16 +60,17 @@ func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Messag ...@@ -60,16 +60,17 @@ func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Messag
return return
} }
var newData bool var isNewAlert bool
if alertItem.Id == 0 { // 新数据 if alertItem.Id == 0 { // 新数据
newData = true isNewAlert = true
} }
switch newData { switch isNewAlert {
case true: // 新增数据到OpenSearch case true: // 新增数据到OpenSearch
max := alertSvc.CatCount(OpenSearchIndex) max := alertSvc.CatCount(OpenSearchIndex)
if max == 0 { if max == 0 {
err = errors.New("failed to get doc count for index")
return return
} }
alertId := max + 1 alertId := max + 1
...@@ -79,7 +80,7 @@ func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Messag ...@@ -79,7 +80,7 @@ func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Messag
break break
} }
} }
err = alertSvc.DocCreate(request.CreateAlert{Alert: entity.Alert{ createAlert := request.CreateAlert{Alert: entity.Alert{
Id: alertId, Id: alertId,
AlertPoint: alertRulesItem.ClassParentName + "/" + alertRulesItem.MetricName, AlertPoint: alertRulesItem.ClassParentName + "/" + alertRulesItem.MetricName,
AlertRulesId: alertRulesItem.Id, AlertRulesId: alertRulesItem.Id,
...@@ -103,12 +104,75 @@ func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Messag ...@@ -103,12 +104,75 @@ func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Messag
CreatedAt: now, CreatedAt: now,
UpdatedBy: a.User.SystemAccount, UpdatedBy: a.User.SystemAccount,
UpdatedAt: now, UpdatedAt: now,
}}) }}
err = alertSvc.DocCreate(createAlert)
if err != nil { if err != nil {
return return
} }
// 新数据发送短信
var (
phones []string
pushRecords []entity.PushRecord
)
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
case "sms": // 发送短信
smsErr := alertSvc.Sms(
phones,
createAlert.ClassParentName,
createAlert.ClassName,
createAlert.AlertPoint,
createAlert.MetricConfigName,
cast.ToString(createAlert.CurrentValue),
constant.RiskLeveText(createAlert.RiskLevel))
if smsErr != nil { // 短信推送失败
for i := 0; i < len(pushRecords); i++ {
pushRecords[i].Status = 2
}
}
case "dingtalk":
smsErr := alertSvc.DingTalkMsg(phones,
createAlert.ClassParentName,
createAlert.ClassName,
createAlert.AlertPoint,
createAlert.MetricConfigName,
cast.ToString(createAlert.CurrentValue),
constant.RiskLeveText(createAlert.RiskLevel))
if smsErr != nil { // 短信推送失败
for i := 0; i < len(pushRecords); i++ {
pushRecords[i].Status = 2
}
}
}
err = alertSvc.Update(request.UpdateAlert{Id: createAlert.Id, PushRecords: pushRecords})
}
default: // 旧数据,更新或解决 default: // 旧数据,更新或解决
switch alert.Status { switch alert.Status {
......
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