自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

夜鶯自定義告警模板

數(shù)據(jù)庫(kù) 其他數(shù)據(jù)庫(kù)
要實(shí)現(xiàn)上面的需求很簡(jiǎn)單,夜鶯監(jiān)控的數(shù)據(jù)庫(kù)表Alert_cur_event保存了我們所需要的當(dāng)前未處理的告警總數(shù),而且夜鶯監(jiān)控也提供了查詢未處理告警的面板,而對(duì)于告警恢復(fù)時(shí)候的值我們只需要根據(jù)自定義的恢復(fù)Promql即可查詢。

希望在告警通知里有以下數(shù)據(jù):

  • 告知當(dāng)前系統(tǒng)還有多少未處理的告警。
  • 告知當(dāng)前告警恢復(fù)時(shí)候的具體值。
  • 告警通知里增加查看未處理告警的頁(yè)面鏈接。

具體實(shí)現(xiàn)

要實(shí)現(xiàn)上面的需求很簡(jiǎn)單,夜鶯監(jiān)控的數(shù)據(jù)庫(kù)表alert_cur_event保存了我們所需要的當(dāng)前未處理的告警總數(shù),而且夜鶯監(jiān)控也提供了查詢未處理告警的面板,而對(duì)于告警恢復(fù)時(shí)候的值我們只需要根據(jù)自定義的恢復(fù)promql即可查詢。

最簡(jiǎn)單的方式就是直接通過(guò)notify.py腳本進(jìn)行告警發(fā)送,我們只需要做一丟丟修改即可。

整體腳本如下:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import sys
import json
import requests
import pymysql

# 處理字符問(wèn)題
reload(sys)
sys.setdefaultencoding('utf-8')

# 通過(guò)api查詢指標(biāo)
def getPrometheus(url, promql):
    response = requests.get(url, params={'query': promql})
    data = json.loads(response.text)
    # 提取指標(biāo)數(shù)據(jù)
    if response.status_code == 200
        result = data['data']['result']
        if len(result) == 1:
            return result[0]['value'][1]
        else:
            return 0
    else:
        return 0

def count_rows_and_get_rule_names():
    try:
        conn = pymysql.connect(
            host='127.0.0.1',
            port=3306,
            user='n9e',
            passwd='1234',
            db='n9e_v6',
            charset='utf8mb4'
        )
        cursor = conn.cursor()

        # Count the total number of rows in the table
        count_query = "SELECT COUNT(*) FROM alert_cur_event"
        cursor.execute(count_query)
        total_rows = cursor.fetchone()[0]
        return total_rows

    except Exception as e:
        print("Error: ", e)


class Sender(object):
    @classmethod
    def send_qywx(cls, payload):
        users = payload.get('event').get("notify_users_obj")
        is_recovered = payload.get('event').get("is_recovered")
        tokens = {}
        phones = {}
        res = {} 

        history_row = count_rows_and_get_rule_names()

        if is_recovered:
            # 獲取自定義的恢復(fù)promql
            promQL = payload.get('event').get("annotations").get("recovery_promql")
            url = "http://127.0.0.1:9090/api/v1/query"
            res = getPrometheus(url, promQL)

        # 查詢活躍告警的面板
        currAlert = "http://127.0.0.1:17000/alert-cur-events"
        for u in users:
            if u.get("phone"):
                phones[u.get("phone")] = 1

            contacts = u.get("contacts")
            if contacts.get("qywx_robot_token", ""):
                tokens[contacts.get("qywx_robot_token", "")] = 1

        headers = {
            "Content-Type": "application/json;charset=utf-8",
            "Host": "qyapi.weixin.qq.com"

        }

        for t in tokens:
            url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={}".format(t)
            content = payload.get('tpls').get("qywx", "qywx not found")
            content = "# **當(dāng)前環(huán)境的全部告警數(shù)**: %s" % (history_row) + "\n" + content
            if is_recovered:
                content = content + "\n" + "> **恢復(fù)時(shí)值**: %s" % (res)

            if history_row > 0:
                content = content + "\n" + "[當(dāng)前活躍告警](%s)" % (currAlert)
            body = {
                "msgtype": "markdown",
                "markdown": {
                    "content": content
                }
            }

            response = requests.post(url, headers=headers, data=json.dumps(body))
  

def main():
    payload = json.load(sys.stdin)
    with open(".payload", 'w') as f:
        f.write(json.dumps(payload, indent=4))
    for ch in payload.get('event').get('notify_channels'):
        send_func_name = "send_{}".format(ch.strip())
        if not hasattr(Sender, send_func_name):
            print("function: {} not found", send_func_name)
            continue
        send_func = getattr(Sender, send_func_name)
        send_func(payload)

  
def hello():
    print("hello nightingale")

if __name__ == "__main__":
    if len(sys.argv) == 1:
        main()
    elif sys.argv[1] == "hello":
        hello()
    else:
        print("I am confused")

需要在服務(wù)器上安裝pymysql以及requests包

然后將上面的腳本放到夜鶯監(jiān)控面板->系統(tǒng)設(shè)置->通知設(shè)置->通知腳本中,并將腳本設(shè)置為啟用狀態(tài)。

然后新增名叫qywx的通知媒介以及名叫qywx_robot_token的聯(lián)系方式,在發(fā)送告警的時(shí)候會(huì)通過(guò)通知媒介來(lái)調(diào)用通知方法,比如你的通知媒介名叫zhangsan,那么你定義的方法名就是send_zhangsan。另外還會(huì)從聯(lián)系方式處獲取發(fā)送的token。

然后我們來(lái)創(chuàng)建一個(gè)通知模板,這個(gè)模板是在原生的基礎(chǔ)上進(jìn)行更改的,如下創(chuàng)建一個(gè)名叫qywx的模板。

> **級(jí)別狀態(tài)**: {{if .IsRecovered}}<font color="info">告警恢復(fù)</font>{{else}}<font color="warning">發(fā)生告警</font>{{end}}   
> **級(jí)別級(jí)別**: S{{.Severity}}
> **告警類型**: {{.RuleName}}{{if .RuleNote}}   
> **告警詳情**: {{.RuleNote}}{{end}}{{if .TargetIdent}}   
> **監(jiān)控對(duì)象**: {{.TargetIdent}}{{end}}   
> **監(jiān)控指標(biāo)**: {{.TagsJSON}}{{if not .IsRecovered}}   
> **觸發(fā)時(shí)值**: {{.TriggerValue}}{{end}}   
{{if .IsRecovered}}> **恢復(fù)時(shí)間**: {{timeformat .LastEvalTime}}{{else}}> **首次觸發(fā)時(shí)間**: {{timeformat .FirstTriggerTime}}{{end}}   
{{$time_duration := sub now.Unix .FirstTriggerTime }}{{if .IsRecovered}}{{$time_duration = sub .LastEvalTime .FirstTriggerTime }}{{end}}> **距離首次告警**: {{humanizeDurationInterface $time_duration}}
> **發(fā)送時(shí)間**: {{timestamp}}

在實(shí)際發(fā)送過(guò)程中會(huì)對(duì)模板進(jìn)行相應(yīng)的增加。

最后,再來(lái)配置告警,比如我們現(xiàn)在要配置一個(gè)K8s中Pod的狀態(tài)異常的告警規(guī)則,如下:

填寫具體的規(guī)則名以及備注,并且填寫具體的promql。

往下繼續(xù)填寫通知媒介以及附加信息。

其中附加信息中就有告警恢復(fù)時(shí)候的promql,在python腳本中會(huì)獲取當(dāng)前的promql,然后調(diào)用prometheus的接口進(jìn)行查詢當(dāng)前值,最后填充到告警模板中去。

以上就是具體的實(shí)現(xiàn)思路,希望對(duì)你有所啟發(fā)。

加餐

除了這種python腳本的方式,還可以通過(guò)自定義webhook的方式實(shí)現(xiàn),夜鶯是支持回調(diào)地址的,只需要把回調(diào)地址填寫進(jìn)去即可。

那這個(gè)webhook應(yīng)該怎么開(kāi)發(fā)呢?

其實(shí)不需要我們做啥大的開(kāi)發(fā),直接把夜鶯的源碼里告警相關(guān)的CV出來(lái),改吧改吧就能直接用了。

首先,把a(bǔ)lert_cur_event的數(shù)據(jù)結(jié)構(gòu)弄過(guò)來(lái),查表就查它。

其次,增加一個(gè)查詢prometheus的接口,如下:

package prometheus  
  
import (  
   "context"  
   "devops-webhook-service/src/server/config"       "github.com/prometheus/client_golang/api"   "github.com/prometheus/client_golang/api/prometheus/v1"   "github.com/prometheus/common/model"   "github.com/toolkits/pkg/logger"   "time")  
  
func GetMetricsValue(promql string) string {  
   client, err := api.NewClient(api.Config{  
      Address: config.C.Prometheus.Address,  
   })  
   if err != nil {  
      logger.Error("init prometheus client failed. err: ", err)  
   }  
   queryAPI := v1.NewAPI(client)  
   result, warnings, err := queryAPI.Query(context.TODO(), promql, time.Now())  
   if err != nil {  
      // handle error  
      logger.Error("query prometheus metrics failed. err: ", err)  
   }  
   if len(warnings) > 0 {  
      // handle warnings  
   }  
   vector := result.(model.Vector)  
   //for _, sample := range vector {  
   // fmt.Printf("Time: %v, Value: %v\n", sample.Timestamp, sample.Value)   //}  
   return vector[0].Value.String()  
  
}

再則,我們就可以把需要的告警字段都動(dòng)議到告警模板中,通過(guò)template自動(dòng)填充數(shù)據(jù)了。

## 當(dāng)前環(huán)境的告警總數(shù): {{ .TotalAlert }}  
---  
**級(jí)別狀態(tài)**: {{if .IsRecovered}}<font color="info">S{{.Severity}} Recovered</font>{{else}}<font color="warning">S{{.Severity}} Triggered</font>{{end}}  
**規(guī)則標(biāo)題**: {{.RuleName}}{{if .TargetIdent}}  
**監(jiān)控對(duì)象**: {{.TargetIdent}}{{end}}{{ if .IsRecovered }}  
**當(dāng)前值**: {{ .RecoveryValue }}{{end}}  
**監(jiān)控指標(biāo)**: {{.TagsJSON}}{{if not .IsRecovered}}  
**觸發(fā)時(shí)值**: {{.TriggerValue}}{{end}}  
{{if .IsRecovered}}**恢復(fù)時(shí)間**: {{timeformat .LastEvalTime}}{{else}}**首次觸發(fā)時(shí)間**: {{timeformat .TriggerTime}}{{end}}  
**發(fā)送時(shí)間**: {{timestamp}}  
---

最后,就是在notify.go中做一丟丟的小修改。

比如event事件增加兩個(gè)字段。

type NoticeEvent struct {  
   *models.AlertCurEvent  
   RecoveryValue string // 恢復(fù)時(shí)候的值  
   TotalAlert    int    // 告警總數(shù)  
}

比如在notify.go中的GenNotice方法里,增加查詢prometheus和數(shù)據(jù)庫(kù)的代碼。

var recoveryValue string  
if event.IsRecovered {  
   text := event.RuleNote  
   promql := strings.Split(text, "=")[1]  
   recoveryValue = prometheus.GetMetricsValue(promql)  
}  
  
// 獲取當(dāng)前剩余的總告警數(shù)  
events, err := models.AlertCurEventGetAll(event.Cluster)  
if err != nil {  
   logger.Error("get alert event failed. err: ", err)  
}

整體代碼也就只需要一丟丟東西。

最后

以上就是整體的實(shí)現(xiàn)了,這只是領(lǐng)導(dǎo)根據(jù)領(lǐng)導(dǎo)的需要做的,每個(gè)團(tuán)隊(duì)的需求不一樣,實(shí)現(xiàn)方式肯定也不通,這里只是拋磚引玉。

個(gè)人建議使用webhook比較好一點(diǎn),因?yàn)榭梢员容^靈活的增加其他的功能,比如告警認(rèn)領(lǐng),比如告警抑制,比如告警轉(zhuǎn)發(fā)等。

另外,最近剛換工作沒(méi)多久,寫的文章少了,但是對(duì)技術(shù)的熱愛(ài)并沒(méi)有減少。

責(zé)任編輯:姜華 來(lái)源: 運(yùn)維開(kāi)發(fā)故事
相關(guān)推薦

2023-03-26 08:41:37

2022-04-11 07:47:45

zabbix郵件告警項(xiàng)目

2023-04-20 07:12:33

夜鶯監(jiān)控夜鶯

2011-03-02 10:24:23

DashboardAndroid用戶界面設(shè)計(jì)模板

2015-02-12 15:33:43

微信SDK

2015-02-12 15:38:26

微信SDK

2016-12-26 15:25:59

Android自定義View

2016-11-16 21:55:55

源碼分析自定義view androi

2011-06-23 10:49:13

Qt 自定義信號(hào)

2009-07-06 16:59:26

JSP自定義標(biāo)簽

2011-12-16 14:23:51

Java

2015-01-14 15:06:48

定義相機(jī)

2009-06-08 20:13:36

Eclipse自定義控

2022-04-24 15:17:56

鴻蒙操作系統(tǒng)

2021-11-23 15:06:42

Kubernetes 運(yùn)維開(kāi)源

2013-04-01 14:35:10

Android開(kāi)發(fā)Android自定義x

2015-07-22 10:57:36

watchOS圖表自定義

2010-09-14 16:47:23

SQL自定義函數(shù)

2013-04-19 10:14:24

2013-06-27 11:10:01

iOS開(kāi)發(fā)自定義UISlider
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)