Skip to content

add dingtalk alarm #43

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions configs/alarm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@ wechat:
agentid: 1000008
corpid: ""
corpsecret: ""
dingtalk:
enabled: true
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dingtalk.enabled 默认为false比较好

accesstoken: "xxxx"
worker:
sms: 10 #send sms concurrency
mail: 50 #send mail concurrency
wechat: 50 #send wechat concurrency
dingtalk: 50 #send dingtalk concurrency
# remain: 30
29 changes: 18 additions & 11 deletions modules/alarm/g/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ import (
)

type GlobalConfig struct {
Debug bool `yaml:"debug"`
SmsEnabled bool `yaml:"smsEnabled"`
Remain int `yaml:"remain"`
Rpc *RpcConfig `yaml:"rpc"`
Web *WebConfig `yaml:"web"`
Worker *WorkerConfig `yaml:"worker"`
Smtp *SmtpConfig `yaml:"smtp"`
WeChat *WeChatConfig `yaml:"wechat"`
Debug bool `yaml:"debug"`
SmsEnabled bool `yaml:"smsEnabled"`
Remain int `yaml:"remain"`
Rpc *RpcConfig `yaml:"rpc"`
Web *WebConfig `yaml:"web"`
Worker *WorkerConfig `yaml:"worker"`
Smtp *SmtpConfig `yaml:"smtp"`
WeChat *WeChatConfig `yaml:"wechat"`
DingTalk *DingTalkConfig `yaml:"dingtalk"`
}

type MysqlConfig struct {
Expand All @@ -37,9 +38,10 @@ type WebConfig struct {
}

type WorkerConfig struct {
Sms int `yaml:"sms"`
Mail int `yaml:"mail"`
WeChat int `yaml:"wechat"`
Sms int `yaml:"sms"`
Mail int `yaml:"mail"`
WeChat int `yaml:"wechat"`
DingTalk int `yaml:"dingtalk"`
}

type SmtpConfig struct {
Expand All @@ -59,6 +61,11 @@ type WeChatConfig struct {
CorpSecret string `yaml:corpsecret`
}

type DingTalkConfig struct {
Enabled bool `yaml:"enabled"`
AccessToken string `yaml:"accesstoken"`
}

var (
Config *GlobalConfig
configLock = new(sync.RWMutex)
Expand Down
15 changes: 14 additions & 1 deletion modules/alarm/g/var.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ type WeChat struct {
Content string `json:"content"`
}

type DingTalk struct {
Tos string `json:"tos"`
Content string `json:"content"`
}

func (this *Sms) String() string {
return fmt.Sprintf(
"<Tos:%s, Content:%s>",
Expand All @@ -46,4 +51,12 @@ func (this *WeChat) String() string {
this.Tos,
this.Content,
)
}
}

func (this *DingTalk) String() string {
return fmt.Sprintf(
"<Tos:%s, Content:%s>",
this.Tos,
this.Content,
)
}
29 changes: 29 additions & 0 deletions modules/alarm/sender/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,23 @@ func BuildWeChat(event *dataobj.Event) string {
)
}

func BuildDingTalk(event *dataobj.Event) string {
strategy, _ := cache.StrategyMap.Get(event.StrategyId)
respTime := fmt.Sprintf("%dms", event.RespTime)
return fmt.Sprintf(
"### 站点监控\n>- 站点状态: **%s**\n>- 站点地址: **<%s>**\n>- 备注信息: **%s**\n>- 监控主机: **%s**\n>- 返回状态码: **%s**\n>- 响应时间: **%s**\n>- 告警时间: **%s**\n>- 告警次数: **%d**\n",
//"状态:%s\nUrl:%s\n备注:%s\nIP:%s\n返回状态码:%s\n响应时间:%s\n时间:%s\n报警次数:%d\n",
event.Status,
event.Url,
strategy.Note,
event.Ip,
event.RespCode,
respTime,
humanTime(event.EventTime),
event.CurrentStep,
)
}

func humanTime(ts int64) string {
return time.Unix(ts, 0).Format("2006-01-02 15:04:05")
}
Expand Down Expand Up @@ -113,3 +130,15 @@ func WriteWeChat(tos []string, content string) {
WeChatWorkerChan <- 1
go sendWeChat(weChat)
}

func WriteDingTalk(tos []string, content string) {
if !g.Config.DingTalk.Enabled {
return
}
if len(tos) == 0 {
return
}
DingTalk := &g.DingTalk{Tos: strings.Join(tos, ","), Content: content}
DingTalkWorkerChan <- 1
go sendDingTalk(DingTalk)
}
67 changes: 62 additions & 5 deletions modules/alarm/sender/sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,44 +25,52 @@ import (
)

var (
SmsWorkerChan chan int
MailWorkerChan chan int
WeChatWorkerChan chan int
requestError = errors.New("request error,check url or network")
SmsWorkerChan chan int
MailWorkerChan chan int
WeChatWorkerChan chan int
DingTalkWorkerChan chan int
requestError = errors.New("request error,check url or network")
)

const (
// 发送消息使用导的url
sendUrl = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="
// 获取token使用导的url
getToken = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid="
// 钉钉webhook
webHook = "https://oapi.dingtalk.com/robot/send?access_token="
)

func Init() {
workerConfig := g.Config.Worker
SmsWorkerChan = make(chan int, workerConfig.Sms)
MailWorkerChan = make(chan int, workerConfig.Mail)
WeChatWorkerChan = make(chan int, workerConfig.WeChat)
DingTalkWorkerChan = make(chan int, workerConfig.DingTalk)
}

func SendEvent(event *dataobj.Event) {
mail := make([]string, 0)
sms := make([]string, 0)
weChat := make([]string, 0)
dingTalk := make([]string, 0)
users := getUsers(event.StrategyId)

mailContent := BuildMail(event)
smsContent := BuildSms(event)
weChatContent := BuildWeChat(event)
dingTalkContent := BuildDingTalk(event)
for _, user := range users {
mail = append(mail, user.Email)
sms = append(sms, user.Phone)
weChat = append(weChat, user.Wechat)
dingTalk = append(dingTalk, user.Phone)
}

WriteSms(sms, smsContent)
WriteMail(mail, smsContent, mailContent)
WriteWeChat(weChat, weChatContent)
WriteDingTalk(dingTalk, dingTalkContent)
}

func sendSms(phone string, sms string) {
Expand Down Expand Up @@ -135,6 +143,28 @@ func sendWeChat(weChat *g.WeChat) {
}
}

func sendDingTalk(dingTalk *g.DingTalk) {
defer func() {
<-DingTalkWorkerChan
}()
var msg = dingTalkMsg{
MsgType: "markdown",
MarkDown: map[string]string{"title": "站点监控", "text": dingTalk.Content},
}
buf, err := json.Marshal(msg)
if err != nil {
log.Println(err, "marshal dingTalk msg error")
}
err = SendDingTalk(g.Config.DingTalk.AccessToken, buf)
if err != nil {
log.Println(err, "send dingTalk")
} else {
log.Println("==dingTalk==>>>>", dingTalk)
log.Println("<<<<==dingTalk==", string(buf))
}

}

func getUsers(sid int64) []*dataobj.User {
var usersResp api.UsersResponse
var users []*dataobj.User
Expand Down Expand Up @@ -169,7 +199,13 @@ type weChatMsg struct {
Safe int `json:"safe"`
}

// 定义微信错误返回结构体
// 定义钉钉markdown消息结构体
type dingTalkMsg struct {
MsgType string `json:"msgtype"`
MarkDown map[string]string `json:"markdown"`
}

// 定义微信/钉钉错误返回结构体
type sendMsgError struct {
ErrCode int `json:"errcode`
ErrMsg string `json:"errmsg"`
Expand Down Expand Up @@ -219,3 +255,24 @@ func SendMsg(AccessToken string, msgBody []byte) error {
}
return nil
}

// 发送钉钉
func SendDingTalk(AccessToken string, msgBody []byte) error {
body := bytes.NewBuffer(msgBody)
resp, err := http.Post(webHook+AccessToken, "application/json", body)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的 err 没有处理哈

if resp.StatusCode != 200 {
return requestError
}
buf, _ := ioutil.ReadAll(resp.Body)
resp.Body.Close()
var e sendMsgError
err = json.Unmarshal(buf, &e)
if err != nil {
return err
}
if e.ErrCode != 0 && e.ErrMsg != "ok" {
return errors.New(string(buf))
}
return nil

}