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

feat: 预警消息

parent add99f25
......@@ -3,7 +3,7 @@ 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
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:重大风险
......
......@@ -42,6 +42,7 @@ type Config struct {
SmsAccessKeyId string
SmsAccessSecret string
SmsTemplateLogin string
SmsTemplateAlert string
SmsWorkOrderTemplate string
SmsSignName string
......
......@@ -81,16 +81,17 @@ func initConfig() {
//PublicKeySSH: util.SetEnvStr("PUBLIC_KEY_SSH", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCw4WT05QHzCD19348MfJfycS1NI9Jlj62PGrZ1rU9/kWQif5TV1rqHZ6qjAX2WfK+W3u4SV51MhZBkMZZOgZgJmdGiaZJkSmj+8gj6XU/bxslUd+BYUKqbE18gFkVDgqs6n2tcqJ2at3x+WEr81Msk2qvKuGEiIOzcJPICWKxwiw== chenzilong@example.com\n"),
OrderDingTalkAccessToken: util.SetEnvStr("ORDER_DING_TALK_ACCESS_TOKEN", "203fe1644b446bba0a34e6e622c523d39ee9916fdad94b9c64224449f659e20b"),
OrderDingTalkSecret: util.SetEnvStr("ORDER_DING_TALK_SECRET", "SECa73d8372e336451c9daf29a99f750ee1bdd170c1dab910eab9cd06d729a831b7"),
SmsAccessKeyId: util.SetEnvStr("SMS_ACCESS_KEY", "LTAI4GBcVubRjzX7ABPcHnhB"), // 短信key
SmsAccessSecret: util.SetEnvStr("SMS_ACCESS_SECRET", "dYE2dtABFOqYtK1ijcrits0yedHkw7"), // 短信secret
SmsTemplateLogin: util.SetEnvStr("SMS_TEMPLATE_LOGIN", "SMS_212925130"), // 短信验证码模板
SmsWorkOrderTemplate: util.SetEnvStr("SMS_TEMPLATE_LOGIN", "SMS_462020767"), // 短信工单下发模板
SmsSignName: util.SetEnvStr("SMS_SIGN_NAME", "比格数据"), // 签名
AweRestURL: util.SetEnvStr("AWE_REST_URL", "http://awecloud-rest.beagle-system/awecloud/rest"), // awecloud-rest
KubernetesToken: util.SetEnvStr("AWE_REST_K8S_TOKEN", "eyJhbGciOiJSUzI1NiIsImtpZCI6InJ1alJzNEVGamN5UC0wRU1rS1BKQ0JZVUtNNWpzR0t2bmlrSlJhY2Q3R00ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJiZWFnbGUtc3lzdGVtIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InJvb3QiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoicm9vdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjRlMDM0OTI3LTc0ZTMtNDQ5Yy1hN2RlLWExMGE3MjU1NGYyMCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpiZWFnbGUtc3lzdGVtOnJvb3QifQ.YPLE_E2kIeo-YFQtKScBt5p4KhnniJF9n3iWN2i9UMYS06lIsq2-2wBrgON-YsJihWJupYyDQRiZ9h8bUWTrQzhnpsnuJ_aUclKyAw3QOT9rjvZhJp7qP--27dmdspSHncKtvIiprWE7UTUKzvF33WsMB0fSYFqYXOggNFMoT-fXmWwUXjgar3op0iOl3c3deJ_GeBzFyLSHEuGM7OVdjU8032aUmTen0Kji_P1yB4-O3Iqd0OdVs33BQy_tycjbxhQ8TDEpqrqhLnXjAwJCprLDEpFMx7ODZbjB9Wmuns8yJhaRDxTO47rTME7ZIAxjZ-zLR_QybtW97rlwnUTaNw"), // k8s token
OpenSearchAddresses: util.SetEnvStr("Open_Search_Addresses", "https://so-opensearch.wodcloud.com"), // 短信验证码模板
OpenSearchUserName: util.SetEnvStr("Open_Search_User_Name", ""), // 短信验证码模板
OpenSearchPassword: util.SetEnvStr("Open_Search_Password", ""), // 短信验证码模板
SmsAccessKeyId: util.SetEnvStr("SMS_ACCESS_KEY", "LTAI4GBcVubRjzX7ABPcHnhB"), // 短信key
SmsAccessSecret: util.SetEnvStr("SMS_ACCESS_SECRET", "dYE2dtABFOqYtK1ijcrits0yedHkw7"), // 短信secret
SmsTemplateLogin: util.SetEnvStr("SMS_TEMPLATE_LOGIN", "SMS_212925130"), // 短信验证码模板
SmsTemplateAlert: util.SetEnvStr("Sms_Template_Alert", "SMS_461975765"), // 预警短信模板 // 短信工单下发模板
SmsWorkOrderTemplate: util.SetEnvStr("SMS_TEMPLATE_LOGIN", "SMS_462020767"), // 短信工单下发模板
SmsSignName: util.SetEnvStr("SMS_SIGN_NAME", "比格数据"), // 签名
AweRestURL: util.SetEnvStr("AWE_REST_URL", "http://awecloud-rest.beagle-system/awecloud/rest"), // awecloud-rest
KubernetesToken: util.SetEnvStr("AWE_REST_K8S_TOKEN", "eyJhbGciOiJSUzI1NiIsImtpZCI6InJ1alJzNEVGamN5UC0wRU1rS1BKQ0JZVUtNNWpzR0t2bmlrSlJhY2Q3R00ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJiZWFnbGUtc3lzdGVtIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InJvb3QiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoicm9vdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjRlMDM0OTI3LTc0ZTMtNDQ5Yy1hN2RlLWExMGE3MjU1NGYyMCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpiZWFnbGUtc3lzdGVtOnJvb3QifQ.YPLE_E2kIeo-YFQtKScBt5p4KhnniJF9n3iWN2i9UMYS06lIsq2-2wBrgON-YsJihWJupYyDQRiZ9h8bUWTrQzhnpsnuJ_aUclKyAw3QOT9rjvZhJp7qP--27dmdspSHncKtvIiprWE7UTUKzvF33WsMB0fSYFqYXOggNFMoT-fXmWwUXjgar3op0iOl3c3deJ_GeBzFyLSHEuGM7OVdjU8032aUmTen0Kji_P1yB4-O3Iqd0OdVs33BQy_tycjbxhQ8TDEpqrqhLnXjAwJCprLDEpFMx7ODZbjB9Wmuns8yJhaRDxTO47rTME7ZIAxjZ-zLR_QybtW97rlwnUTaNw"),
OpenSearchAddresses: util.SetEnvStr("Open_Search_Addresses", "https://so-opensearch.wodcloud.com"), // 短信验证码模板
OpenSearchUserName: util.SetEnvStr("Open_Search_User_Name", ""), // 短信验证码模板
OpenSearchPassword: util.SetEnvStr("Open_Search_Password", ""), // 短信验证码模板
}
}
......
......@@ -4,11 +4,13 @@ import (
"context"
"errors"
"fmt"
"github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi"
json "github.com/json-iterator/go"
"github.com/olivere/elastic/v7"
"github.com/opensearch-project/opensearch-go/opensearchapi"
"github.com/spf13/cast"
"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/vo/request"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response"
......@@ -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/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/resp"
"go.uber.org/zap"
"io"
"log"
......@@ -873,3 +876,75 @@ func (a *AlertSvc) DisposeAlert(req request.DisposeAlert) (err error) {
time.Sleep(time.Second)
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
return
}
var newData bool
var isNewAlert bool
if alertItem.Id == 0 { // 新数据
newData = true
isNewAlert = true
}
switch newData {
switch isNewAlert {
case true: // 新增数据到OpenSearch
max := alertSvc.CatCount(OpenSearchIndex)
if max == 0 {
err = errors.New("failed to get doc count for index")
return
}
alertId := max + 1
......@@ -79,7 +80,7 @@ func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Messag
break
}
}
err = alertSvc.DocCreate(request.CreateAlert{Alert: entity.Alert{
createAlert := request.CreateAlert{Alert: entity.Alert{
Id: alertId,
AlertPoint: alertRulesItem.ClassParentName + "/" + alertRulesItem.MetricName,
AlertRulesId: alertRulesItem.Id,
......@@ -103,12 +104,75 @@ func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Messag
CreatedAt: now,
UpdatedBy: a.User.SystemAccount,
UpdatedAt: now,
}})
}}
err = alertSvc.DocCreate(createAlert)
if err != nil {
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: // 旧数据,更新或解决
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