Prometheus學習系列(三十二)之編寫客戶端庫

本文檔介紹了Prometheus客戶端庫應提供的功能和API,旨在實現庫之間的一致性,簡化易用用例,避免提供可能致使用戶走錯路的功能。git

在撰寫本文時已經支持了10種語言,所以咱們如今已經很好地理解了如何編寫客戶端。 這些指南旨在幫助新客戶端庫的做者生成良好的庫。github

1、Conventions約定

MUST/MUST NOT/SHOULD/SHOULD NOT/MAY具備給出的含義在www.ietf.org/rfc/rfc2119…緩存

此外,ENCOURAGED意味着某個功能對於庫來講是理想的,但若是它不存在則能夠。 換句話說,一個很好的。安全

記住下面的幾點:併發

  • 利用每種語言的功能。
  • 經常使用用例應該很簡單
  • 作事情正確方式是簡單的方法
  • 更復雜的例子應該是可能的

經常使用用例(有序):ide

  • 沒有標籤的Counters在庫/應用程序之間傳播
  • Summaries/Histograms的時序功能/代碼塊
  • Gauges跟蹤事情的當前狀態
  • 批量任務監控
2、整體結構

必須將客戶端編寫爲內部回調。客戶一般應該遵循這裏描述的結構。函數

關鍵類是Collector。有一個方法(一般稱爲collect),返回零個或多個指標及其樣本。CollectorCollectorRegistry註冊。經過將CollectorRegistry傳遞給class/method/function``bridge來公開數據,該類以Prometheus支持的格式返回指標。每次抓取CollectorRegistry時,它都必須回調每一個Collectorcollect方法。工具

大多數用戶與之交互的界面是CounterGaugeSummaryHistogram Collectors。這些表明一個度量標準,應涵蓋用戶正在使用本身的代碼的絕大多數用例。佈局

更高級的用例(例如從另外一個監視/檢測系統代理)須要編寫自定義Collector。有人可能還想編寫一個bridge,它採用CollectorRegistry並以不一樣監控/儀表系統理解的格式生成數據,從而容許用戶只需考慮一個儀器系統。性能

CollectorRegistry應該提供register()/unregister()函數,而且應該容許收集器註冊到多個CollectorRegistrys

客戶端庫必須是線程安全的。

對於諸如C的非OO語言,客戶端庫應該儘量地遵循這種結構的精神。

2.1 命名

客戶端庫應該遵循本文檔中提到的function/method/class,記住它們所使用的語言的命名約定。例如,set_to_current_time()適用於方法名稱Python,但SetToCurrentTime()更好 在Go中,setToCurrentTime()是Java中的約定。 若是名稱因技術緣由而不一樣(例如,不容許函數重載),文檔/幫助字符串應該將用戶指向其餘名稱。

庫不得提供與此處給出的名稱相同或類似的函數/方法/類,但具備不一樣的語義。

3、Metrics

CounterGaugeSummaryHistogram度量指標類型是最主要的接口。

CounterGauge必須是客戶庫的一部分。SummaryHistogram至少被提供一個。

這些應該主要用做文件靜態變量,即在與它們正在檢測的代碼相同的文件中定義的全局變量。客戶端庫應該啓用它。常見的用例是總體編寫一段代碼,而不是在一個對象實例的上下文中編寫代碼。用戶沒必要擔憂在他們的代碼中管理他們的指標,客戶端庫應該爲他們作這些(若是沒有,用戶將在庫周圍編寫一個包裝器以使其「更容易」 - 這不多傾向於好吧)。

必須有一個默認的CollectorRegistry,默認狀況下,標準指標必須隱式註冊到它中,而不須要用戶進行任何特殊工做。必須有一種方法能夠將指標註冊到默認的CollectorRegistry,以便在批處理做業和單元測試中使用。定製收藏家也應該遵循這一點。

究竟應該如何建立指標因語言而異。對於某些人(Java,Go),構建器方法是最好的,而對於其餘人(Python),函數參數足夠豐富,能夠在一次調用中完成。

例如,在Java Simpleclient中,咱們有:

class YourClass {
  static final Counter requests = Counter.build()
      .name("requests_total")
      .help("Requests.").register();
}
複製代碼

這將使用默認的CollectorRegistry註冊請求。 經過調用build()而不是register(),度量標準將不會被註冊(方便單元測試),您還能夠將CollectorRegistry傳遞給register()(便於批處理做業)。

3.1 Counter

Counter[prometheus.io/docs/concep…]是一個單調遞增的計數器。它不容許counter值降低,可是它能夠被重置爲0(例如:客戶端服務重啓)。

一個counter必須有如下方法:

  • inc(): 增量爲1.
  • inc(double v): 增長給定值v。必須檢查v>=0。

一個Counter鼓勵有:

一種計算在給定代碼段中拋出/引起異常的方法,以及可選的僅某些類型的異常。 這是Python中的count_exceptions。

計數器必須從0開始。

3.2 Gauge

Gauge表示一個能夠上下波動的值。

gauge必須有如下的方法:

  • inc(): 每次增長1
  • inc(double v): 每次增長給定值v
  • dec(): 每次減小1
  • dec(double v): 每次減小給定值v
  • set(double v): 設置gauge值成v

Gauges值必須從0開始,你能夠爲給定的量表提供一種方法,以不一樣的數字開始。

gauge應該有如下方法:

  • set_to_current_time(): 將gauge設置爲當前的unix時間(以秒爲單位)。

gauge被建議有: 一種跟蹤某些代碼/功能中正在進行的請求的方法。 這是Python中的track_inprogress

一種爲一段代碼計時並將儀表設置爲其持續時間的方法,以秒爲單位。 這對批處理做業頗有用。 這是Java中的startTimer/setDuration和Python中的time()裝飾器/上下文管理器。 這應該與Summary/Histogram中的模式匹配(儘管是set()而不是observe())。

3.3 Summary

summary經過時間滑動窗口抽樣觀察(一般是要求持續時間),並提供對其分佈、頻率和總和的即時觀察。

Summary毫不容許用戶將「quantile」設置爲標籤名稱,由於這在內部用於指定摘要分位數。 一個Summary是ENCOURAGED提供分位數做爲出口,雖然這些不能彙總,每每很慢。 總結必須容許沒有分位數,由於_count/_sum很是有用,這必須是默認值。

Summary必須具備如下方法:

  • observe(double v):觀察給定量

Summary應該有如下方法:

一些方法能夠在幾秒鐘內爲用戶計時。 在Python中,這是time()裝飾器/上下文管理器。 在Java中,這是startTimer/observeDuration。 毫不能提供秒之外的單位(若是用戶想要其餘東西,他們能夠手工完成)。 這應該遵循與Gauge/Histogram相同的模式。

Summary``_count/_sum必須從0開始。

3.4 Histogram

Histogram容許可聚合的事件分佈,例如請求延遲。 這是每一個桶的核心。

Histogram毫不容許le做爲用戶設置標籤,由於le在內部用於指定存儲桶。

Histogram必須提供一種手動選擇存儲桶的方法。應該提供以linear(start, width, count)exponential(start, factor, count)方式設置桶的方法。計數必須排除+Inf桶。

Histogram應該與其餘客戶端庫具備相同的默認存儲桶。建立度量標準後,不得更改存儲桶。

Histogram必須有如下方法:

  • observe(double v):觀察給定量

Histogram應該有如下方法:

一些方法能夠在幾秒鐘內爲用戶計時。在Python中,這是time()裝飾器/上下文管理器。在Java中,這是startTimer/observeDuration。毫不能提供秒之外的單位(若是用戶想要其餘東西,他們能夠手工完成)。這應該遵循與Gauge/Summary相同的模式。

Histogram``_count/_sum和桶必須從0開始。

進一步的指標考慮

除了上面記錄的對於給定語言有意義的指標以外,還提供額外的功能,這是ENCOURAGED。

若是有一個常見的用例,你能夠作得更簡單而後去作,只要它不會鼓勵不良行爲(例如次優的度量/標籤佈局,或在客戶端進行計算)。

3.5 標籤

標籤是普羅米修斯最強大的方面之一,但很容易被濫用。所以,客戶端庫必須很是當心地向用戶提供標籤。

在任何狀況下,客戶端庫都不容許用戶爲Gauge/Counter/Summary/Histogram或庫提供的任何其餘Collector的相同度量標準指定不一樣的標籤名稱。

自定義收集器中的度量標準幾乎老是具備一致的標籤名稱。因爲仍然存在罕見但有效的用例,但事實並不是如此,客戶端庫不該對此進行驗證。

雖然標籤功能強大,但大多數指標都沒有標籤。所以,API應該容許標籤但不支配它。

客戶端庫必須容許在Gauge/Counter/Summary/Histogram建立時指定標籤名稱列表。客戶端庫應該支持任意數量的標籤名稱。客戶端庫必須驗證標籤名稱是否符合記錄的要求。

提供對度量標註維度的訪問的通常方法是使用labels()方法,該方法獲取標籤值列表或從標籤名稱到標籤值的映射並返回「Child」。而後能夠在Child上調用一般的.inc()/.dec()/.observe()等方法。

labels()返回的子項應該由用戶緩存,以免再次查找 - 這在延遲關鍵代碼中很重要。

帶標籤的度量標準應該支持一個remove()方法,該方法具備與labels()相同的簽名,它將從再也不導出它的度量中刪除Child,以及一個從度量中刪除全部Children的clear()方法。這些無效的緩存兒童。

應該是一種使用默認值初始化給定Child的方法,一般只是調用labels()。必須始終初始化沒有標籤的度量標準以免缺乏度量標準的問題。

3.6 度量指標名稱

度量標準名稱必須遵循規範。 與標籤名稱同樣,必須知足使用Gauge/Counter/Summary/Histogram以及隨庫提供的任何其餘Collector。

許多客戶端庫提供了三個部分的名稱設置:namespace_subsystem_name,其中只有name是必需的。

除非自定義收集器從其餘檢測/監視系統進行代理,不然不得禁止動態/生成的度量標準名稱或度量標準名稱的子部分。 生成/動態度量標準名稱是您應該使用標籤的標誌。

3.7 度量指標描述和幫助

Gauge/Counter/Summary/Histogram必需要求提供度量標準描述/幫助。

隨客戶端庫提供的任何自定義收集器必須具備其指標的描述/幫助。

建議將其做爲強制性參數,但不要檢查它是否具備必定的長度,好像有人真的不想寫文檔,不然咱們不會說服它們。 圖書館提供的收藏家(實際上咱們能夠在生態系統中的任何地方)應該有很好的度量描述,以身做則。

4、導出

客戶必須實現博覽會格式文檔中概述的基於文本的導出格式

若是能夠在沒有顯着資源成本的狀況下實現暴露度量的可重現順序是ENCOURAGED(特別是對於人類可讀格式)。

5、標準化和運行時收集器

客戶端庫應該提供標準導出的功能,以下所示。

這些應該做爲自定義收集器實現,並默認註冊在默認的CollectorRegistry上。 應該有一種方法來禁用它們,由於有一些很是小的用例會妨礙它們。

5.1 處理度量指標

這些導出應該有前綴process_。 若是語言或運行時沒有公開其中一個變量,那麼它就不會導出它。 全部內存值,以字節爲單位,全部時間均爲unixtime/seconds

度量指標名稱 含義 單位
process_cpu_seconds_total 用戶和系統CPU花費的時間
process_open_fds 打開的文件描述符數量 文件描述符
process_max_fds 打開描述符最大值 文件描述符
process_virtual_memory_bytes 虛擬內存大小 字節
process_resident_memory_bytes 駐留內存大小 字節
process_heap_bytes 進程head堆大小 字節
process_start_time_seconds unix時間
5.2 運行時度量指標

此外,還鼓勵客戶端庫提供其語言運行時(例如垃圾收集統計信息)的度量標準,並提供適當的前綴,如go_hostspot_等。

6、單元測試

客戶端庫應該有單元測試,涵蓋核心工具庫和博覽會。

客戶端庫鼓勵提供方便用戶對其使用儀器代碼進行單元測試的方法。 例如,Python中的CollectorRegistry.get_sample_value

7、包和依賴

理想狀況下,客戶端庫能夠包含在任何應用程序中,以便在不破壞應用程序的狀況下添加一些檢測。

所以,在向客戶端庫添加依賴項時,建議謹慎。 例如,若是添加使用Prometheus客戶端的庫,該客戶端須要x.y版本的庫但應用程序在其餘地方使用x.z,那麼這會對應用程序產生負面影響嗎?

建議在可能出現這種狀況時,將核心工具與給定格式的度量的橋樑/展現分開。 例如,Java simpleclient simpleclient模塊沒有依賴關係,simpleclient_servlet具備HTTP位。

8、性能考慮

因爲客戶端庫必須是線程安全的,所以須要某種形式的併發控制,而且必須考慮多核機器和應用程序的性能。

根據咱們的經驗,效果最差的是互斥體。

處理器原子指令每每位於中間,而且一般是可接受的。

避免不一樣CPU改變相同RAM的方法最有效,例如Java的simpleclient中的DoubleAdder。可是有記憶費用。

如上所述,labels()的結果應該是可緩存的。傾向於使用標籤返回度量標準的併發映射每每相對較慢。沒有標籤的特殊套管指標能夠避免labels()- 像查找同樣能夠提供不少幫助。

度量標準應當在遞增/遞減/設置等時避免阻塞,由於在刮擦正在進行時整個應用程序被阻止是不可取的。

主要儀器操做(包括標籤)的基準測試是鼓勵的。

在進行博覽會時,應牢記資源消耗,特別是RAM。考慮經過流式傳輸結果減小內存佔用量,並可能限制併發擦除次數。

9、連接

Prometheus官網地址:prometheus.io/ 個人Github:github.com/Alrights/pr…

相關文章
相關標籤/搜索