效果展示

配置文件
{
"dingding": {
"token": "SECxxx",
"webhook": "https://oapi.dingtalk.com/robot/send?access_token=xxx"
},
"alert": {
"filter_type": "black",
"white_list": [],
"black_list": []
}
}
markdown模板
#### <font color="black">{{.Src.AlertName}}</font>
>简介:<font color="black">{{.Src.RuleName}}</font><br>
>级别:<font color="{{.Color}}">{{.Src.Level}}</font><br>
>产品:<font color="black">{{.Src.Product}}</font><br>
>集群:<font color="black">{{.Src.Cluster}}</font><br>
>机器:<font color="black">{{.Src.Machine}}</font><br>
>时间:<font color="black">{{.Src.Time}}</font><br>
>详情:<font color="black">{{.Src.Detail}}</font><br>
>告警源:<font color="">{{.Src.Source}}</font><br>
代码
package service
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
"text/template"
"time"
"zx_alert/config"
"zx_alert/pkg/model"
logg "zx_alert/utils/log"
)
const (
tmpl = `#### <font color="black">{{.Src.AlertName}}</font>
>简介:<font color="black">{{.Src.RuleName}}</font><br>
>级别:<font color="{{.Color}}">{{.Src.Level}}</font><br>
>产品:<font color="black">{{.Src.Product}}</font><br>
>集群:<font color="black">{{.Src.Cluster}}</font><br>
>机器:<font color="black">{{.Src.Machine}}</font><br>
>时间:<font color="black">{{.Src.Time}}</font><br>
>详情:<font color="black">{{.Src.Detail}}</font><br>
>告警源:<font color="">{{.Src.Source}}</font><br>`
)
type DingDingPusher struct {
Dest string
Src AlertMsg
Color string
}
type AlertMsg struct {
RuleName string
AlertName string
Level string
Product string
Cluster string
Machine string
Time string
Detail string
Source string
}
func NewDingDingPusher(data model.AsoWebhookAlarm) *DingDingPusher {
var (
level string
cluster string
product string
machine string
color string
)
switch data.EventLevel {
case "FATAL":
level = "P1"
color = "red"
case "SERIOUS":
level = "P2"
color = "orange"
case "NORMAL":
level = "P3"
color = "yellow"
case "NOTIFY":
level = "P4"
color = "greeen"
}
if data.Cluster == "" {
cluster = "-"
} else {
cluster = data.Cluster
}
if data.Machine == "" {
machine = "-"
} else {
machine = data.Machine
}
if data.Product == "" {
product = "-"
} else {
product = data.Product
}
alertMsg := AlertMsg{
RuleName: data.RuleName,
AlertName: data.AlertName,
Level: level,
Product: product,
Cluster: cluster,
Machine: machine,
Time: time.Unix(0, data.UpdateTime*int64(time.Millisecond)).Format("2006-01-02 15:04:05"),
Detail: data.Message,
Source: data.DataSource,
}
return &DingDingPusher{
Src: alertMsg,
Dest: "",
Color: color,
}
}
func (dp *DingDingPusher) RenderTemplate() error {
t := template.Must(template.New("alert").Parse(tmpl))
var buf bytes.Buffer
if err := t.Execute(&buf, dp); err != nil {
return fmt.Errorf("error executing template: %w", err)
}
dp.Dest = buf.String()
return nil
}
type DingTalkMessage struct {
MsgType string `json:"msgtype"`
Markdown struct {
Title string `json:"title"`
Text string `json:"text"`
} `json:"markdown"`
}
type DingTalkText struct {
Content string `json:"content"`
}
func (dp *DingDingPusher) Push() error {
dingTalkMessage := DingTalkMessage{
MsgType: "markdown",
Markdown: struct {
Title string `json:"title"`
Text string `json:"text"`
}{
Title: "Alert Notifications",
Text: dp.Dest,
},
}
jsonMessage, err := json.Marshal(dingTalkMessage)
if err != nil {
return fmt.Errorf("failed to marshal message: %v", err)
}
timestamp := time.Now().UnixMilli()
sign, err := dingdingSignature(timestamp, config.Conf.DingDingConfig.Token)
if err != nil {
return fmt.Errorf("failed to dingdingSignature: %v", err)
}
var urlBuilder strings.Builder
urlBuilder.WriteString(config.Conf.DingDingConfig.Webhook)
urlBuilder.WriteString("&")
urlBuilder.WriteString("timestamp=")
urlBuilder.WriteString(strconv.FormatInt(timestamp, 10))
urlBuilder.WriteString("&")
urlBuilder.WriteString("sign=")
urlBuilder.WriteString(sign)
req, err := http.NewRequest("POST", urlBuilder.String(), bytes.NewBuffer(jsonMessage))
if err != nil {
return fmt.Errorf("failed to create HTTP request: %v", err)
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("failed to send request: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("received non-200 response: %s", resp.Status)
}
msg := fmt.Sprintf("success! alert[%v]", dp.Src)
logg.Logger.Info(msg)
return nil
}
func dingdingSignature(ts int64, token string) (string, error) {
stringToSign := fmt.Sprintf("%d\n%s", ts, token)
h := hmac.New(sha256.New, []byte(token))
h.Write([]byte(stringToSign))
signData := h.Sum(nil)
signature := base64.StdEncoding.EncodeToString(signData)
encodedSignature := url.QueryEscape(signature)
return encodedSignature, nil
}