prometheus实战之五:飞书通知告警

欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos

《prometheus实战》系列链接

  1. prometheus实战之一:用ansible部署
  2. prometheus实战之二:使用常见指标
  3. prometheus实战之三:告警规则
  4. prometheus实战之四:alertmanager的部署和配置

本篇概览



shellMay 13 10:04:40 deskmini alertmanager[767]: ts=2023-05-13T02:04:40.869Z caller=notify.go:732 level=warn component=dispatcher receiver=web.hook integration=webhook[0] msg="Notify attempt failed, will retry later" attempts=1 err="Post "http://192.168.50.134:8888/webhook": dial tcp http://192.168.50.134:8888/webhook: connect: connection refused"
May 13 10:09:40 deskmini alertmanager[767]: ts=2023-05-13T02:09:40.869Z caller=dispatch.go:352 level=error component=dispatcher msg="Notify for alerts failed" num_alerts=1 err="web.hook/webhook[0]: notify retry canceled after 16 attempts: Post "http://192.168.50.134:8888/webhook": dial tcp http://192.168.50.134:8888/webhook: connect: connection refused"
May 13 10:09:40 deskmini alertmanager[767]: ts=2023-05-13T02:09:40.869Z caller=notify.go:732 level=warn component=dispatcher receiver=web.hook integration=webhook[0] msg="Notify attempt failed, will retry later" attempts=1 err="Post "http://192.168.50.134:8888/webhook": dial tcp http://192.168.50.134:8888/webhook: connect: connection refused"

准备工作:飞书机器人

















源码下载

名称

链接

备注

项目主页

https://github.com/zq2599/blog_demos

该项目在GitHub上的主页

git仓库地址(https)

https://github.com/zq2599/blog_demos.git

该项目源码的仓库地址,https协议

git仓库地址(ssh)

git@github.com:zq2599/blog_demos.git

该项目源码的仓库地址,ssh协议



开发web服务,梳理开发步骤



1. 创建工程

2. 搭好web框架

3. 定义数据结构:alertmanager的请求体

4. 定义数据结构:飞书消息的请求体和响应

5. 转换器,将alertmanager请求体转换为飞书请求体

6. 主逻辑,收到alertmanager请求时向飞书发请求

7. 路由配置,将web path和主逻辑绑定

创建web工程

shellgo install github.com/cloudwego/hertz/cmd/hz@latest
shellhz new -module webhook
shellgo mod tidy
shelltree webhook                                      
webhook
  biz
      handler
          ping.go
      router
          register.go
  build.sh
  go.mod
  main.go
  router_gen.go
  router.go
  script
      bootstrap.sh

编码,alertmanager请求体定义

gopackage model

import "time"

type Alert struct {
	Labels      map[string]string `json:"labels"`
	Annotations map[string]string `json:annotations`
	StartsAt    time.Time         `json:"startsAt"`
	EndsAt      time.Time         `json:"endsAt"`
}

type Notification struct {
	Version           string            `json:"version"`
	GroupKey          string            `json:"groupKey"`
	Status            string            `json:"status"`
	Receiver          string            `json:receiver`
	GroupLabels       map[string]string `json:groupLabels`
	CommonLabels      map[string]string `json:commonLabels`
	CommonAnnotations map[string]string `json:commonAnnotations`
	ExternalURL       string            `json:externalURL`
	Alerts            []Alert           `json:alerts`
}

编码,飞书消息的请求和响应

gopackage model

// 飞书机器人支持的POST数据结构
// 请求体相关
type LarkRequest struct {
	MsgType string  `json:"msg_type"`
	Content Content `json:"content"`
}
type Content struct {
	Text string `json:"text"`
}

// 响应体相关
type LarkResponse struct {
	Code int    `json:"code"`
	Msg  string `json:"msg"`
	Data Data   `json:"data"`
}
type Data struct {
}

编码,alertmanager到飞书请求体的转换工具

gopackage util

import (
	"bytes"
	"fmt"
	"webhook/biz/model"
)

// TransformToLarkRequest 根据alertmanager的对象,创建出飞书消息的对象
func TransformToLarkRequest(notification model.Notification) (larkRequest *model.LarkRequest, err error) {
	var buffer bytes.Buffer

	// 先拿到分组情况
	buffer.WriteString(fmt.Sprintf("通知组%s,状态[%s]
告警项

", notification.GroupKey, notification.Status))

	// 每条告警逐个获取,拼接到一起
	for _, alert := range notification.Alerts {
		buffer.WriteString(fmt.Sprintf("摘要:%s
详情:%s
", alert.Annotations["summary"], alert.Annotations["description"]))
		buffer.WriteString(fmt.Sprintf("开始时间: %s

", alert.StartsAt.Format("15:04:05")))
	}

	// 构造出飞书机器人所需的数据结构
	larkRequest = &model.LarkRequest{
		MsgType: "text",
		Content: model.Content{
			Text: buffer.String(),
		},
	}

	return larkRequest, nil
}

编码:主逻辑

go// Code generated by hertz generator.

package handler

import (
	"bytes"
	"context"
	"encoding/json"
	"io"
	"net/http"
	"webhook/biz/model"
	"webhook/biz/util"

	"github.com/cloudwego/hertz/pkg/app"
	"github.com/cloudwego/hertz/pkg/common/hlog"
	"github.com/cloudwego/hertz/pkg/common/utils"
	"github.com/cloudwego/hertz/pkg/protocol/consts"
)

const (
	// 请使用您自己的机器人的webhook地址
	LARK_URL = "https://open.feishu.cn/open-apis/bot/v2/hook/12345678-1234-1234-1234-123456789012"
)

// Ping .
func AlertmanagerWebhook(ctx context.Context, c *app.RequestContext) {
	var notification model.Notification

	// 绑定对象
	err := c.BindAndValidate( ification)
	if err != nil {
		c.JSON(consts.StatusBadRequest, utils.H{
			"error": err.Error(),
		})

		return
	}

	hlog.Info("收到alertmanager告警:
%s", notification)

	// 根据alertmanager的请求构造飞书消息的请求数据结构
	larkRequest, _ := util.TransformToLarkRequest(notification)

	// 向飞书服务器发送POST请求,将飞书服务器返回的内容转为对象
	bytesData, _ := json.Marshal(larkRequest)
	req, _ := http.NewRequest("POST", LARK_URL, bytes.NewReader(bytesData))
	req.Header.Add("content-type", "application/json")
	res, err := http.DefaultClient.Do(req)
	// 飞书服务器可能通信失败
	if err != nil {
		hlog.Error("请求飞书服务器失败:%s", err)
		c.JSON(consts.StatusInternalServerError, utils.H{
			"error": err.Error(),
		})

		return
	}
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	var larkResponse model.LarkResponse
	err = json.Unmarshal([]byte(body), &larkResponse)
	// 飞书服务器返回的包可能有问题
	if err != nil {
		hlog.Error("获取飞书服务器响应失败:%s", err)
		c.JSON(consts.StatusInternalServerError, utils.H{
			"error": err.Error(),
		})

		return
	}
	hlog.Info("向飞书服务器发送消息成功")
	c.JSON(consts.StatusOK, utils.H{
		"message": "successful receive alert notification message!",
	})
}

vscode配置

json{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch Package",
            "type": "go",
            "request": "launch",
            "mode": "auto",
            "program": "${workspaceFolder}"
        }
    ]
}

shell脚本配置

shell#!/bin/bash
CURDIR=$(cd $(dirname $0); pwd)
BinaryName=
echo "$CURDIR/bin/${BinaryName}"
exec $CURDIR/bin/${BinaryName}
shell#!/bin/bash
CURDIR=$(cd $(dirname $0); pwd)
BinaryName=webhook
echo "$CURDIR/bin/${BinaryName}"
exec $CURDIR/bin/${BinaryName}

验证













欢迎关注头条号:程序员欣宸

展开阅读全文

页面更新:2024-03-03

标签:实战   数据结构   机器人   仓库   状态   消息   地址   服务器   通知   内容   工程

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top