我們?nèi)绾谓Y(jié)合OpenTelemetry跟蹤和Prometheus指標(biāo)構(gòu)建強(qiáng)大的警報(bào)機(jī)制?
譯文譯者 | 布加迪
審校 | 重樓
工程團(tuán)隊(duì)卓越的品質(zhì)之一是另辟蹊徑,找到解決難題的創(chuàng)造性方法。作為開(kāi)發(fā)領(lǐng)導(dǎo)者,我們有責(zé)任向下一代開(kāi)發(fā)人員傳授技巧,幫助他們盡可能透過(guò)表面解決復(fù)雜的業(yè)務(wù)問(wèn)題,并充分利用開(kāi)源社區(qū)的力量。
在Helios,這種基因最近引導(dǎo)我們將復(fù)雜的邏輯委托給一個(gè)經(jīng)過(guò)驗(yàn)證的開(kāi)源項(xiàng)目(Prometheus)。我們竭力為產(chǎn)品添加警報(bào)機(jī)制。現(xiàn)在,警報(bào)不是新鮮事——許多軟件產(chǎn)品提供警報(bào)向用戶(hù)通知系統(tǒng)/產(chǎn)品中的事件,但事實(shí)上,它不是新鮮事并不意味著就沒(méi)有挑戰(zhàn)性。我們利用Prometheus(具體地說(shuō)是AWS托管Prometheus,我們選擇用它來(lái)減少內(nèi)部管理的維護(hù)開(kāi)銷(xiāo))解決了這個(gè)挑戰(zhàn)——OpenTelemetry收集器度量管道已經(jīng)在使用Prometheus,以構(gòu)建警報(bào)機(jī)制,既滿(mǎn)足了用戶(hù)的產(chǎn)品需求,又節(jié)省了開(kāi)發(fā)和維護(hù)它的大量時(shí)間和精力。
本文將介紹這一解決方案,并希望它能夠激勵(lì)開(kāi)發(fā)者創(chuàng)造性地思考可能遇到的日常挑戰(zhàn)。希望我們的經(jīng)驗(yàn)展示了我們?nèi)绾?/span>使用開(kāi)源項(xiàng)目構(gòu)建了一種大大提高了效率的解決方案,以便工程團(tuán)隊(duì)可以花寶貴的時(shí)間去解決更多的業(yè)務(wù)挑戰(zhàn)。
構(gòu)建警報(bào)機(jī)制:不需要重新發(fā)明輪子
OpenTelemetry(OTel)是一種開(kāi)源可觀察性框架,可以幫助開(kāi)發(fā)人員生成、收集和導(dǎo)出來(lái)自分布式應(yīng)用程序中的遙測(cè)數(shù)據(jù)。我們用OTel收集的數(shù)據(jù)包括幾種不同的信號(hào):分布式跟蹤數(shù)據(jù)(比如HTTP請(qǐng)求、DB調(diào)用以及發(fā)送到各種通信基礎(chǔ)設(shè)施的消息)以及指標(biāo)(比如CPU使用情況、內(nèi)存消耗和OOM事件等)。
我們開(kāi)始基于這些數(shù)據(jù)以及來(lái)自其他來(lái)源的數(shù)據(jù)構(gòu)建警報(bào)機(jī)制,使用戶(hù)能夠根據(jù)系統(tǒng)中的事件來(lái)配置條件。比如說(shuō),用戶(hù)可能會(huì)收到關(guān)于API失效、DB查詢(xún)所花時(shí)間比預(yù)期長(zhǎng)或Lambda出現(xiàn)OOM的警報(bào),他們就可以根據(jù)想要的精細(xì)度和想要的通知頻率來(lái)設(shè)置警報(bào)。
如前所述,許多軟件產(chǎn)品都需要提供警報(bào)機(jī)制,以便用戶(hù)能夠了解應(yīng)用程序或其他重要業(yè)務(wù)KPI所發(fā)生的事件方面的最新情況。這是一項(xiàng)常見(jiàn)特性,但構(gòu)建起來(lái)依然很復(fù)雜。
我們希望解決方案實(shí)現(xiàn)這三個(gè)目標(biāo):
1. 無(wú)縫地基于分布式跟蹤數(shù)據(jù)實(shí)施警報(bào)(不需要太費(fèi)力!)
2. 使一切內(nèi)容對(duì)OTel數(shù)據(jù)模型而言都是原生的
3. 快速進(jìn)入市場(chǎng)
為此,我們轉(zhuǎn)向開(kāi)源工具:我們利用了Prometheus的Alerts Manager模塊。Prometheus是用于監(jiān)視和警報(bào)的開(kāi)源行業(yè)標(biāo)準(zhǔn),旨在跟蹤應(yīng)用程序和基礎(chǔ)設(shè)施的性能和運(yùn)行狀況。Prometheus從各種來(lái)源收集指標(biāo),并提供靈活的查詢(xún)語(yǔ)言以分析和可視化數(shù)據(jù)。它是收集OTel指標(biāo)的最常見(jiàn)后端之一,我們的后端已經(jīng)有了Prometheus來(lái)支持指標(biāo)收集。
我們依靠像Prometheus這樣的開(kāi)源工具為我們做這些工作,因?yàn)檫@類(lèi)解決方案是由許多聰明而有經(jīng)驗(yàn)的開(kāi)發(fā)人員構(gòu)建的,他們有多年的豐富經(jīng)驗(yàn),調(diào)整改動(dòng)解決方案以支持許多用例,已碰到過(guò)該領(lǐng)域的所有或至少大部分陷阱。我們對(duì)警報(bào)機(jī)制的設(shè)計(jì)進(jìn)行了內(nèi)部討論,利用Prometheus的想法是由團(tuán)隊(duì)的一些成員根據(jù)他們以前的經(jīng)驗(yàn)提出的。

圖1. 設(shè)置基于分布式跟蹤數(shù)據(jù)的警報(bào)——由Prometheus Alert Manager提供支持;這個(gè)標(biāo)簽可以在Helios Sandbox中訪問(wèn)

圖2. 這個(gè)例子表明了Prometheus中如何配置來(lái)自Helios Sandbox的不同警報(bào)
深入探討:我們?nèi)绾螛?gòu)建警報(bào)機(jī)制?
有了Prometheus,我們開(kāi)始著手添加警報(bào)機(jī)制。我們想從跟蹤警報(bào)入手,或者更準(zhǔn)確地說(shuō)從跟蹤的基本模塊:span入手(比如HTTP請(qǐng)求或DB查詢(xún)的結(jié)果)。Prometheus提供了指標(biāo)警報(bào),但我們需要跟蹤警報(bào)。來(lái)自跟蹤的數(shù)據(jù)不會(huì)按原樣抵達(dá)Prometheus——它需要轉(zhuǎn)換成數(shù)據(jù)模型。因此,為了讓Prometheus實(shí)際發(fā)出span警報(bào),我們需要獲取span,將其轉(zhuǎn)換成指標(biāo),并配置由它觸發(fā)的警報(bào)。當(dāng)跟蹤(span)匹配警報(bào)條件時(shí)(比如DB查詢(xún)耗時(shí)超過(guò)5秒),我們將span轉(zhuǎn)換成Prometheus指標(biāo)。
Prometheus模型符合我們旨在實(shí)現(xiàn)的目標(biāo)。針對(duì)每個(gè)事件,我們從OTel獲得原始數(shù)據(jù),并通過(guò)Prometheus將其作為指標(biāo)來(lái)饋送。然后我們可以說(shuō),如果某個(gè)特定的操作錯(cuò)誤在五分鐘內(nèi)出現(xiàn)超過(guò)三次,就應(yīng)該激活警報(bào)。
我們沒(méi)有止步于此。在Helios中,對(duì)我們用戶(hù)來(lái)說(shuō)一大好處是我們可以從分布式跟蹤數(shù)據(jù)到一個(gè)指標(biāo),也可以從一個(gè)指標(biāo)返回到特定的跟蹤,因?yàn)槲覀兙S護(hù)指標(biāo)上下文。用戶(hù)可以設(shè)置基于跟蹤的警報(bào),然后從警報(bào)返回到E2E流,以便快速分析根本原因。這為用戶(hù)提供了終極可見(jiàn)性,以便深入了解應(yīng)用程序的性能和運(yùn)行狀況。可用的上下文(基于測(cè)量數(shù)據(jù))可幫助用戶(hù)輕松確定應(yīng)用程序流中的問(wèn)題和瓶頸,以便快速排除故障,并縮短平均解決時(shí)間(MTTR)。
基于跟蹤的警報(bào)
在警報(bào)機(jī)制中,我們構(gòu)建的機(jī)制旨在對(duì)可以根據(jù)跟蹤數(shù)據(jù)定義的行為發(fā)出警報(bào),比如服務(wù)A向服務(wù)B發(fā)出的失敗的HTTP請(qǐng)求,MongoDB對(duì)特定集合的查詢(xún)超過(guò)500毫秒,或者Lambda函數(shù)調(diào)用失敗。
以上每一項(xiàng)都可以描述為基于標(biāo)準(zhǔn)OTel屬性(比如HTTP狀態(tài)碼、span持續(xù)時(shí)間等)的span過(guò)濾器。在這些過(guò)濾器之上,我們支持各種聚合邏輯(比如,如果匹配span的數(shù)量在Y時(shí)間內(nèi)達(dá)到X)。因此,警報(bào)定義實(shí)際上是過(guò)濾器和聚合邏輯。
實(shí)施包括三個(gè)部分:
1. 為每個(gè)警報(bào)定義創(chuàng)建唯一的指標(biāo)。
2. 將聚合邏輯轉(zhuǎn)換成PromQL查詢(xún),并使用警報(bào)定義更新Prometheus Alert Manager。
3. 將匹配警報(bào)過(guò)濾器的span持續(xù)轉(zhuǎn)換成Prometheus時(shí)間序列,這將符合警報(bào)聚合定義,并觸發(fā)警報(bào)。
我們希望盡可能保持OTel原生,因此基于OTel收集器構(gòu)建警報(bào)管道,具體做法如下:
1. 創(chuàng)建alert matcher collector,它使用kafka receiver來(lái)處理從“一線”收集器(接收來(lái)自客戶(hù)的OTel SDK的數(shù)據(jù))發(fā)送的OTLP格式的span。
2. kafka receiver連接(作為跟蹤管道的一部分)到alert matcher processor,這是我們構(gòu)建的自定義處理程序,它加載我們的客戶(hù)在Helios UI中配置的過(guò)濾器,并相應(yīng)地過(guò)濾span。
3. 在過(guò)濾相關(guān)的span之后,我們需要將它們作為指標(biāo)導(dǎo)出到Prometheus。為此,我們實(shí)施了連接器,這是一項(xiàng)比較新的OTel收集器特性,允許連接不同類(lèi)型的管道(本例中是跟蹤和指標(biāo))。spans-to-metrics連接器將每個(gè)匹配的span轉(zhuǎn)換成指標(biāo),具有以下屬性:
- 它的名稱(chēng)是根據(jù)數(shù)據(jù)庫(kù)中的客戶(hù)ID和警報(bào)定義ID構(gòu)建的。
- 它的標(biāo)簽是跟蹤ID、span ID、時(shí)間戳和服務(wù)名稱(chēng)等。
4. 使用Prometheus遠(yuǎn)程寫(xiě)入導(dǎo)出器將指標(biāo)導(dǎo)出到托管的AWS Prometheus。
Prometheus幾乎直接就能發(fā)揮功效,我們要注意幾個(gè)小細(xì)節(jié),因?yàn)樗?/span>AWS管理的(比如只能使用SNS-SQS來(lái)報(bào)告警報(bào))。
從警報(bào)到根本原因
我們已有了基于跟蹤的警報(bào),但為了確保快速分析根本原因,我們還希望在觸發(fā)警報(bào)時(shí)提供完整的應(yīng)用程序上下文。觸發(fā)警報(bào)后,我們向Prometheus查詢(xún)警報(bào)定義的時(shí)間序列(客戶(hù)和警報(bào)定義ID的組合),并獲得作為警報(bào)查詢(xún)實(shí)例的指標(biāo)列表——每個(gè)指標(biāo)都有匹配的span和跟蹤ID。比如說(shuō),如果警報(bào)針對(duì)長(zhǎng)時(shí)間運(yùn)行的DB查詢(xún)配置,示例跟蹤將含有查詢(xún)本身及整個(gè)跟蹤。
整個(gè)機(jī)制看起來(lái)是這樣的:

圖3. Helios的警報(bào)機(jī)制架構(gòu)——從客戶(hù)的OpenTelemetry SDK報(bào)告的span到Slack中的警報(bào)

圖4. Helios Alerts Collector架構(gòu)——從跟蹤管道到度量管道的轉(zhuǎn)換
使用Prometheus警報(bào)作為我們方法的利弊
我們用于警報(bào)機(jī)制的方法是將OTel跟蹤數(shù)據(jù)轉(zhuǎn)換成Prometheus指標(biāo),以便利用Prometheus的Alert Manager,因而不需要實(shí)施我們自己的警報(bào)后端。不妨看看這種方法的一些優(yōu)缺點(diǎn)。
盡管優(yōu)點(diǎn)多多,但有時(shí)使用開(kāi)源工具或團(tuán)隊(duì)無(wú)法控制的任何外部組件可能很棘手,因?yàn)槟鷮?shí)際上得到的是“黑盒子”——如果其API和集成機(jī)制不適合您的架構(gòu),您可能需要做更多的工作,甚至完全受阻。
不妨看一個(gè)例子。在Prometheus中,可以通過(guò)使用API調(diào)用來(lái)更新YAML定義以配置警報(bào)。然而,我們使用的AWS Managed Prometheus支持使用AWS API調(diào)用來(lái)更新這些定義,并不直接更新Prometheus,而是在周期性同步中進(jìn)行實(shí)際更新。為了防止這種行為方面的問(wèn)題(比如由于第一次更新還沒(méi)有同步,持續(xù)更新警報(bào)定義失敗),我們必須實(shí)施自己的定期同步機(jī)制,以封裝更新。如果我們從頭開(kāi)始構(gòu)建這個(gè)解決方案,就可以全面控制這個(gè)機(jī)制,可以隨時(shí)進(jìn)行更新。在這里,由于AWS Managed Prometheus,我們沒(méi)有這種控制,這迫使我們構(gòu)建一個(gè)額外的同步機(jī)制。
此外,您可能希望調(diào)整解決方案的一些特性——比如在該例子中,我們希望在發(fā)送警報(bào)時(shí)提供精度更細(xì)的數(shù)據(jù)——這可能是個(gè)繁瑣的過(guò)程。比如在接收到警報(bào)(作為Prometheus報(bào)告的警報(bào)的有效負(fù)載的一部分)時(shí)為它們直接觸發(fā)的警報(bào)獲取匹配的span ID在默認(rèn)情況下不適用于我們,因此我們必須向Prometheus發(fā)送另一個(gè)API調(diào)用并查詢(xún)它們,這增加了一些小小的開(kāi)銷(xiāo)。
盡管存在這些挑戰(zhàn),但我們知道在不依賴(lài)Prometheus的情況下自己實(shí)施這種功能要困難得多。我們有一個(gè)開(kāi)箱即用的解決方案,節(jié)省了大量的開(kāi)發(fā)時(shí)間,而不是從頭開(kāi)始開(kāi)發(fā)警報(bào)邏輯,不然這需要設(shè)計(jì)(不同的組件和存儲(chǔ)等)、實(shí)施,可能還需要幾次錯(cuò)誤修復(fù)和反饋的迭代。
有了Prometheus這個(gè)功能豐富的成熟開(kāi)源工具,我們就省心多了。我們知道未來(lái)的用例會(huì)得到這款工具的支持,它已準(zhǔn)備好用于生產(chǎn)環(huán)境,許多用戶(hù)會(huì)對(duì)它進(jìn)行微調(diào),這給了我們很大的信心,同時(shí)節(jié)省了時(shí)間。我們知道,我們將來(lái)可能想到的任何警報(bào)邏輯都可能已經(jīng)在Prometheus中實(shí)現(xiàn)了。如果我們自行構(gòu)建,錯(cuò)誤的設(shè)計(jì)選擇可能意味著我們不得不破壞設(shè)計(jì)或編寫(xiě)糟糕的代碼來(lái)支持新用例。
此外,我們這種方法的好處之一是使所有內(nèi)容對(duì)OTel數(shù)據(jù)模型而言都是原生的。這意味著OTel收集器將過(guò)濾、處理、導(dǎo)出和接收所有內(nèi)容,至于它是span(比如失敗的HTTP請(qǐng)求)還是指標(biāo)(比如高CPU使用率)都無(wú)關(guān)緊要。
結(jié)論
在Helios開(kāi)發(fā)警報(bào)機(jī)制可能很困難,但借助一些創(chuàng)造性思維和開(kāi)源協(xié)作,我們高效而從容地完成了這項(xiàng)任務(wù)。我們利用了OTel和Prometheus,在穩(wěn)定的周轉(zhuǎn)時(shí)間內(nèi)提供了復(fù)雜的警報(bào)機(jī)制。我們找到了一種關(guān)聯(lián)span和指標(biāo)的方法,這樣當(dāng)我們獲取span并將其轉(zhuǎn)換成指標(biāo)時(shí),就知道如何將警報(bào)重新與業(yè)務(wù)邏輯聯(lián)系起來(lái)。
但愿這段經(jīng)歷不僅能激勵(lì)開(kāi)發(fā)者利用開(kāi)源解決復(fù)雜的問(wèn)題,還能成為我們用戶(hù)的好伙伴。創(chuàng)新是關(guān)鍵,但除了為了創(chuàng)新而創(chuàng)新之外,我們還希望對(duì)用戶(hù)產(chǎn)生影響,改善他們的體驗(yàn),希望您也能這樣做。
原文標(biāo)題:How we combined OpenTelemetry traces with Prometheus metrics to build a powerful alerting mechanism,作者:Ran Nozik



























