如果您正在為自己的程式碼進行儀器化,應遵循使用 Prometheus client 程式庫為程式碼進行儀器化的一般規則。從其他監控或儀器化系統擷取指標時,情況往往沒有這麼黑白分明。
撰寫匯出器或自訂收集器時,此文件包含您應該考慮的事項。所涵蓋的理論也將引起從事直接儀器化的人的興趣。
如果您正在撰寫匯出器,並且對此處的任何內容感到困惑,請透過 IRC (#prometheus on libera) 或郵件清單與我們聯繫。
撰寫匯出器時,您需要做出的主要決定是您願意投入多少工作來取得完美的指標。
如果所討論的系統只有少數指標且很少變更,那麼將所有內容都弄得完美是一個容易的選擇,HAProxy 匯出器就是一個很好的例子。
另一方面,如果您嘗試在系統有數百個指標且隨著新版本頻繁變更時將所有內容弄得完美,那麼您就註定要進行大量的持續工作。MySQL 匯出器就在這個範圍的另一端。
節點匯出器是這些的混合,複雜度因模組而異。例如,mdadm
收集器手動解析檔案並公開專門為該收集器建立的指標,因此我們可以取得正確的指標。對於meminfo
收集器,結果會因核心版本而異,因此我們最終只會執行足夠的轉換來建立有效的指標。
在使用應用程式時,你應該要以一個不需使用者自訂組態的匯出器為目標,只要告訴匯出器應用程式在哪裡即可。你可能也需要提供過濾特定指標的功能,如果這些指標在大型設定中過於細緻且昂貴,例如 HAProxy 匯出器 允許過濾每個伺服器的統計資料。同樣地,也可能有一些昂貴的指標在預設情況下會被停用。
在使用其他監控系統、架構和協定時,你通常需要提供額外的組態或自訂化,才能產生適合 Prometheus 的指標。在最佳情況下,監控系統具有與 Prometheus 非常相似的資料模型,你可以自動判斷如何轉換指標。對於 Cloudwatch、SNMP 和 collectd 來說就是如此。充其量,我們需要讓使用者能夠選擇他們想要提取的指標。
在其他情況下,系統的指標完全是非標準的,這取決於系統和底層應用程式的使用情況。在這種情況下,使用者必須告訴我們如何轉換指標。JMX 匯出器 是這裡最糟糕的違規者,Graphite 和 StatsD 匯出器也需要組態才能提取標籤。
建議確保匯出器在沒有組態的情況下也能正常運作,並在需要時提供一系列轉換範例組態。
YAML 是標準的 Prometheus 組態格式,預設所有組態都應該使用 YAML。
遵循 指標命名最佳實務。
一般來說,指標名稱應該讓熟悉 Prometheus 但不熟悉特定系統的人可以很好地猜測指標的意義。名為 http_requests_total
的指標並不是很實用 - 這些指標是在進入時、在某些過濾器中還是當它們到達使用者的程式碼時測量的?而 requests_total
甚至更糟,什麼類型的請求?
在直接儀器化中,給定的指標應該只存在於一個檔案中。因此,在匯出器和收集器中,指標應該套用於一個子系統,並相應地命名。
指標名稱絕不應該以程序方式產生,除非撰寫自訂收集器或匯出器。
應用程式的指標名稱通常應該以匯出器名稱為前綴,例如 haproxy_up
。
指標必須使用基本單位(例如秒、位元組),並將轉換為更易於讀取的內容留給繪圖工具。無論最終使用什麼單位,指標名稱中的單位都必須與使用中的單位相符。類似地,顯示比率,而不是百分比。更好的做法是,為比率的兩個組成部分指定一個計數器。
指標名稱不應包含其匯出的標籤,例如 by_type
,因為如果標籤被匯總,這將沒有意義。
唯一的例外是,當您透過多個指標使用不同的標籤匯出相同資料時,這種情況通常是區分它們最明智的方法。對於直接儀器化,只有在匯出具有所有標籤的單一指標會導致過高的基數時,才會出現這種情況。
Prometheus 指標和標籤名稱以 snake_case
撰寫。將 camelCase
轉換為 snake_case
是可取的,儘管自動執行此操作並不總是會產生良好的結果,例如 myTCPExample
或 isNaN
,因此有時最好保持原樣。
公開的指標不應包含冒號,這些冒號是保留給使用者定義的記錄規則在匯總時使用。
指標名稱中僅 [a-zA-Z0-9:_]
有效。
摘要、直方圖和計數器使用 _sum
、_count
、_bucket
和 _total
字尾。除非您要產生其中之一,否則請避免使用這些字尾。
_total
是計數器的慣例,如果您使用 COUNTER 類型,則應使用它。
process_
和 scrape_
前綴是保留的。如果它們遵循匹配語義,則可以將您自己的前綴新增到這些前綴上。例如,Prometheus 具有 scrape_duration_seconds
,表示刮取花費多長時間,良好的做法是也有一個以匯出為中心的指標,例如 jmx_scrape_duration_seconds
,說明特定匯出程式執行其任務花費多長時間。對於您可以存取 PID 的處理程序統計資料,Go 和 Python 都提供收集器來為您處理這項工作。這方面的一個好例子是 HAProxy 匯出程式。
當您有成功的請求計數和失敗的請求計數時,公開此資訊的最佳方法是將其作為一個指標表示總請求,另一個指標表示失敗的請求。這使得計算故障率變得容易。請勿使用一個帶有失敗或成功標籤的指標。類似地,對於快取的命中或未命中,最好有一個指標表示總數,另一個指標表示命中數。
考慮使用監控的人員會為指標名稱進行程式碼或網路搜尋的可能性。如果名稱非常完善,而且不太可能在使用這些名稱的人員領域之外使用,例如 SNMP 和網路工程師,那麼保持原樣可能是一個好主意。此邏輯並不適用於所有匯出程式,例如 MySQL 匯出程式指標可能被各種人員使用,而不仅仅是資料庫管理員。具有原始名稱的 HELP
字串可以提供與使用原始名稱相同的大部分好處。
閱讀一般建議以了解標籤。
避免將 type
作為標籤名稱,它太過通用,而且常常沒有意義。您也應盡可能避免使用可能會與目標標籤衝突的名稱,例如 region
、zone
、cluster
、availability_zone
、az
、datacenter
、dc
、owner
、customer
、stage
、service
、environment
和 env
。然而,如果這是應用程式對某些資源的稱呼,最好不要透過重新命名來造成混淆。
避免因為共用前綴就將項目放入單一指標的誘惑。除非您確定某些項目作為單一指標是有意義的,否則使用多個指標較為安全。
標籤 le
對直方圖具有特殊意義,而 quantile
對摘要具有特殊意義。一般而言,請避免使用這些標籤。
讀寫和傳送/接收最好作為不同的指標,而不是標籤。這通常是因為您一次只會在意其中一個,而且這樣使用比較容易。
經驗法則是一項指標在加總或平均時應具有意義。還有一個情況會出現在匯出器中,也就是資料基本上是表格,而以其他方式處理會要求使用者對指標名稱進行正規表示式,才能夠使用。考慮主機板上的電壓感測器,對它們進行數學運算沒有意義,但將它們放在單一指標中比為每個感測器建立一個指標更合理。指標中的所有值應(幾乎)始終具有相同的單位,例如考慮將風扇速度與電壓混合在一起,而且您沒有辦法自動將它們分開。
不要這樣做
my_metric{label="a"} 1 my_metric{label="b"} 6 my_metric{label="total"} 7
或這樣做
my_metric{label="a"} 1 my_metric{label="b"} 6 my_metric{} 7
前者會讓對指標執行 sum()
的人感到困擾,而後者會讓加總中斷,而且相當難以使用。例如,某些客戶端程式庫(如 Go)會積極嘗試阻止您在自訂收集器中執行後者,而所有客戶端程式庫都應阻止您使用直接儀器執行後者。永遠不要執行這兩個動作,請改用 Prometheus 聚合。
如果您的監控顯示類似這樣的總計,請捨棄總計。如果您必須保留它,例如總計包含未個別計算的項目,請使用不同的指標名稱。
儀器標籤應盡量簡潔,每個額外的標籤都是使用者在撰寫 PromQL 時需要考慮的項目。因此,請避免使用可以移除而不影響時間序列唯一性的儀器標籤。指標周圍的額外資訊可透過資訊指標新增,以下範例說明如何處理版本號碼。
然而,有些情況預期度量標準的幾乎所有使用者都會想要額外的資訊。如果是這樣,新增非唯一的標籤,而不是資訊度量標準,就是正確的解決方案。例如 mysqld_exporter 的 mysqld_perf_schema_events_statements_total
的 digest
標籤是完整查詢模式的雜湊,且足以用於唯一性。但是,沒有人類可讀的 digest_text
標籤幾乎沒有用處,而對於長查詢,它只會包含查詢模式的開頭,因此並不唯一。因此,我們最後會得到人類使用的 digest_text
標籤和用於唯一性的 digest
標籤。
如果您發現自己想要將相同的標籤套用至所有度量標準,請停止。
通常會有兩種情況會出現這種情況。
第一種情況是某些標籤會對度量標準有幫助,例如軟體的版本號碼。請改用 https://www.robustperception.io/how-to-have-labels-for-machine-roles/ 中所述的方法。
第二種情況是標籤實際上是目標標籤。這些是區域、叢集名稱等來自您的基礎架構設定,而非應用程式本身的內容。應用程式無權決定它在您的標籤分類法中適合的位置,那是執行 Prometheus 伺服器的人員要設定的,而監控相同應用程式的不同人員可能會給它不同的名稱。
因此,這些標籤屬於 Prometheus 的擷取設定中,透過您使用的任何服務發現。在此處套用機器角色的概念也可以,因為這可能是至少對某些擷取它的人員有用的資訊。
您應該嘗試將您的度量標準類型與 Prometheus 類型配對。這通常表示計數器和量規。摘要的 _count
和 _sum
也相對常見,而且偶爾您會看到分位數。直方圖很少見,如果您遇到一個,請記住說明格式會顯示累積值。
通常不會很明顯度量標準的類型是什麼,特別是如果您自動處理一組度量標準時。一般來說,UNTYPED
是安全的預設值。
計數器無法下降,因此如果您有來自另一個可遞減的儀器系統的計數器類型,例如 Dropwizard 度量標準,那麼它不是計數器,而是量規。UNTYPED
可能是最佳的類型,因為如果它用作計數器,則 GAUGE
會令人誤解。
當您轉換指標時,使用者可以追蹤回原始指標以及造成轉換的規則,這對使用者來說很有用。將收集器或匯出器的名稱、已套用規則的 ID,以及原始指標的名稱和詳細資料放入說明字串中,將能大幅協助使用者。
Prometheus 不喜歡一個指標有不同的說明字串。如果您要從許多其他指標中建立一個指標,請選擇其中一個放入說明字串中。
例如,SNMP 匯出器使用 OID,而 JMX 匯出器會放入範例 mBean 名稱。HAProxy 匯出器 有手寫字串。節點匯出器 也有各種範例。
除了最小值、最大值和標準差之外,有些儀器系統會顯示 1m、5m、15m 速率,以及自應用程式啟動以來的平均速率(例如,在 Dropwizard 指標中稱為 mean
)。
這些都應該移除,因為它們不太實用,而且會增加雜訊。Prometheus 本身可以計算速率,而且通常更準確,因為顯示的平均值通常會呈指數衰減。您不知道最小值或最大值是在什麼時間計算出來的,而標準差在統計上沒有用,如果您需要計算它,您隨時可以顯示平方和、_sum
和 _count
。
分位數有相關問題,您可以選擇移除它們或將它們放入摘要中。
許多監控系統沒有標籤,而是執行類似 my.class.path.mymetric.labelvalue1.labelvalue2.labelvalue3
的動作。
Graphite 和 StatsD 匯出器共用一種方法,使用小型設定語言轉換這些資料。其他匯出器應該實作相同的方法。目前轉換只在 Go 中實作,而且會受益於將其分解成一個獨立的函式庫。
在為您的匯出器實作收集器時,您永遠不應該使用一般的直接儀器方法,然後在每次擷取時更新指標。
相反地,每次都建立新的指標。在 Go 中,這是透過在您的 Collect()
方法中使用 MustNewConstMetric 來完成的。對於 Python,請參閱 https://github.com/prometheus/client_python#custom-collectors,而對於 Java,請在您的收集方法中產生一個 List<MetricFamilySamples>
,請參閱 StandardExports.java 以取得範例。
造成這個問題的原因有兩個。首先,兩個刮取作業可能會同時發生,而直接儀器化會使用實際上是檔案層級全域變數的內容,因此會造成競爭條件。其次,如果標籤值消失,它仍然會被匯出。
透過直接儀器化對匯出器本身進行儀器化是沒問題的,例如匯出器在所有刮取作業中傳輸的總位元組數或執行的呼叫。對於未連結到單一目標的匯出器,例如 blackbox 匯出器 和 SNMP 匯出器,這些匯出器應該只在一般的 /metrics
呼叫中公開,而不是在特定目標的刮取作業中公開。
有時您會想要匯出與刮取作業相關的指標,例如花費的時間或處理的記錄數。
這些指標應該公開為量規,因為它們與事件(刮取作業)相關,且指標名稱加上匯出器名稱作為前綴,例如 jmx_scrape_duration_seconds
。通常會排除 _exporter
,如果匯出器也適合只當作收集器使用,那麼肯定會排除它。
許多系統(例如 Elasticsearch)會公開機器指標,例如 CPU、記憶體和檔案系統資訊。由於 節點匯出器 在 Prometheus 生態系統中提供這些指標,因此應該捨棄這些指標。
在 Java 世界中,許多儀器化架構會公開處理程序層級和 JVM 層級的統計資料,例如 CPU 和 GC。Java 用戶端和 JMX 匯出器已透過 DefaultExports.java 以優先格式包含這些指標,因此也應該捨棄這些指標。
其他語言和架構也類似。
每個匯出器應監控一個執行個體應用程式,最好與它在同一台機器上並排執行。這表示對於您執行的每一個 HAProxy,您都會執行一個 haproxy_exporter
程序。對於每台具有 Mesos 工作人員的機器,您在上面執行 Mesos 匯出器,如果一台機器同時具有這兩個,則再執行一個主匯出器。
此理論的背後原因是,對於直接儀器化,這是您會執行的動作,而我們嘗試在其他配置中盡可能接近此動作。這表示所有服務偵測都在 Prometheus 中完成,而不在匯出器中。這也有好處,也就是 Prometheus 具有目標資訊,可讓使用者使用 黑盒匯出器 探測您的服務。
有兩個例外
第一個例外是在您監控的應用程式旁邊執行完全沒有意義。SNMP、黑盒和 IPMI 匯出器就是這方面的主要範例。IPMI 和 SNMP 匯出器,因為裝置通常是無法執行程式碼的黑盒(儘管如果您可以在它們上執行節點匯出器,那會更好),而黑盒匯出器是您監控類似 DNS 名稱的項目,而這方面也沒有任何可執行的項目。在這種情況下,Prometheus 仍應執行服務偵測,並傳遞要刮取的目標。請參閱黑盒和 SNMP 匯出器以取得範例。
請注意,目前僅能使用 Go、Python 和 Java 程式庫撰寫此類型的匯出器。
第二個例外是您從系統的隨機執行個體中提取一些統計資料,而且不介意與哪一個通訊。考慮一組 MySQL 複本,您想對資料執行一些商業查詢,然後匯出。使用您通常的負載平衡方法與一個複本通訊的匯出器是最明智的方法。
當您監控具有主機選舉的系統時,這並不適用,在這種情況下,您應該單獨監控每個執行個體,並在 Prometheus 中處理「主機」。這是因為並不總是有完全一個主機,並且在 Prometheus 的腳下改變目標會導致異常。
指標應僅在 Prometheus 擷取時從應用程式擷取,匯出器不應根據自己的計時器執行擷取。也就是說,所有擷取都應該是同步的。
因此,您不應對所顯示的指標設定時間戳記,讓 Prometheus 處理即可。如果您認為需要時間戳記,那麼您可能需要 Pushgateway。
如果擷取指標特別昂貴,例如花費超過一分鐘,則可以快取它。這應在 HELP
字串中註明。
Prometheus 的預設擷取逾時時間為 10 秒。如果預期您的匯出器會超過此時間,您應在使用者文件中明確說明這一點。
某些應用程式和監控系統僅推送指標,例如 StatsD、Graphite 和 collectd。
這裡有兩個考量事項。
首先,您何時讓指標過期?Collectd 和與 Graphite 對話的事物都會定期匯出,當它們停止時,我們希望停止顯示指標。Collectd 包含過期時間,因此我們使用它,Graphite 沒有,因此它是匯出器上的標記。
StatsD 有點不同,因為它處理的是事件,而不是指標。最佳模型是在每個應用程式旁邊執行一個匯出器,並在應用程式重新啟動時重新啟動它們,以便清除狀態。
其次,這些類型的系統往往允許您的使用者傳送增量或原始計數器。您應盡可能依賴原始計數器,因為那是 Prometheus 的一般模型。
對於服務層級指標,例如服務層級批次作業,您應讓您的匯出器推送到 Pushgateway,並在事件後退出,而不是自己處理狀態。對於執行個體層級批次指標,目前尚無明確模式。選項是濫用節點匯出器的文字檔收集器、依賴於記憶體中狀態(如果您不需要在重新開機時保留,這可能是最好的選擇)或實作類似於文字檔收集器的功能。
目前有兩種失敗擷取的模式,其中您正在對話的應用程式沒有回應或有其他問題。
第一個是傳回 5xx 錯誤。
第二個是有 myexporter_up
,例如 haproxy_up
,變數,其值為 0 或 1,視擷取是否成功而定。
後者較好,即使擷取失敗,您仍可取得一些有用的指標,例如 HAProxy 匯出器提供程序統計資料。前者對使用者來說較容易處理,因為 up
以一般方式運作,雖然您無法區分匯出器已關閉和應用程式已關閉。
如果拜訪 http://yourexporter/
有個包含匯出器名稱和連結至 /metrics
頁面的簡單 HTML 頁面,對使用者來說會比較好。
使用者可能在同一台機器上有許多匯出器和 Prometheus 元件,因此為了讓這更容易,每個元件都有唯一的埠號。
https://github.com/prometheus/prometheus/wiki/Default-port-allocations 是我們追蹤它們的地方,這是公開可編輯的。
在開發匯出器時,請隨時取得下一個免費埠號,最好在公開宣告之前。如果您尚未準備好釋出,輸入您的使用者名稱和 WIP 即可。
這是個註冊表,讓我們的使用者生活更輕鬆,而不是承諾開發特定匯出器。對於內部應用程式的匯出器,我們建議使用預設埠號分配範圍之外的埠號。
當您準備向全世界宣告您的匯出器時,請寄電子郵件至郵件清單,並傳送公關將其新增至 可用匯出器清單。
此文件為 開放原始碼。請透過提交問題或拉取要求協助改善文件。