diff --git a/src/bean/entity/push_record.go b/src/bean/entity/push_record.go index 8aa3fb09c50b850abf9bd0b399c593cf2ff5d29c..9989803c4f1f0b448cea852e0bbfdc9fccdcd567 100644 --- a/src/bean/entity/push_record.go +++ b/src/bean/entity/push_record.go @@ -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:重大风险 diff --git a/src/common/conf/options.go b/src/common/conf/options.go index a918b545f261629af219f23626e9b65b258eb11b..78cf9056a5c2b22fced9f97a8988cd5efff053ca 100644 --- a/src/common/conf/options.go +++ b/src/common/conf/options.go @@ -42,6 +42,7 @@ type Config struct { SmsAccessKeyId string SmsAccessSecret string SmsTemplateLogin string + SmsTemplateAlert string SmsWorkOrderTemplate string SmsSignName string diff --git a/src/main.go b/src/main.go index 4c031f264f501163831f85d0cb95b82efd515ceb..e2403766ad84bda0bb677f03ee528b6a9a821f0c 100644 --- a/src/main.go +++ b/src/main.go @@ -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", ""), // 短信验证码模板 } } diff --git a/src/service/alert.go b/src/service/alert.go index 73f59f5567268fd4ff3932d47174459923d0e94f..2a891417761ebea96c15541c455349ea0de6e3cb 100644 --- a/src/service/alert.go +++ b/src/service/alert.go @@ -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 +} diff --git a/src/service/alert_webhook.go b/src/service/alert_webhook.go index b77d81e95d43877d8e77849bf8a8b8e306d7b9f5..5d7a7fa1ba37a1e4488283e71f1917611e380d90 100644 --- a/src/service/alert_webhook.go +++ b/src/service/alert_webhook.go @@ -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 {