华为云CES监控与飞书通知

这篇具有很好参考价值的文章主要介绍了华为云CES监控与飞书通知。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

华为云负载均衡连接数监控与飞书通知

在云服务的日常运维中,持续监控资源状态是保障系统稳定性的关键步骤之一。本文通过一个实际案例展示了如何使用华为云的Go SDK获取负载均衡器的连接数,并通过飞书Webhook发送通知到团队群组,以便运维人员及时获取最新的监控信息。本来准备直接使用ces告警,但是看了一下模版以及最佳实践貌似没有很好的支持webhook,就直接自己使用go sdk实现了!

背景知识

在华为云上,负载均衡服务(ELB)用于分发来自客户端的网络请求到多个云服务器,确保系统在面对不同的负载情况时,仍能够提供稳定、可靠的服务。ELB的性能指标,如每分钟连接数(CPS),是反映当前系统承载能力的重要数据。通常情况下,我们希望能够实时监控这些关键指标。

随着云服务技术的成熟,大型企业往往会将监控数据集成到实时通讯工具中,便于团队成员即时查看和响应潜在的问题。本案例中选择的通讯工具是飞书,华为云Go SDK则是我们与华为云服务交互的媒介。

环境准备

华为云提供的Go SDK是一套围绕华为云API构建的开发工具包,使得开发者可以在Go语言环境中便捷地调用云服务。在这里,我们利用Cloud Eye Service (CES) 的API,通过SDK检索ELB的CPS指标数据。

安装华为云Go SDK

首先需要安装华为云Go SDK。可以通过go get命令安装所需的SDK包:

go get -u github.com/huaweicloud/huaweicloud-sdk-go-v3

安装完成后,即可在项目中引入相关的SDK模块。

初始化客户端

要与华为云的服务交互,我们需要创建并初始化一个SDK客户端。如下示例中,我们创建了用于CES(Cloud Eye Service)服务的客户端,并使用了之前提到的AK和SK进行了认证。

package main

// 导入相关的包
import (
    "fmt"
    "bytes"
    "json"
    "http"
    "ioutil"
    "time"

    "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic"
    "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ces/v1"
    ces "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ces/v1/model"
)

const (
    feishuWebhookURL = "xxxx" // 飞书Webhook URL
    ak               = "xxx"  // Access Key
    sk               = "xxxxx" // Secret Key
)

func main() {
    // 构建认证信息
    auth := basic.NewCredentialsBuilder().
       WithAk(ak).
       WithSk(sk).
       Build()

    // 初始化CES客户端
    client := ces.NewCesClient(
       ces.CesClientBuilder().
          WithRegion(region.ValueOf("cn-east-3")).
          WithCredential(auth).
          Build())

    // ...后续代码
}

设置定时器和执行任务

我们通过一个定时器来定期检查负载均衡器的最大连接数,例如:

    ticker := time.NewTicker(1 * time.Minute) // 每分钟触发检查
    for {
       select {
       case t := <-ticker.C:
          currentHour := t.Hour()
          // 只在既定的时间范围内执行
          if currentHour >= 7 && currentHour < 24 {
             // 我们设定在59分时收集数据
             if t.Minute() == 59 {
                go collectDataAndSendToFeishu(client)
             }
          }
       }
    }

这里限制了定时器发送的时间范围早上7点到24点执行,0点-7点默认不执行。并且执行的时间是每个小时的59分执行!

收集和发送数据

一旦定时器触发并满足条件,我们会收集负载均衡的最大连接数并发送给飞书,参考 华为云ces ShowMetricData接口:
华为云CES监控与飞书通知,杂七乱八,华为云,linux工具,华为云,飞书,运维,devops,chatgpt
具体实现如下,注意**ShowMetricDataRequest **中具体参数:

func collectDataAndSendToFeishu(client *ces.CesClient) {
    currentTime := time.Now().UTC()
    startTime := currentTime.Truncate(time.Hour).Add(time.Minute * 58)
    endTime := startTime.Add(time.Minute)

    startTimestamp := startTime.UnixNano() / int64(time.Millisecond)
    endTimestamp := endTime.UnixNano() / int64(time.Millisecond)

    request := &model.ShowMetricDataRequest{
       Namespace:  "SYS.ELB",
       MetricName: "m1_cps",
       Dim0:       "lbaas_instance_id,xxxxxx",
       Filter:     model.GetShowMetricDataRequestFilterEnum().MAX,
       Period:     int32(1),
       From:       startTimestamp,
       To:         endTimestamp,
    }

    response, err := client.ShowMetricData(request)
    if err != nil {
       fmt.Println("Error querying CES data:", err)
       return
    }
    fmt.Printf("CES response: %+v\n", response)

    // Extract max value and timestamp from the response
    var maxConnection float64
    var timestamp int64
    if response.Datapoints != nil && len(*response.Datapoints) > 0 {
       datapoints := *response.Datapoints
       maxConnection = *datapoints[0].Max
       timestamp = datapoints[0].Timestamp
    }

    // Format the timestamp to a readable form
    readableTime := time.Unix(timestamp/1000, (timestamp%1000)*int64(time.Millisecond)).Format("2006-01-02 15:04:05")
    // Prepare the message to send to Feishu
    feishuMessage := fmt.Sprintf("当前时间 %s 负载均衡最大连接数是 %.2f", readableTime, maxConnection)

    if err := sendToFeishuWebhook(feishuWebhookURL, feishuMessage); err != nil {
       fmt.Println("Error sending to Feishu webhook:", err)
    }
}

发送Webhook通知

最后,实现sendToFeishuWebhook方法以将消息推送到飞书。

func sendToFeishuWebhook(webhookURL string, message string) error {
    webhookMessage := FeishuWebhookMessage{
       MsgType: "text",
    }
    webhookMessage.Content.Text = message

    jsonData, err := json.Marshal(webhookMessage)
    if err != nil {
       return fmt.Errorf("failed to marshal webhook message: %v", err)
    }

    req, err := http.NewRequest("POST", webhookURL, bytes.NewBuffer(jsonData))
    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 HTTP request: %v", err)
    }
    defer resp.Body.Close()

    responseBody, err := ioutil.ReadAll(resp.Body)
    if err != nil {
       return fmt.Errorf("failed to read webhook response body: %v", err)
    }

    fmt.Println("Feishu webhook response:", string(responseBody))
    return nil
}

完整代码:

每小时59分统计58-59分最大值发送统计到飞书:

package main
type FeishuWebhookMessage struct {
    MsgType string `json:"msg_type"`
    Content struct {
       Text string `json:"text"`
    } `json:"content"`
}

const (
    // 定时器间隔,用于根据特定时间点触发数据检索。例如:59分时执行任务,就是(59 - 当前时间的分钟数) x 每分钟的秒数
    feishuWebhookURL = "xxxx"
    ak               = "xxx"
    sk               = "xxxxx"
)

func main() {
    auth := basic.NewCredentialsBuilder().
       WithAk(ak).
       WithSk(sk).
       Build()

    client := ces.NewCesClient(
       ces.CesClientBuilder().
          WithRegion(region.ValueOf("cn-east-3")).
          WithCredential(auth).
          Build())

    ticker := time.NewTicker(1 * time.Minute) // Check every 10 minutes to adjust for the next 59th minute.
    for {
       select {
       case t := <-ticker.C:
          // 这里设置只在7-24点执行
          currentHour := t.Hour()
          if currentHour >= 7 && currentHour < 24 {
             if t.Minute() == 59 {
                go collectDataAndSendToFeishu(client)
             }
          }
       }
    }
}
func collectDataAndSendToFeishu(client *ces.CesClient) {
    currentTime := time.Now().UTC()
    startTime := currentTime.Truncate(time.Hour).Add(time.Minute * 58)
    endTime := startTime.Add(time.Minute)

    startTimestamp := startTime.UnixNano() / int64(time.Millisecond)
    endTimestamp := endTime.UnixNano() / int64(time.Millisecond)

    request := &model.ShowMetricDataRequest{
       Namespace:  "SYS.ELB",
       MetricName: "m1_cps",
       Dim0:       "lbaas_instance_id,xxxxxx",
       Filter:     model.GetShowMetricDataRequestFilterEnum().MAX,
       Period:     int32(1),
       From:       startTimestamp,
       To:         endTimestamp,
    }

    response, err := client.ShowMetricData(request)
    if err != nil {
       fmt.Println("Error querying CES data:", err)
       return
    }
    fmt.Printf("CES response: %+v\n", response)

    // Extract max value and timestamp from the response
    var maxConnection float64
    var timestamp int64
    if response.Datapoints != nil && len(*response.Datapoints) > 0 {
       datapoints := *response.Datapoints
       maxConnection = *datapoints[0].Max
       timestamp = datapoints[0].Timestamp
    }

    // Format the timestamp to a readable form
    readableTime := time.Unix(timestamp/1000, (timestamp%1000)*int64(time.Millisecond)).Format("2006-01-02 15:04:05")
    // Prepare the message to send to Feishu
    feishuMessage := fmt.Sprintf("当前时间 %s 负载均衡最大连接数是 %.2f", readableTime, maxConnection)

    if err := sendToFeishuWebhook(feishuWebhookURL, feishuMessage); err != nil {
       fmt.Println("Error sending to Feishu webhook:", err)
    }
}

// sendToFeishuWebhook sends a message to Feishu webhook
func sendToFeishuWebhook(webhookURL string, message string) error {
    webhookMessage := FeishuWebhookMessage{
       MsgType: "text",
    }
    webhookMessage.Content.Text = message

    jsonData, err := json.Marshal(webhookMessage)
    if err != nil {
       return fmt.Errorf("failed to marshal webhook message: %v", err)
    }

    req, err := http.NewRequest("POST", webhookURL, bytes.NewBuffer(jsonData))
    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 HTTP request: %v", err)
    }
    defer resp.Body.Close()

    responseBody, err := ioutil.ReadAll(resp.Body)
    if err != nil {
       return fmt.Errorf("failed to read webhook response body: %v", err)
    }

    fmt.Println("Feishu webhook response:", string(responseBody))
    return nil
}

运行以上代码:
华为云CES监控与飞书通知,杂七乱八,华为云,linux工具,华为云,飞书,运维,devops,chatgpt

其它的扩展玩法:

每分钟检查一次,当连接数大于100报警触发

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic"
	ces "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ces/v1"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ces/v1/model"
	region "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ces/v1/region"
	"io/ioutil"
	"net/http"
	"time"
)

type FeishuWebhookMessage struct {
	MsgType string `json:"msg_type"`
	Content struct {
		Text string `json:"text"`
	} `json:"content"`
}

const (
	feishuWebhookURL = "xxxx"
	ak               = "xxxx"
	sk               = "xxxxx"
)

func main() {
	auth := basic.NewCredentialsBuilder().
		WithAk(ak).
		WithSk(sk).
		Build()

	client := ces.NewCesClient(
		ces.CesClientBuilder().
			WithRegion(region.ValueOf("cn-east-3")).
			WithCredential(auth).
			Build())

	ticker := time.NewTicker(1 * time.Minute) // Check every 10 minutes to adjust for the next 59th minute.
	for {
		select {
		case t := <-ticker.C:
			// 这里设置只在7-24点执行
			currentHour := t.Hour()
			if currentHour >= 7 && currentHour < 24 {
				go collectDataAndSendToFeishu(client)
			}
		}
	}
}
func collectDataAndSendToFeishu(client *ces.CesClient) {
	currentTime := time.Now().UTC().Truncate(time.Minute)
	startTime := currentTime.Add(-1 * time.Minute)
	endTime := currentTime

	startTimestamp := startTime.UnixNano() / int64(time.Millisecond)
	endTimestamp := endTime.UnixNano() / int64(time.Millisecond)

	request := &model.ShowMetricDataRequest{
		Namespace:  "SYS.ELB",
		MetricName: "m1_cps",
		Dim0:       "lbaas_instance_id,xxxxx",
		Filter:     model.GetShowMetricDataRequestFilterEnum().MAX,
		Period:     int32(1),
		From:       startTimestamp,
		To:         endTimestamp,
	}

	response, err := client.ShowMetricData(request)
	if err != nil {
		fmt.Println("Error querying CES data:", err)
		return
	}
	fmt.Printf("CES response: %+v\n", response)

	// Extract max value and timestamp from the response
	var maxConnection float64
	var timestamp int64
	if response.Datapoints != nil && len(*response.Datapoints) > 0 {
		datapoints := *response.Datapoints
		maxConnection = *datapoints[0].Max
		timestamp = datapoints[0].Timestamp
	}

	// Format the timestamp to a readable form
	readableTime := time.Unix(timestamp/1000, (timestamp%1000)*int64(time.Millisecond)).Format("2006-01-02 15:04:05")
	// Prepare the message to send to Feishu
	if maxConnection > 100 {
		// Prepare the alert message to send to Feishu
		feishuMessage := fmt.Sprintf("警告:当前时间 %s 负载均衡连接数超越100,当前数值是 %.2f", readableTime, maxConnection)

		if err := sendToFeishuWebhook(feishuWebhookURL, feishuMessage); err != nil {
			fmt.Println("Error sending to Feishu webhook:", err)
		}
	}
}

// sendToFeishuWebhook sends a message to Feishu webhook
func sendToFeishuWebhook(webhookURL string, message string) error {
	webhookMessage := FeishuWebhookMessage{
		MsgType: "text",
	}
	webhookMessage.Content.Text = message

	jsonData, err := json.Marshal(webhookMessage)
	if err != nil {
		return fmt.Errorf("failed to marshal webhook message: %v", err)
	}

	req, err := http.NewRequest("POST", webhookURL, bytes.NewBuffer(jsonData))
	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 HTTP request: %v", err)
	}
	defer resp.Body.Close()

	responseBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("failed to read webhook response body: %v", err)
	}

	fmt.Println("Feishu webhook response:", string(responseBody))
	return nil
}

为了方便代码的复用性,可读性。将100作为一个可配置常量提取出来:

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic"
	ces "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ces/v1"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ces/v1/model"
	region "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ces/v1/region"
	"io/ioutil"
	"net/http"
	"time"
)

type FeishuWebhookMessage struct {
	MsgType string `json:"msg_type"`
	Content struct {
		Text string `json:"text"`
	} `json:"content"`
}

const (
	// 定时器间隔,用于根据特定时间点触发数据检索。例如:59分时执行任务,就是(59 - 当前时间的分钟数) x 每分钟的秒数
	feishuWebhookURL                = "xxxxx"
	ak                              = "xxxx"
	sk                              = "xxxx"
	loadBalancerConnectionThreshold = 100.00 // 负载均衡连接数阈值
)

func main() {
	auth := basic.NewCredentialsBuilder().
		WithAk(ak).
		WithSk(sk).
		Build()

	client := ces.NewCesClient(
		ces.CesClientBuilder().
			WithRegion(region.ValueOf("cn-east-3")).
			WithCredential(auth).
			Build())

	ticker := time.NewTicker(1 * time.Minute) // Check every 10 minutes to adjust for the next 59th minute.
	for {
		select {
		case t := <-ticker.C:
			// 这里设置只在7-24点执行
			currentHour := t.Hour()
			if currentHour >= 7 && currentHour < 24 {
				go collectDataAndSendToFeishu(client)
			}
		}
	}
}
func collectDataAndSendToFeishu(client *ces.CesClient) {
	currentTime := time.Now().UTC().Truncate(time.Minute)
	startTime := currentTime.Add(-1 * time.Minute)
	endTime := currentTime

	startTimestamp := startTime.UnixNano() / int64(time.Millisecond)
	endTimestamp := endTime.UnixNano() / int64(time.Millisecond)

	request := &model.ShowMetricDataRequest{
		Namespace:  "SYS.ELB",
		MetricName: "m1_cps",
		Dim0:       "lbaas_instance_id,xxxx",
		Filter:     model.GetShowMetricDataRequestFilterEnum().MAX,
		Period:     int32(1),
		From:       startTimestamp,
		To:         endTimestamp,
	}

	response, err := client.ShowMetricData(request)
	if err != nil {
		fmt.Println("Error querying CES data:", err)
		return
	}
	fmt.Printf("CES response: %+v\n", response)

	// Extract max value and timestamp from the response
	var maxConnection float64
	var timestamp int64
	if response.Datapoints != nil && len(*response.Datapoints) > 0 {
		datapoints := *response.Datapoints
		maxConnection = *datapoints[0].Max
		timestamp = datapoints[0].Timestamp
	}

	// Format the timestamp to a readable form
	readableTime := time.Unix(timestamp/1000, (timestamp%1000)*int64(time.Millisecond)).Format("2006-01-02 15:04:05")
	// Prepare the message to send to Feishu
	if maxConnection > loadBalancerConnectionThreshold {
		// Prepare the alert message to send to Feishu
		feishuMessage := fmt.Sprintf("警报:在%s,负载均衡器的连接数超过了%.2f,当前连接数:%.2f", readableTime, loadBalancerConnectionThreshold, maxConnection)

		if err := sendToFeishuWebhook(feishuWebhookURL, feishuMessage); err != nil {
			fmt.Println("Error sending to Feishu webhook:", err)
		}
	}
}

// sendToFeishuWebhook sends a message to Feishu webhook
func sendToFeishuWebhook(webhookURL string, message string) error {
	webhookMessage := FeishuWebhookMessage{
		MsgType: "text",
	}
	webhookMessage.Content.Text = message

	jsonData, err := json.Marshal(webhookMessage)
	if err != nil {
		return fmt.Errorf("failed to marshal webhook message: %v", err)
	}

	req, err := http.NewRequest("POST", webhookURL, bytes.NewBuffer(jsonData))
	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 HTTP request: %v", err)
	}
	defer resp.Body.Close()

	responseBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("failed to read webhook response body: %v", err)
	}

	fmt.Println("Feishu webhook response:", string(responseBody))
	return nil
}

注意loadBalancerConnectionThresholdfloat64.

增加 MetricName多个条件

这里以弹性IP EIP与负载均衡为例,我想查询负载均衡连接数大于100报警,并根据负载均衡对应eip的四个指标:“upstream_bandwidth_usage”,“downstream_bandwidth_usage”,“upstream_bandwidth”,"downstream_bandwidth"报警,完整代码如下:

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic"
	ces "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ces/v1"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ces/v1/model"
	region "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ces/v1/region"
	"io/ioutil"
	"net/http"
	"time"
)

type FeishuWebhookMessage struct {
	MsgType string `json:"msg_type"`
	Content struct {
		Text string `json:"text"`
	} `json:"content"`
}

const (
	// 定时器间隔,用于根据特定时间点触发数据检索。例如:59分时执行任务,就是(59 - 当前时间的分钟数) x 每分钟的秒数
	feishuWebhookURL                = "xxxxxxx"
	ak                              = "xxx"
	sk                              = "xxxx"
	upstreamBandwidthThreshold      = 40    // 出网带宽阈值,单位Mbps
	downstreamBandwidthThreshold    = 80    // 入网带宽阈值,单位Mbps(示例中以百分比为单位,根据实际单位调整)
	upstreamUsageThreshold          = 20    // 出网带宽使用率阈值,单位百分比
	downstreamUsageThreshold        = 40    // 入网带宽使用率阈值,单位百分比
)

var metricNames = []string{
	"upstream_bandwidth_usage",
	"downstream_bandwidth_usage",
	"upstream_bandwidth",
	"downstream_bandwidth",
}

func main() {
	auth := basic.NewCredentialsBuilder().
		WithAk(ak).
		WithSk(sk).
		Build()

	client := ces.NewCesClient(
		ces.CesClientBuilder().
			WithRegion(region.ValueOf("cn-east-3")).
			WithCredential(auth).
			Build())

	ticker := time.NewTicker(time.Minute) // Check every minute.
	for {
		select {
		case <-ticker.C:
			// 每分钟执行
			go collectDataAndSendToFeishu(client)
		}
	}
}

func collectDataAndSendToFeishu(client *ces.CesClient) {
	currentTime := time.Now().UTC().Truncate(time.Minute)
	startTime := currentTime.Add(-1 * time.Minute)
	endTime := currentTime

	startTimestamp := startTime.UnixMilli()
	endTimestamp := endTime.UnixMilli()
	dimensionValues := "bandwidth_id,xxxx"
	for _, metricName := range metricNames {
		request := &model.ShowMetricDataRequest{
			Namespace:  "SYS.VPC",
			MetricName: metricName,
			Dim0:       dimensionValues, // Replace with actual dimension value
			Filter:     model.GetShowMetricDataRequestFilterEnum().MAX,
			Period:     int32(1),
			From:       startTimestamp,
			To:         endTimestamp,
		}

		response, err := client.ShowMetricData(request)
		if err != nil {
			fmt.Printf("Error querying CES data for %s: %v\n", metricName, err)
			continue
		}

		if response.Datapoints == nil || len(*response.Datapoints) == 0 {
			fmt.Printf("No datapoints received for %s\n", metricName)
			continue
		}

		datapoints := *response.Datapoints
		var maxUsage float64
		for _, point := range datapoints {
			if point.Max != nil {
				if metricName == "upstream_bandwidth" || metricName == "downstream_bandwidth" {
					// Convert from bits to Mbits
					maxUsage = *point.Max / 1000000.0
				} else {
					maxUsage = *point.Max // for utilization metrics, which are percentages
				}
				break // Assuming there's only 1 datapoint with MAX filter
			}
		}

		if (metricName == "upstream_bandwidth" && maxUsage > upstreamBandwidthThreshold) ||
			(metricName == "downstream_bandwidth" && maxUsage > downstreamBandwidthThreshold) ||
			(metricName == "upstream_bandwidth_usage" && maxUsage > upstreamUsageThreshold) ||
			(metricName == "downstream_bandwidth_usage" && maxUsage > downstreamUsageThreshold) {

			alertMessage := createAlertMessage(metricName, maxUsage, endTime)
			if err := sendToFeishuWebhook(feishuWebhookURL, alertMessage); err != nil {
				fmt.Printf("Error sending to Feishu webhook: %v\n", err)
			}
		}
	}
}

func createAlertMessage(metricName string, usage float64, endTime time.Time) string {
	readableTime := endTime.Add(+8 * time.Hour).Format("2006-01-02 15:04:05")
	var alertMessage string

	// 注意阈值和单位已更新,具体文本格式根据实际需要调整
	switch metricName {
	case "upstream_bandwidth":
		alertMessage = fmt.Sprintf("警报:在%s,出网带宽超过了%.2fMbps,当前带宽:%.2fMbps", readableTime, upstreamBandwidthThreshold, usage)
	case "downstream_bandwidth":
		alertMessage = fmt.Sprintf("警报:在%s,入网带宽超过了%.2fMbps,当前带宽:%.2fMbps", readableTime, downstreamBandwidthThreshold, usage)
	case "upstream_bandwidth_usage":
		alertMessage = fmt.Sprintf("警报:在%s,出网带宽使用率超过了%.2f%%,当前使用率:%.2f%%", readableTime, upstreamUsageThreshold, usage)
	case "downstream_bandwidth_usage":
		alertMessage = fmt.Sprintf("警报:在%s,入网带宽使用率超过了%.2f%%,当前使用率:%.2f%%", readableTime, downstreamUsageThreshold, usage)
	}

	return alertMessage
}

func sendToFeishuWebhook(webhookURL string, message string) error {
	webhookMessage := FeishuWebhookMessage{
		MsgType: "text",
	}
	webhookMessage.Content.Text = message

	jsonData, err := json.Marshal(webhookMessage)
	if err != nil {
		return fmt.Errorf("failed to marshal webhook message: %v", err)
	}

	req, err := http.NewRequest("POST", webhookURL, bytes.NewBuffer(jsonData))
	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 HTTP request: %v", err)
	}
	defer resp.Body.Close()

	responseBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("failed to read webhook response body: %v", err)
	}

	fmt.Printf("Feishu webhook response: %s\n", responseBody)
	return nil
}

测试报警如下:
华为云CES监控与飞书通知,杂七乱八,华为云,linux工具,华为云,飞书,运维,devops,chatgpt

其他

  1. 遍历负载均衡列表,批量查询所有负载均衡连接数?发送告警时候传入负载均衡的名称?
  2. 根据负载均衡列表查询绑定的eip实例,查询所有eip对应bandwidth_id,输出所有eip的指标?

总结

此文为你展示了如何通过Go SDK获取华为云上的负载均衡最大连接数and eip指标的多个条件查询,并通过飞书Webhook发送通知的过程。以上的实现可以根据你自己的需求进行调整,比如改变监测的指标或者消息发送的方式。希望本文能帮助你更好地监控和管理华为云上的资源。文章来源地址https://www.toymoban.com/news/detail-782015.html

到了这里,关于华为云CES监控与飞书通知的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 『EasyNotice』.NET开源消息通知组件——快速实现邮件/钉钉/飞书/企业微信告警通知

    📣读完这篇文章里你能收获到 了解博主开源的告警通知项目——EasyNotice 傻瓜式扩展方法直接使用 如何通过EasyNotice快速实现邮件/钉钉/飞书/企业微信的通知发送 感谢点赞+收藏,避免下次找不到~ 这是博主开源的一个基于.NET开源的消息通知组件,它包含了邮件、钉钉、飞书

    2023年04月08日
    浏览(50)
  • ElastAlert通过飞书机器人发送报警通知

    公司采用ELK架构搜集业务系统的运行日志,以前开发人员只有在业务出现问题的时候,才会去kibana上进行日志搜索操作,每次都是被用户告知系统出问题了,这简直是被啪啪打脸~ 于是痛定思痛,决定主动出击,查阅了许多资料,发现ElastAlert这个服务能够对elasticsearch的索引按

    2024年02月07日
    浏览(42)
  • Java项目中利用飞书自定义机器人Webhook向飞书群推送告警通知

    今天来看一下如何在Java项目中利用飞书的自定义机器人Webhook向飞书群推送告警通知         企业存在给 特定群组 自动推送消息的需求,比如:监控报警推送、销售线索推送、运营内容推送等。        你可以在群聊中添加一个 自定义机器人 ,通过服务端调用  webh

    2023年04月14日
    浏览(86)
  • 【Jenkins】+【飞书机器人】发送通知(带签名)【Linux】

    自定义机器人使用指南飞书官网https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot 我这个设置了签名的,具体怎么设置签名可以查看飞书官方文档 可以看到上传去是没有执行权限的,一定要记得叫上执行权限 chmod +x sendMsg.py 最后一个参数标识 0 开始构建 1 构建完成 /opt/java/scri

    2024年02月13日
    浏览(39)
  • linux+Jenkins+飞书机器人发送通知(带签名)

    自定义机器人使用指南飞书官网https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot 我这个设置了签名的,具体怎么设置签名可以查看飞书官方文档 可以看到上传去是没有执行权限的,一定要记得叫上执行权限 chmod +x sendMsg.py 最后一个参数标识 0 开始构建 1 构建完成 /opt/java/scri

    2024年02月15日
    浏览(51)
  • 【Linux】+【Jenkins】+【飞书机器人】发送通知(带签名)

    自定义机器人使用指南飞书官网https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot 我这个设置了签名的,具体怎么设置签名可以查看飞书官方文档 可以看到上传去是没有执行权限的,一定要记得叫上执行权限 chmod +x sendMsg.py 最后一个参数标识 0 开始构建 1 构建完成 /opt/java/scri

    2024年02月14日
    浏览(40)
  • Jenkins+Allure测试报告+飞书机器人发送通知

    本篇讲述在jenkins构建成功后,如何生成测试报告,以及推送飞书(因为我公司用的是飞书,所以是发送到飞书机器人)。 本次实践搞了一天,踩了一些坑,其中有2个坑可参考如下: 1、关于jenkins生成allure报告是空的:https://blog.csdn.net/qq_37159446/article/details/122233467 2、如遇到构

    2024年02月04日
    浏览(33)
  • 数据分析:扩展企业微信、钉钉、飞书等告警通知渠道

    本章节主要讲述如何扩展告警的通知渠道,以便将告警发送到第三方应用中 实现目标 ●在鸿鹄中创建的告警被触发后,将告警通知发送至指定的企业微信群聊 配置步骤 1、打开“企业微信”,点击告警群右上角的“...”按钮 2、点击“群机器人” 3、点击“添加群机器人”

    2024年02月17日
    浏览(47)
  • Webfunny前端监控如何接入飞书单点登录(SSO)

    Hello,大家好,欢迎使用** webfunny前端监控和埋点平台 **。今天我们将介绍一下如何接入飞书的登录系统。 友情提示:如果飞书侧已经配置好了,可以直接跳到第六步阅读。 进入飞书开发者后台,创建企业自建应用,命名「webfunny」(名字自己起哈) 应用创建完成后,会生成

    2024年04月27日
    浏览(36)
  • 加强版python连接飞书通知——本地电脑PC端通过网页链接打开本地已安装软件(调用注册表形式,以漏洞扫描工具AppScan为例)

            如果你想要通过超链接来打开本地应用,那么你首先你需要将你的应用添入windows注册表中(这样网页就可以通过指定代号来调用程序),由于安全性的原因所以网页无法直接通过输入绝对路径来调用本地文件。         创建文本文档,使用记事本打开,添加内

    2024年02月09日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包