教你一招,告警恢復時如何拿到恢復時的值?

SRETalk發表於2024-06-12

Prometheus 生態的原生做法,由於閾值是放在 promql 中的,恢復時的訊息中難以拿到恢復時的值,夜鶯 v7.0.0.beta10 版本開始,提供了一種較為簡單的內建方式,解決這個問題。下面我們就來看一下如何實現這個能力。

升級方法

從 v6 版本開始,程式自動建立表結構,所以 v6、v7 的各個小版本之間升級,相對容易,整體邏輯是:

  • 1.備份,包括資料庫、二進位制、配置檔案、integrations目錄,以防萬一
  • 2.下載新版本解壓,修改配置檔案中的資料庫連線地址、redis連線地址、時序庫連線地址等個性化資訊
  • 3.停掉老版本,啟動新版本(建議新老版本使用不同的安裝目錄,都保留不刪,建個軟鏈指向當前使用的版本)

拿到恢復時的值的原理

夜鶯的告警邏輯是拿著規則中的 promql 去週期性查詢,如果查不到資料就認為是正常的,如果查到了資料,就認為有觸發了閾值的異常資料,進而生成告警事件。從這裡邏輯可以看出,恢復的時候,promql 查不到資料,所以也就難以拿到恢復的時候的值了。

有兩個辦法可以解決:

  • 不要把閾值放到 promql 中了,promql 查詢原始資料,然後在告警引擎裡邊判斷是否觸發了閾值,而不是讓時序庫去判斷,Flashduty 和夜鶯企業版就提供了這個方式,這個方式比較容易理解,但是每次 promql 把原始資料查出來,可能會查出特別大量的資料,要小心使用
  • 在告警恢復的時候,重新發起一次 promql 查詢,查詢當前最新值。但是要注意,比如 10 臺機器同時觸發了 load1 告警,某個時刻有 2 臺恢復了,查詢最新值的 promql 得是準確去查詢恢復的 2 臺,得對應起來

開源版本的夜鶯,提供的是第二種方式,下面我們來看一下如何配置。

如何配置

要配置兩個地方,第一個是通知模板,我以釘釘的通知模板舉例,其他的通知模板大家可以參考釘釘的:

#### {{if .IsRecovered}}<font color="#008800">💚{{.RuleName}}</font>{{else}}<font color="#FF0000">💔{{.RuleName}}</font>{{end}}

---
{{$time_duration := sub now.Unix .FirstTriggerTime }}{{if .IsRecovered}}{{$time_duration = sub .LastEvalTime .FirstTriggerTime }}{{end}}
- **告警級別**: {{.Severity}}級
{{- if .RuleNote}}
- **規則備註**: {{.RuleNote}}
{{- end}}
{{- if not .IsRecovered}}
- **當次觸發時值**: {{.TriggerValue}}
- **當次觸發時間**: {{timeformat .TriggerTime}}
- **告警持續時長**: {{humanizeDurationInterface $time_duration}}
{{- else}}
{{- if .AnnotationsJSON.recovery_value}}
- **恢復時值**: {{formatDecimal .AnnotationsJSON.recovery_value 4}}
{{- end}}
- **恢復時間**: {{timeformat .LastEvalTime}}
- **告警持續時長**: {{humanizeDurationInterface $time_duration}}
{{- end}}
- **告警事件標籤**:
{{- range $key, $val := .TagsMap}}
{{- if ne $key "rulename" }}
  - `{{$key}}`: `{{$val}}`
{{- end}}
{{- end}}

這裡最為關鍵的邏輯是判斷 .AnnotationsJSON.recovery_value 的邏輯:

{{- if .AnnotationsJSON.recovery_value}}
- **恢復時值**: {{formatDecimal .AnnotationsJSON.recovery_value 4}}
{{- end}}

如果 .AnnotationsJSON 中包含 recovery_value 就展示,展示的時候把 recovery_value 保留 4 位小數。這個 .AnnotationsJSON 是夜鶯告警規則中的自定義欄位部分,如果告警事件中有恢復時的值,就會在這個欄位中體現。

另一個要配置的,是告警規則,你想讓哪個告警規則支援獲取恢復時的值,就在告警規則的自定義欄位中加上 recovery_promql 欄位。比如我有一個告警規則用來偵測 HTTP 地址探測失敗:

需要在告警規則最下面的自定義欄位裡,增加 recovery_promql 的配置,如下:

要理解這個工作邏輯,我們先來看看 http_response_result_code 這個指標的資料長什麼樣子:

從上圖可以看出,這個指標包含兩個 series,其中 agent_hostname 和 method 欄位相同,target 欄位可以區分開這倆 series。告警規則 http_response_result_code != 0 如果觸發,告警事件中一定會帶有 target 標籤,所以,如果告警事件恢復的時候,我們用高警時的那個 target 標籤去查詢,一定就可以準確查到恢復時的值了。所以 recovery_promql 的配置中引用了 target 標籤,其值是變數,這個變數就是告警事件中的 target 標籤值。

效果

本文作者:秦曉輝,GitHub ID:UlricQin,開源監控產品 Open-Falcon、Nightingale 創始人,極客時間《運維監控系統實戰筆記》作者,目前在監控/可觀測性領域創業中。

相關文章