本文檔介紹了Prometheus客戶端庫(kù)應(yīng)提供的功能和API,旨在實(shí)現(xiàn)庫(kù)之間的一致性总寻,簡(jiǎn)化易用用例器罐,避免提供可能導(dǎo)致用戶走錯(cuò)路的功能。
在撰寫(xiě)本文時(shí)已經(jīng)支持了10種語(yǔ)言渐行,因此我們現(xiàn)在已經(jīng)很好地理解了如何編寫(xiě)客戶端轰坊。 這些指南旨在幫助新客戶端庫(kù)的作者生成良好的庫(kù)。
一祟印、Conventions約定
MUST/MUST NOT/SHOULD/SHOULD NOT/MAY具有給出的含義在https://www.ietf.org/rfc/rfc2119.txt
此外肴沫,ENCOURAGED意味著某個(gè)功能對(duì)于庫(kù)來(lái)說(shuō)是理想的,但如果它不存在則可以蕴忆。 換句話說(shuō)颤芬,一個(gè)很好的。
記住下面的幾點(diǎn):
- 利用每種語(yǔ)言的功能套鹅。
- 常用用例應(yīng)該很簡(jiǎn)單
- 做事情正確方式是簡(jiǎn)單的方法
- 更復(fù)雜的例子應(yīng)該是可能的
常用用例(有序):
- 沒(méi)有標(biāo)簽的Counters在庫(kù)/應(yīng)用程序之間傳播
- Summaries/Histograms的時(shí)序功能/代碼塊
- Gauges跟蹤事情的當(dāng)前狀態(tài)
- 批量任務(wù)監(jiān)控
二站蝠、總體結(jié)構(gòu)
必須將客戶端編寫(xiě)為內(nèi)部回調(diào)∽柯梗客戶通常應(yīng)該遵循這里描述的結(jié)構(gòu)沉衣。
關(guān)鍵類是Collector
。有一個(gè)方法(通常稱為collect
)减牺,返回零個(gè)或多個(gè)指標(biāo)及其樣本豌习。Collector
在CollectorRegistry
注冊(cè)。通過(guò)將CollectorRegistry
傳遞給class/method/function``bridge
來(lái)公開(kāi)數(shù)據(jù)拔疚,該類以Prometheus支持的格式返回指標(biāo)肥隆。每次抓取CollectorRegistry
時(shí),它都必須回調(diào)每個(gè)Collector
的collect
方法稚失。
大多數(shù)用戶與之交互的界面是Counter
栋艳,Gauge
,Summary
和Histogram
Collectors句各。這些代表一個(gè)度量標(biāo)準(zhǔn)吸占,應(yīng)涵蓋用戶正在使用自己的代碼的絕大多數(shù)用例。
更高級(jí)的用例(例如從另一個(gè)監(jiān)視/檢測(cè)系統(tǒng)代理)需要編寫(xiě)自定義Collector
凿宾。有人可能還想編寫(xiě)一個(gè)bridge
矾屯,它采用CollectorRegistry
并以不同監(jiān)控/儀表系統(tǒng)理解的格式生成數(shù)據(jù),從而允許用戶只需考慮一個(gè)儀器系統(tǒng)初厚。
CollectorRegistry
應(yīng)該提供register()/unregister()
函數(shù)件蚕,并且應(yīng)該允許收集器注冊(cè)到多個(gè)CollectorRegistrys
。
客戶端庫(kù)必須是線程安全的。
對(duì)于諸如C的非OO語(yǔ)言排作,客戶端庫(kù)應(yīng)該盡可能地遵循這種結(jié)構(gòu)的精神牵啦。
2.1 命名
客戶端庫(kù)應(yīng)該遵循本文檔中提到的function/method/class
,記住它們所使用的語(yǔ)言的命名約定妄痪。例如哈雏,set_to_current_time()
適用于方法名稱Python,但SetToCurrentTime()
更好 在Go中衫生,setToCurrentTime()
是Java中的約定裳瘪。 如果名稱因技術(shù)原因而不同(例如,不允許函數(shù)重載)障簿,文檔/幫助字符串應(yīng)該將用戶指向其他名稱。
庫(kù)不得提供與此處給出的名稱相同或相似的函數(shù)/方法/類栅迄,但具有不同的語(yǔ)義站故。
三、Metrics
Counter
毅舆、Gauge
西篓、Summary
和Histogram
度量指標(biāo)類型是最主要的接口。
Counter
和Gauge
必須是客戶庫(kù)的一部分憋活。Summary
和Histogram
至少被提供一個(gè)岂津。
這些應(yīng)該主要用作文件靜態(tài)變量,即在與它們正在檢測(cè)的代碼相同的文件中定義的全局變量悦即∷背桑客戶端庫(kù)應(yīng)該啟用它。常見(jiàn)的用例是整體編寫(xiě)一段代碼辜梳,而不是在一個(gè)對(duì)象實(shí)例的上下文中編寫(xiě)代碼粱甫。用戶不必?fù)?dān)心在他們的代碼中管理他們的指標(biāo),客戶端庫(kù)應(yīng)該為他們做這些(如果沒(méi)有作瞄,用戶將在庫(kù)周圍編寫(xiě)一個(gè)包裝器以使其“更容易” - 這很少傾向于好吧)茶宵。
必須有一個(gè)默認(rèn)的CollectorRegistry
,默認(rèn)情況下宗挥,標(biāo)準(zhǔn)指標(biāo)必須隱式注冊(cè)到它中乌庶,而不需要用戶進(jìn)行任何特殊工作。必須有一種方法可以將指標(biāo)注冊(cè)到默認(rèn)的CollectorRegistry
契耿,以便在批處理作業(yè)和單元測(cè)試中使用瞒大。定制收藏家也應(yīng)該遵循這一點(diǎn)。
究竟應(yīng)該如何創(chuàng)建指標(biāo)因語(yǔ)言而異搪桂。對(duì)于某些人(Java糠赦,Go),構(gòu)建器方法是最好的,而對(duì)于其他人(Python)拙泽,函數(shù)參數(shù)足夠豐富淌山,可以在一次調(diào)用中完成。
例如顾瞻,在Java Simpleclient中泼疑,我們有:
class YourClass {
static final Counter requests = Counter.build()
.name("requests_total")
.help("Requests.").register();
}
這將使用默認(rèn)的CollectorRegistry
注冊(cè)請(qǐng)求。 通過(guò)調(diào)用build()
而不是register()
荷荤,度量標(biāo)準(zhǔn)將不會(huì)被注冊(cè)(方便單元測(cè)試)退渗,您還可以將CollectorRegistry
傳遞給register()
(便于批處理作業(yè))。
3.1 Counter
Counter
[https://prometheus.io/docs/concepts/metric_types/#counter]是一個(gè)單調(diào)遞增的計(jì)數(shù)器蕴纳。它不允許counter值下降会油,但是它可以被重置為0(例如:客戶端服務(wù)重啟)。
一個(gè)counter必須有以下方法:
-
inc()
: 增量為1. -
inc(double v)
: 增加給定值v古毛。必須檢查v>=0翻翩。
一個(gè)Counter
鼓勵(lì)有:
一種計(jì)算在給定代碼段中拋出/引發(fā)異常的方法,以及可選的僅某些類型的異常稻薇。 這是Python中的count_exceptions嫂冻。
計(jì)數(shù)器必須從0開(kāi)始。
3.2 Gauge
Gauge表示一個(gè)可以上下波動(dòng)的值塞椎。
gauge必須有以下的方法:
-
inc()
: 每次增加1 -
inc(double v)
: 每次增加給定值v -
dec()
: 每次減少1 -
dec(double v)
: 每次減少給定值v -
set(double v)
: 設(shè)置gauge值成v
Gauges值必須從0開(kāi)始桨仿,你可以為給定的量表提供一種方法,以不同的數(shù)字開(kāi)始案狠。
gauge應(yīng)該有以下方法:
-
set_to_current_time()
: 將gauge設(shè)置為當(dāng)前的unix時(shí)間(以秒為單位)服傍。
gauge被建議有:
一種跟蹤某些代碼/功能中正在進(jìn)行的請(qǐng)求的方法。 這是Python中的track_inprogress
骂铁。
一種為一段代碼計(jì)時(shí)并將儀表設(shè)置為其持續(xù)時(shí)間的方法伴嗡,以秒為單位。 這對(duì)批處理作業(yè)很有用从铲。 這是Java中的startTimer/setDuration
和Python中的time()
裝飾器/上下文管理器瘪校。 這應(yīng)該與Summary/Histogram
中的模式匹配(盡管是set()
而不是observe()
)。
3.3 Summary
summary通過(guò)時(shí)間滑動(dòng)窗口抽樣觀察(通常是要求持續(xù)時(shí)間)名段,并提供對(duì)其分布阱扬、頻率和總和的即時(shí)觀察。
Summary
絕不允許用戶將“quantile”設(shè)置為標(biāo)簽名稱伸辟,因?yàn)檫@在內(nèi)部用于指定摘要分位數(shù)麻惶。 一個(gè)Summary
是ENCOURAGED提供分位數(shù)作為出口,雖然這些不能匯總信夫,往往很慢窃蹋。 總結(jié)必須允許沒(méi)有分位數(shù)卡啰,因?yàn)?code>_count/_sum非常有用,這必須是默認(rèn)值警没。
Summary
必須具有以下方法:
-
observe(double v)
:觀察給定量
Summary
應(yīng)該有以下方法:
一些方法可以在幾秒鐘內(nèi)為用戶計(jì)時(shí)匈辱。 在Python中,這是time()
裝飾器/上下文管理器杀迹。 在Java中亡脸,這是startTimer/observeDuration
。 絕不能提供秒以外的單位(如果用戶想要其他東西树酪,他們可以手工完成)浅碾。 這應(yīng)該遵循與Gauge/Histogram
相同的模式。
Summary``_count/_sum
必須從0開(kāi)始续语。
3.4 Histogram
Histogram允許可聚合的事件分布垂谢,例如請(qǐng)求延遲。 這是每個(gè)桶的核心疮茄。
Histogram
絕不允許le
作為用戶設(shè)置標(biāo)簽滥朱,因?yàn)?code>le在內(nèi)部用于指定存儲(chǔ)桶。
Histogram
必須提供一種手動(dòng)選擇存儲(chǔ)桶的方法娃豹。應(yīng)該提供以linear(start, width, count)
和exponential(start, factor, count)
方式設(shè)置桶的方法焚虱。計(jì)數(shù)必須排除+Inf
桶购裙。
Histogram
應(yīng)該與其他客戶端庫(kù)具有相同的默認(rèn)存儲(chǔ)桶懂版。創(chuàng)建度量標(biāo)準(zhǔn)后,不得更改存儲(chǔ)桶躏率。
Histogram
必須有以下方法:
-
observe(double v)
:觀察給定量
Histogram
應(yīng)該有以下方法:
一些方法可以在幾秒鐘內(nèi)為用戶計(jì)時(shí)躯畴。在Python中,這是time()
裝飾器/上下文管理器薇芝。在Java中蓬抄,這是startTimer/observeDuration
。絕不能提供秒以外的單位(如果用戶想要其他東西夯到,他們可以手工完成)嚷缭。這應(yīng)該遵循與Gauge/Summary
相同的模式。
Histogram``_count/_sum
和桶必須從0開(kāi)始耍贾。
進(jìn)一步的指標(biāo)考慮
除了上面記錄的對(duì)于給定語(yǔ)言有意義的指標(biāo)之外阅爽,還提供額外的功能,這是ENCOURAGED荐开。
如果有一個(gè)常見(jiàn)的用例付翁,你可以做得更簡(jiǎn)單然后去做,只要它不會(huì)鼓勵(lì)不良行為(例如次優(yōu)的度量/標(biāo)簽布局晃听,或在客戶端進(jìn)行計(jì)算)百侧。
3.5 標(biāo)簽
標(biāo)簽是普羅米修斯最強(qiáng)大的方面之一砰识,但很容易被濫用。因此佣渴,客戶端庫(kù)必須非常小心地向用戶提供標(biāo)簽辫狼。
在任何情況下,客戶端庫(kù)都不允許用戶為Gauge/Counter/Summary/Histogram
或庫(kù)提供的任何其他Collector
的相同度量標(biāo)準(zhǔn)指定不同的標(biāo)簽名稱观话。
自定義收集器中的度量標(biāo)準(zhǔn)幾乎總是具有一致的標(biāo)簽名稱予借。由于仍然存在罕見(jiàn)但有效的用例,但事實(shí)并非如此频蛔,客戶端庫(kù)不應(yīng)對(duì)此進(jìn)行驗(yàn)證灵迫。
雖然標(biāo)簽功能強(qiáng)大,但大多數(shù)指標(biāo)都沒(méi)有標(biāo)簽晦溪。因此瀑粥,API應(yīng)該允許標(biāo)簽但不支配它。
客戶端庫(kù)必須允許在Gauge/Counter/Summary/Histogram
創(chuàng)建時(shí)指定標(biāo)簽名稱列表三圆∧唬客戶端庫(kù)應(yīng)該支持任意數(shù)量的標(biāo)簽名稱≈廴猓客戶端庫(kù)必須驗(yàn)證標(biāo)簽名稱是否符合記錄的要求修噪。
提供對(duì)度量標(biāo)注維度的訪問(wèn)的一般方法是使用labels()
方法,該方法獲取標(biāo)簽值列表或從標(biāo)簽名稱到標(biāo)簽值的映射并返回“Child”路媚。然后可以在Child上調(diào)用通常的.inc()/.dec()/.observe()
等方法黄琼。
labels()
返回的子項(xiàng)應(yīng)該由用戶緩存,以避免再次查找 - 這在延遲關(guān)鍵代碼中很重要整慎。
帶標(biāo)簽的度量標(biāo)準(zhǔn)應(yīng)該支持一個(gè)remove()
方法脏款,該方法具有與labels()
相同的簽名,它將從不再導(dǎo)出它的度量中刪除Child裤园,以及一個(gè)從度量中刪除所有Children的clear()
方法撤师。這些無(wú)效的緩存兒童。
應(yīng)該是一種使用默認(rèn)值初始化給定Child的方法拧揽,通常只是調(diào)用labels()
剃盾。必須始終初始化沒(méi)有標(biāo)簽的度量標(biāo)準(zhǔn)以避免缺少度量標(biāo)準(zhǔn)的問(wèn)題。
3.6 度量指標(biāo)名稱
度量標(biāo)準(zhǔn)名稱必須遵循規(guī)范淤袜。 與標(biāo)簽名稱一樣痒谴,必須滿足使用Gauge/Counter/Summary/Histogram
以及隨庫(kù)提供的任何其他Collector。
許多客戶端庫(kù)提供了三個(gè)部分的名稱設(shè)置:namespace_subsystem_name
饮怯,其中只有name
是必需的闰歪。
除非自定義收集器從其他檢測(cè)/監(jiān)視系統(tǒng)進(jìn)行代理,否則不得禁止動(dòng)態(tài)/生成的度量標(biāo)準(zhǔn)名稱或度量標(biāo)準(zhǔn)名稱的子部分蓖墅。 生成/動(dòng)態(tài)度量標(biāo)準(zhǔn)名稱是您應(yīng)該使用標(biāo)簽的標(biāo)志库倘。
3.7 度量指標(biāo)描述和幫助
Gauge/Counter/Summary/Histogram
必須要求提供度量標(biāo)準(zhǔn)描述/幫助临扮。
隨客戶端庫(kù)提供的任何自定義收集器必須具有其指標(biāo)的描述/幫助。
建議將其作為強(qiáng)制性參數(shù)教翩,但不要檢查它是否具有一定的長(zhǎng)度杆勇,好像有人真的不想寫(xiě)文檔,否則我們不會(huì)說(shuō)服它們饱亿。 圖書(shū)館提供的收藏家(實(shí)際上我們可以在生態(tài)系統(tǒng)中的任何地方)應(yīng)該有很好的度量描述蚜退,以身作則。
四彪笼、導(dǎo)出
客戶必須實(shí)現(xiàn)博覽會(huì)格式文檔中概述的基于文本的導(dǎo)出格式钻注。
如果可以在沒(méi)有顯著資源成本的情況下實(shí)現(xiàn)暴露度量的可重現(xiàn)順序是ENCOURAGED(特別是對(duì)于人類可讀格式)。
五配猫、標(biāo)準(zhǔn)化和運(yùn)行時(shí)收集器
客戶端庫(kù)應(yīng)該提供標(biāo)準(zhǔn)導(dǎo)出的功能幅恋,如下所示。
這些應(yīng)該作為自定義收集器實(shí)現(xiàn)泵肄,并默認(rèn)注冊(cè)在默認(rèn)的CollectorRegistry上捆交。 應(yīng)該有一種方法來(lái)禁用它們,因?yàn)橛幸恍┓浅P〉挠美龝?huì)妨礙它們腐巢。
5.1 處理度量指標(biāo)
這些導(dǎo)出應(yīng)該有前綴process_
品追。 如果語(yǔ)言或運(yùn)行時(shí)沒(méi)有公開(kāi)其中一個(gè)變量,那么它就不會(huì)導(dǎo)出它冯丙。 所有內(nèi)存值肉瓦,以字節(jié)為單位,所有時(shí)間均為unixtime/seconds
银还。
度量指標(biāo)名稱 | 含義 | 單位 |
---|---|---|
process_cpu_seconds_total | 用戶和系統(tǒng)CPU花費(fèi)的時(shí)間 | 秒 |
process_open_fds | 打開(kāi)的文件描述符數(shù)量 | 文件描述符 |
process_max_fds | 打開(kāi)描述符最大值 | 文件描述符 |
process_virtual_memory_bytes | 虛擬內(nèi)存大小 | 字節(jié) |
process_resident_memory_bytes | 駐留內(nèi)存大小 | 字節(jié) |
process_heap_bytes | 進(jìn)程head堆大小 | 字節(jié) |
process_start_time_seconds | unix時(shí)間 | 秒 |
5.2 運(yùn)行時(shí)度量指標(biāo)
此外风宁,還鼓勵(lì)客戶端庫(kù)提供其語(yǔ)言運(yùn)行時(shí)(例如垃圾收集統(tǒng)計(jì)信息)的度量標(biāo)準(zhǔn)洁墙,并提供適當(dāng)?shù)那熬Y蛹疯,如go_
,hostspot_
等热监。
六捺弦、單元測(cè)試
客戶端庫(kù)應(yīng)該有單元測(cè)試,涵蓋核心工具庫(kù)和博覽會(huì)孝扛。
客戶端庫(kù)鼓勵(lì)提供方便用戶對(duì)其使用儀器代碼進(jìn)行單元測(cè)試的方法列吼。 例如,Python中的CollectorRegistry.get_sample_value
苦始。
七寞钥、包和依賴
理想情況下,客戶端庫(kù)可以包含在任何應(yīng)用程序中陌选,以便在不破壞應(yīng)用程序的情況下添加一些檢測(cè)理郑。
因此蹄溉,在向客戶端庫(kù)添加依賴項(xiàng)時(shí),建議謹(jǐn)慎您炉。 例如柒爵,如果添加使用Prometheus客戶端的庫(kù),該客戶端需要x.y版本的庫(kù)但應(yīng)用程序在其他地方使用x.z赚爵,那么這會(huì)對(duì)應(yīng)用程序產(chǎn)生負(fù)面影響嗎棉胀?
建議在可能出現(xiàn)這種情況時(shí),將核心工具與給定格式的度量的橋梁/展示分開(kāi)冀膝。 例如唁奢,Java simpleclient simpleclient
模塊沒(méi)有依賴關(guān)系,simpleclient_servlet
具有HTTP位窝剖。
八驮瞧、性能考慮
由于客戶端庫(kù)必須是線程安全的,因此需要某種形式的并發(fā)控制枯芬,并且必須考慮多核機(jī)器和應(yīng)用程序的性能论笔。
根據(jù)我們的經(jīng)驗(yàn),效果最差的是互斥體千所。
處理器原子指令往往位于中間狂魔,并且通常是可接受的。
避免不同CPU改變相同RAM的方法最有效淫痰,例如Java的simpleclient中的DoubleAdder最楷。但是有記憶費(fèi)用。
如上所述待错,labels()
的結(jié)果應(yīng)該是可緩存的籽孙。傾向于使用標(biāo)簽返回度量標(biāo)準(zhǔn)的并發(fā)映射往往相對(duì)較慢。沒(méi)有標(biāo)簽的特殊套管指標(biāo)可以避免labels()
- 像查找一樣可以提供很多幫助火俄。
度量標(biāo)準(zhǔn)應(yīng)當(dāng)在遞增/遞減/設(shè)置等時(shí)避免阻塞犯建,因?yàn)樵诠尾琳谶M(jìn)行時(shí)整個(gè)應(yīng)用程序被阻止是不可取的。
主要儀器操作(包括標(biāo)簽)的基準(zhǔn)測(cè)試是鼓勵(lì)的瓜客。
在進(jìn)行博覽會(huì)時(shí)适瓦,應(yīng)牢記資源消耗,特別是RAM谱仪〔N酰考慮通過(guò)流式傳輸結(jié)果減少內(nèi)存占用量,并可能限制并發(fā)擦除次數(shù)疯攒。
九嗦随、鏈接
Prometheus官網(wǎng)地址:https://prometheus.io/
我的Github:https://github.com/Alrights/prometheus