首页 > 其他分享 >13.6 编写go代码接收webhook的告警发送钉钉

13.6 编写go代码接收webhook的告警发送钉钉

时间:2024-09-10 10:23:45浏览次数:3  
标签:node string err webhook alert 13.6 json go msg


本节重点介绍 :

  • 使用钉钉机器人发送到钉钉群
  • 通过alertmanager webhook发送我们自定义的go程序中
  • 解析alert对象并拼接钉钉信息发送

需求分析

使用钉钉机器人发送到钉钉群

钉钉机器人发送群消息

通过webhook发送我们自定义的go程序中

  • 然后解析发过来的alert,转换成钉钉的数据结构。推送过去

发送代码编写

钉钉信息json结构体

type dingMsg struct {
	Msgtype string `json:"msgtype"`
	Text    struct {
		Content string `json:"content"`
	} `json:"text"`
	At struct {
		AtMobiles []string `json:"atMobiles"`
	} `json:"at"`
}

由alert对象拼接钉钉信息

  • 代码如下
// 拼接钉钉信息的函数
func buildDDContent(msg template.Alert) ([]byte, error) {
	recM := map[string]string{"firing": "已触发", "resolved": "已恢复"}

	msgTpl := fmt.Sprintf(
		"[规则名称:%s]\n"+
			"[是否已恢复:%s]\n"+
			"[告警级别:%s]\n"+
			"[触发时间:%s]\n"+
			"[看图连接:%s]\n"+
			"[当前值:%s]\n"+
			"[标签组:%s]",
		msg.Labels["alertname"],
		recM[msg.Status],
		msg.Labels["severity"],
		// prometheus使用utc时间,转换为当前时间
		msg.StartsAt.In(time.Local).Format("2006-01-02 15:03:04"),
		msg.GeneratorURL,
		msg.Annotations["value"],
		msg.Labels.SortedPairs(),


	)

	dm := dingMsg{Msgtype: "text"}
	dm.Text.Content = msgTpl
	bs, err := json.Marshal(dm)
	return bs, err
}
  • 解读一下
  • prometheus使用utc时间,转换为当前时间
  • msg.Labels 和msg.Annotations都是 map[string]string,解析相关字段拼接即可

把我们上述的代码添加到之前的alert_receive.go中

  • 完整代码如下
package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/prometheus/alertmanager/notify/webhook"
	"github.com/prometheus/alertmanager/template"
	"io/ioutil"
	"log"
	"net/http"
	"time"
)

func main() {

	listenAddress := flag.String("addr", ":5001",
		"Address on which to expose metrics and web interface.")
	flag.Parse()
	r := gin.Default()

	r.POST("/alert", alertReceive)
	r.Run(*listenAddress) // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}

func alertReceive(c *gin.Context) {
	var msg webhook.Message
	if err := c.BindJSON(&msg); err != nil {
		c.JSON(400, errors.New("invalid args"))
		return
	}
	baseMsg := fmt.Sprintf("[状态:%s][报警条数:%d]", msg.Status, len(msg.Alerts))
	log.Printf("[alertReceive][baseMsg:%+v]", baseMsg)
	for i := 0; i < len(msg.Alerts); i++ {

		alert := msg.Alerts[i]
		bs, _ := buildDDContent(alert)

		log.Printf("[detail][%d/%d][alert:%+v]", i+1, len(msg.Alerts), alert)
		sendToDing(bs)
	}
	c.JSON(200, "ok")
}

type dingMsg struct {
	Msgtype string `json:"msgtype"`
	Text    struct {
		Content string `json:"content"`
	} `json:"text"`
	At struct {
		AtMobiles []string `json:"atMobiles"`
	} `json:"at"`
}

// 拼接钉钉信息的函数
func buildDDContent(msg template.Alert) ([]byte, error) {
	recM := map[string]string{"firing": "已触发", "resolved": "已恢复"}

	msgTpl := fmt.Sprintf(
		"[规则名称:%s]\n"+
			"[是否已恢复:%s]\n"+
			"[告警级别:%s]\n"+
			"[触发时间:%s]\n"+
			"[看图连接:%s]\n"+
			"[当前值:%s]\n"+
			"[标签组:%s]",
		msg.Labels["alertname"],
		recM[msg.Status],
		msg.Labels["severity"],
		// prometheus使用utc时间,转换为当前时间
		msg.StartsAt.In(time.Local).Format("2006-01-02 15:03:04"),
		msg.GeneratorURL,
		msg.Annotations["value"],
		msg.Labels.SortedPairs(),


	)

	dm := dingMsg{Msgtype: "text"}
	dm.Text.Content = msgTpl
	bs, err := json.Marshal(dm)
	return bs, err
}

func sendToDing(jsonByte []byte) {
	apiUrl := "https://oapi.dingtalk.com/robot/send?access_token=75f08bf6f2fa40d45bc987608fa3ffa860bc9d8e2cd2b6099a5cc644ba0b3c50"

	req, err := http.NewRequest("POST", apiUrl, bytes.NewBuffer(jsonByte))
	if err != nil {
		return
	}
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Printf("[http.post.request.err][url:%v][err:%v]", apiUrl, err)
		return
	}
	defer resp.Body.Close()

	log.Printf("response Status:%v", resp.Status)
	log.Printf("response Headers:%v", resp.Header)
	body, _ := ioutil.ReadAll(resp.Body)
	log.Printf("response Body:%v", string(body))
}

修改prometheus侧配置

  • rule配置文件添加 value在annotation中
groups:
- name: alert_g_1
  rules:
  - alert: node_load too high
    expr:  node_memory_Active_bytes>0
    labels:
      severity: critical
      node_name: abc
    annotations:
      summary: 机器太累了
      value: "{{ $value }}"

- name: alert_g_2
  rules:
  - alert: mysql_qps too high
    expr: mysql_global_status_queries >0
    labels:
      severity: warning
      node_name: abc
    annotations:
      summary: mysql太累了
      value: "{{ $value }}"
  • service文件中添加 --web.external-url=http://172.20.70.215:9090/
  • 这个代表 最后告警中的 GeneratorURL字段使用这个链接前缀,钉钉告警中的看图链接能直接访问到对应的prometheus
  • 重启prometheus和alertmanager

观察5001 receive到的报警

2021/08/19 11:39:06 [alertReceive][baseMsg:[状态:firing][报警条数:1]]
2021/08/19 11:39:06 [detail][1/1][alert:{Status:firing Labels:map[alertname:node_load too high instance:172.20.70.205:9100 job:node_exporter node_name:abc severity:critical] Annotat
ions:map[summary:机器太累了 value:1.0065547264e+10] StartsAt:2021-08-19 03:39:01.628 +0000 UTC EndsAt:0001-01-01 00:00:00 +0000 UTC GeneratorURL:http://172.20.70.215:9090/graph?g0.e
xpr=node_memory_Active_bytes+%3E+0&g0.tab=1 Fingerprint:0ccc723bf948e5fb}]
2021/08/19 11:39:06 response Status:200 OK
2021/08/19 11:39:06 response Headers:map[Cache-Control:[no-cache] Connection:[keep-alive] Content-Type:[application/json] Date:[Thu, 19 Aug 2021 03:39:06 GMT] Server:[DingTalk/1.0.0
]]
2021/08/19 11:39:06 response Body:{"errcode":0,"errmsg":"ok"}
[GIN] 2021/08/19 - 11:39:06 |?[97;42m 200 ?[0m|    181.7246ms |   172.20.70.215 |?[97;46m POST    ?[0m "/alert"

观察钉钉群收到的信息

[规则名称:node_load too high]
[是否已恢复:已触发]
[告警级别:critical]
[触发时间:2021-08-19 11:11:39]
[看图连接:http://172.20.70.215:9090/graph?g0.expr=node_memory_Active_bytes+%3E+0&g0.tab=1]
[当前值:1.0065547264e+10]
[标签组:[{alertname node_load too high} {instance 172.20.70.205:9100} {job node_exporter} {node_name abc} {severity critical}]]

截图

13.6 编写go代码接收webhook的告警发送钉钉_prometheus

本节重点总结 :

  • 使用钉钉机器人发送到钉钉群
  • 通过alertmanager webhook发送我们自定义的go程序中
  • 解析alert对象并拼接钉钉信息发送


标签:node,string,err,webhook,alert,13.6,json,go,msg
From: https://blog.51cto.com/moonfdd/11969547

相关文章

  • 2024-09-04:用go语言,给定一个长度为n的数组 happiness,表示每个孩子的幸福值,以及一个正
    2024-09-04:用go语言,给定一个长度为n的数组happiness,表示每个孩子的幸福值,以及一个正整数k,我们需要从这n个孩子中选出k个孩子。在筛选过程中,每轮选择一个孩子时,所有尚未选中的孩子的幸福值都会减少1。需要注意的是,幸福值不能降低到负数,只有在其为正数时才能减少。我们的目标是尽可......
  • 在执行django定时任务中,遇到的celery woker生命周期问题
    在执行django定时任务中,遇到的celerywoker生命周期问题问题描述:当我celeryworker正常启动时,我的定时任务在admin也正常跑,可总是跑完之后和预期结果对不上,结果我发现了个问题,只能在生产环境测的出来,本地一点问题也没有,先看代码。我的定时任务task.py部分代码如下:frompo......
  • 离线标注 - mastergo - 资源社区 - 插件广场 (设计稿打包离线页面)- marklion+figma 平
    离线标注-mastergo-资源社区-插件广场(设计稿打包离线页面)-marklion+figma平替同事用的标记狮marklion做的设计稿,离线包特别好,但是需要配合figma或者苹果的设计器。国内的话,可以用mastergo里面有个离线标注插件,功能一样。又找了个xd的下载,回头试试和mar......
  • COMP2230/COMP6230 Algorithms
    TheUniversityofNewcastle,AustraliaSchoolofInformationandPhysicalSciencesCOMP2230/COMP6230AlgorithmsAssignment1Marks100Weight15%IndividualSubmissionviaCanvas1LearningOutcomesThisassignmentwillrequirestudentsto:Applyspecific......
  • PHP 程序员学会了 Go 语言就能唬住面试官吗?
    大家好,我是码农先森。唬住了50k,唬不住就5k。这句话一直是PHP程序员之间相互吹捧、吹牛逼的笑点,每次面试过后都会挠挠头上仅剩的几根头发,回想自己是否吹牛逼会过了头。我经常在微信程序员撕逼群里,看到群友因为某个技术点而争执不休,时而讨论这个技术能不能在面试过程中突出自......
  • Python与Go在AIGC领域的应用:比较与分析
    1.引言AIGC(ArtificialIntelligenceGeneratedContent,人工智能生成内容)近年来在图像生成、自然语言处理、代码生成等多个领域取得了重大进展。无论是文本生成、图像创作,还是自动代码生成,AIGC都在推动内容创作进入一个全新的高度。Python凭借其简洁的语法和丰富的机器学习、深度学......
  • Go语言编译时为exe添加图标和属性信息的方法
    在使用Go语言开发应用程序时,有个非常方便的地方就是编译得到的可执行文件可以不依赖任何动态链接库、并且不需要任何运行环境即可运行,这一点Java就没那么方便了。不过在Windows上编译得到的exe文件,默认是不带图标和任何属性信息的,那么怎么才能让我们编译得到的可执行文件带上图标......
  • 【Django开发】前后端分离django美多商城项目第10篇:收货地址,1. 展示地址接口设计和定
    本教程的知识点为:项目准备项目准备配置1.修改settings/dev.py文件中的路径信息2.INSTALLED_APPS3.数据库用户部分图片1.后端接口设计:视图原型2.具体视图实现用户部分使用Celery完成发送判断帐号是否存在1.判断用户名是否存在后端接口设计:用户部分JWT什......
  • Win11系统提示找不到rdvgogl32.dll文件的解决办法
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个rdvgogl32.dll文件(挑选合适的版本文件)把它......
  • Leangoo领歌:一站式敏捷缺陷管理平台,助力产品迭代
    ​在开发过程中,缺陷(BUG)管理一直是项目管理中的一个关键环节。及时发现并修复BUG,不仅能够提高产品质量,还能有效提升团队的工作效率和用户满意度。在敏捷开发中,快速迭代和频繁交付的特点使得缺陷管理的重要性更加凸显。Leangoo领歌​​​​​​​作为一款敏捷研发全流程管理工具,提......