开源监控Prometheus介绍,安装,配置,使用详解
介紹
什么是Prometheus?
Prometheus是一個開源監控系統,前身是SoundCloud的告警插件。從2012年開始,Prometheus逐漸被大量公司使用。該項目的社區也便躍起來,收到越來越的貢獻。在2016年繼Kurberntes之后,Prometheus加入了Cloud Native Computing Foundation。
特征
組件
Prometheus生態包括了很多組件,它們中的一些是可選的:
多數Prometheus組件是Go語言寫的,這使得這些組件很容易編譯和部署。
構架
下面這張圖說明了Prometheus的整體架構,以及生態中的一些組件作用:
Prometheus服務,可以直接通過目標拉取數據,或者間接地通過中間網關拉取數據。它在本地存儲抓取的所有數據,并通過一定規則進行清理和整理數據,并把得到的結果存儲到新的時間序列中,PromQL和其他API可視化地展示收集的數據
適用場景
Prometheus在記錄純數字時間序列方面表現非常好。它既適用于面向服務器等硬件指標的監控,也適用于高動態的面向服務架構的監控。對于現在流行的微服務,Prometheus的多維度數據收集和數據篩選查詢語言也是非常的強大。
Prometheus是為服務的可靠性而設計的,當服務出現故障時,它可以使你快速定位和診斷問題。它的搭建過程對硬件和服務沒有很強的依賴關系。
不適用場景
Prometheus,它的價值在于可靠性,甚至在很惡劣的環境下,你都可以隨時訪問它和查看系統服務各種指標的統計信息。 如果你對統計數據需要100%的精確,它并不適用,例如:它不適用于實時計費系統
安裝
使用預編譯二進制文件
我們為Prometheus大多數的官方組件,提供了預編譯二進制文件。可用版本下載列表
源碼安裝
如果要從源碼安裝Prometheus的官方組件,可以查看各個項目源碼目錄下的Makefile
注意點:在web上的文檔指向最新的穩定版(不包括預發布版)。下一個版本指向master分支還沒有發布的版本
Docker安裝
Docker安裝
所有Prometheus服務的Docker鏡像在官方組織prom下,都是可用的
在Docker上運行Prometheus服務,只需要簡單地執行docker run -p 9090:9090 prom/prometheus命令行即可。這條命令會啟動Prometheus服務,使用的是默認配置文件,并對外界暴露9090端口
Prometheus鏡像使用docker中的volumn卷存儲實際度量指標。在生產環境上使用容器卷模式, 可以在Prometheus更新和升級時輕松管理Prometheus數據, 這種使用docker volumn卷方式存儲數據,是被docker官方強烈推薦的.
通過幾個選項,可以達到使用自己的配置的目的。下面有兩個例子。
卷&綁定掛載
在運行Prometheus服務的主機上,做一個本地到docker容器的配置文件關系映射。
docker run -p 9090:9090 -v /tmp/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus
或者為這個配置文件使用一個獨立的volumn
docker run -p 9090:9090 -v /prometheus-data
prom/prometheus -config.file=/prometheus-data/prometheus.yml
自定義鏡像
為了避免在主機上與docker映射配置文件,我們可以直接將配置文件拷貝到docker鏡像中。如果Prometheus配置是靜態的,并且在所有服務器上的配置相同,這種把配置文件直接拷貝到鏡像中的方式是非常好的。
例如:利用Dockerfile創建一個Prometheus配置目錄, Dockerfile應該這樣寫:
FROM prom/prometheus
ADD prometheus.yml /etc/prometheus/
然后編譯和運行它:
docker build -t my-prometheus .
docker run -p 9090:9090 my-prometheus
一個更高級的選項是可以通過一些工具動態地渲染配置,甚至后臺定期地更新配置
使用配置管理系統
如果你喜歡使用配置管理系統,你可能對下面地第三方庫感興趣:
Ansible:
- griggheo/ansible-prometheus
- William-Yeh/ansible-prometheus
Chef:
- rayrod2030/chef-prometheus
SaltStack:
- bechtoldt/saltstack-prometheus-formula
啟動
入門教程
本篇是一篇hello,world風格的入門指南,使用一個簡單的例子,向大家演示怎么樣安裝、配置和使用Prometheus。你可以下載和本地運行Prometheus服務,通過配置文件收集Prometheus服務自己產生的數據,并在這些收集數據的基礎上,進行查詢、制定規則和圖表化顯示所關心的數據
下載和運行Prometheus
tar xvfz prometheus-*.tar.gz
cd prometheus-*
在運行Prometheus服務之前,我們需要指定一個該服務運行所需要的配置文件
配置Prometheus服務監控本身
Prometheus通過Http方式拉取目標機上的度量指標。Prometheus服務也暴露自己運行所產生的數據,它能夠抓取和監控自己的健康狀況。
實際上,Prometheus服務收集自己運行所產生的時間序列數據,是沒有什么意義的。但是它是一個非常好的入門級教程。保存一下的Prometheus配置到文件中,并自定義命名該文件名,如:prometheus.yml
global:scrape_interval: 15s # By default, scrape targets every 15 seconds.# Attach these labels to any time series or alerts when communicating with# external systems (federation, remote storage, Alertmanager).external_labels:monitor: 'codelab-monitor'# A scrape configuration containing exactly one endpoint to scrape: # Here its Prometheus itself. scrape_configs:# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.- job_name: 'prometheus'# Override the global default and scrape targets from this job every 5 seconds.scrape_interval: 5sstatic_configs:- targets: ['localhost:9090']一個完整的配置選項,可以查看文件文檔
啟動Prometheus服務
cd到Prometheus服務目錄,并指定剛剛自定義好的配置文件,并啟動Prometheus服務, 如下所示:
start Prometheus.
By default, Prometheus stores its database in ./data (flag -storage.local.path).
./prometheus -config.file={$dir}/prometheus.yml # $dir = absolutely/relative path
Prometheus服務啟動成功后,然后再打開瀏覽器在頁面上數據http://localhost:9090. 服務運行幾秒后,會開始收集自身的時間序列數據
你也可以通過在瀏覽器輸入http://localhost:9090/metrics, 直接查看Prometheus服務收集到的自身數據
Prometheus服務執行的操作系統線程數量由GOMAXPROCS環境變量控制。從Go 1.5開始,默認值是可用的CPUs數量
盲目地設置GOMAXPROCS到一個比較高德值,有可能會適得其反。見Go FAQs
注意:Prometheus服務默認需要3GB的內存代銷。如果你的機器內存比較小, 你可以調整Prometheus服務使用更少的內存。詳細見內存使用文檔
使用表達式瀏覽器
我們試著查看一些Prometheus服務自身產生的數據。為了使用Prometheus內置表達式瀏覽器,可以在瀏覽器中數據http://localhost:9090/graph, 選擇"Console"視圖,同一層級還有"Graph"tab。
如果你可以從http://localhost:9090/metrics查看到收集的度量指標數據,那么其中有一個指標數據名稱為prometheus_target_interval_length_seconds(兩次抓取數據之間的時間差)可以被提取出來,可以在表達式控制框中輸入:
prometheus_target_interval_length_seconds
它應該會返回帶有prometheus_target_interval_length_seconds度量指標的許多時間序列數據,只是帶有不能標簽, 這些標簽有不同的延遲百分比和目標群組之間的間隔。
如果我們僅僅對p99延遲感興趣,我們使用下面的查詢表達式收集該信息
prometheus_target_interval_length_seconds{quantile=“0.99”}
為了統計時間序列數據記錄的總數量,你可以寫:
count(prometheus_target_interval_length_seconds)
更多的表達式語言,詳見表達式語言文檔
使用圖形界面
使用http://localhost:9090/graph鏈接,查看圖表"Graph"。
例如:輸入下面的表達式,繪制在Prometheus服務中每秒存儲的速率.
rate(prometheus_local_storage_chunk_ops_total[1m])
啟動一些樣本目標機
我們更感興趣的是Prometheus服務抓取其他目標機的數據采樣,并非自己的時間序列數據。Go客戶庫有一個例子,它會產生一些自己造的RPC延遲。啟動三個帶有不同的延時版本。
首先需要確保你有Go的環境
下載Go的Prometheus客戶端,并運行下面三個服務:
# Fetch the client library code and compile example. git clone https://github.com/prometheus/client_golang.git cd client_golang/examples/random go get -d go build# Start 3 example targets in separate terminals: ./random -listen-address=:8080 ./random -listen-address=:8081 ./random -listen-address=:8082你現在應該瀏覽器輸入http://localhost:8080/metrics, http://localhost:8081/metrics, and http://localhost:8082/metrics, 會看到這些服務所產生的度量指標數據.
配置Prometheus服務,監聽樣本目標實例
現在我們將配置Prometheus服務,收集這三個例子的度量指標數據。我們把這三個服務實例命名為一個任務稱為example-random, 并把8080端口服務和8081端口服務作為生產目標group,8082端口成為canary group。 為了在Prometheus服務中建模這個,我們需要添加兩個群組到這個任務中,增加一些標簽到不同的目標群組中。在這個例子中,我們會增加group="production"標簽到帶個目標組中,另外一個則是group=“canary”
為了達到這個目的,在prometheus.yml配置文件中,增加下面任務定義到scrape_config區域中, 并重啟Prometheus服務:
scrape_configs:- job_name: 'example-random'# Override the global default and scrape targets from this job every 5 seconds.scrape_interval: 5sstatic_configs:- targets: ['localhost:8080', 'localhost:8081']labels:group: 'production'- targets: ['localhost:8082']labels:group: 'canary'去表達式瀏覽器中驗證Prometheus服務是否能統計到這兩個群組的目標機度量數據,如:rpc_durations_seconds度量指標
為聚集到抓取的數據,設置規則并寫入到新的時間序列中
當計算ad-hoc時,如果在累計到上千個時間序列數據的查詢,可能會變慢。為了使這種多時間序列數據點查詢更有效率,我們允許通過使用配置的記錄規則,把預先記錄表達式實時收集的數據存入到新的持久時間序列中。該例子中,如果我們對每秒RPCs數量(rpc_durations_seconds_count)的5分鐘窗口流入的統計數量感興趣的話。我們可以下面的表達式:
avg(rate(rpc_durations_seconds_count)[5m]) by (job, service)
試著使用圖形化這個表達式
為了存儲這個表達式所統計到的數據,我們可以使用新的度量指標,如job_service:rpc_durations_seconds_count:avg_rate5m, 創建一個配置規則文件,并把該文件保存為prometheus.rules:
job_service:rpc_durations_seconds_count:avg_rate5m = avg(rate(rpc_durations_seconds_count[5m])) by (job, service)
為了使Prometheus服務使用這個新的規則,在prometheus.yml配置文件的global配置區域添加一個rule_files語句。這個配置應該向下面這樣寫:
global:scrape_interval: 15s # By default, scrape targets every 15 seconds.evaluation_interval: 15s # Evaluate rules every 15 seconds.# Attach these extra labels to all timeseries collected by this Prometheus instance.external_labels:monitor: 'codelab-monitor'rule_files:- 'prometheus.rules'scrape_configs:- job_name: 'prometheus'# Override the global default and scrape targets from this job every 5 seconds.scrape_interval: 5sstatic_configs:- targets: ['localhost:9090']- job_name: 'example-random'# Override the global default and scrape targets from this job every 5 seconds.scrape_interval: 5sstatic_configs:- targets: ['localhost:8080', 'localhost:8081']labels:group: 'production'- targets: ['localhost:8082']labels:group: 'canary'指定這個新的配置文件,并重啟Prometheus服務。驗證新的時間序列度量指標job_service:rpc_durations_seconds_count:avg_rate5m是否能夠在Console控制框中查找出時間序列數據
常見問題
一般問題
Prometheus是一款高活躍生態系統的開源系統監控和警告工具包。詳見概覽
詳見比較
Prometheus服務獨立運行,沒有其他依賴
是的,在多臺服務器上運行相同的Prometheus服務,相同的報警會由警告管理器刪除
警告管理器當前不能保證高可用,但高可用是目標
事實上,有許多方式可以擴展Prometheus。 閱讀Robust Percetion的博客關于Prometheus的擴展
在通常的設置中,不可能使用inode。 有一個可能的缺點:如果你想刪除Prometheus的存儲目錄,你會注意到,一些文件系統在刪除文件時非常慢。
雖然TLS和身份驗證是經常請求的功能,但我們有意不在Prometheus的任何服務器端組件中實現它們。 有這么多不同的選項和參數(僅限TLS的10多個選項),我們決定專注于建立最佳的監控系統,而不是在每個服務器組件中支持完全通用的TLS和身份驗證解決方案。
如果您需要TLS或身份驗證,我們建議將反向代理放在Prometheus前面。 參見例如使用Nginx添加對Prometheus的基本認證。
請注意,這僅適用于入站連接。 Prometheus確實支持刪除TLS-和auth啟用的目標,以及其他創建出站連接的Prometheus組件具有類似的支持。
概念
數據模型
Prometheus從根本上存儲的所有數據都是時間序列: 具有時間戳的數據流只屬于單個度量指標和該度量指標下的多個標簽維度。除了存儲時間序列數據外,Prometheus也可以利用查詢表達式存儲5分鐘的返回結果中的時間序列數據
metrics和labels(度量指標名稱和標簽)
每一個時間序列數據由metric度量指標名稱和它的標簽labels鍵值對集合唯一確定。
這個metric度量指標名稱指定監控目標系統的測量特征(如:http_requests_total- 接收http請求的總計數). metric度量指標命名ASCII字母、數字、下劃線和冒號,他必須配正則表達式[a-zA-Z_:][a-zA-Z0-9_:]*。
標簽開啟了Prometheus的多維數據模型:對于相同的度量名稱,通過不同標簽列表的結合, 會形成特定的度量維度實例。(例如:所有包含度量名稱為/api/tracks的http請求,打上method=POST的標簽,則形成了具體的http請求)。這個查詢語言在這些度量和標簽列表的基礎上進行過濾和聚合。改變任何度量上的任何標簽值,則會形成新的時間序列圖
標簽label名稱可以包含ASCII字母、數字和下劃線。它們必須匹配正則表達式[a-zA-Z_][a-zA-Z0-9_]*。帶有_下劃線的標簽名稱被保留內部使用。
標簽labels值包含任意的Unicode碼。
具體詳見metrics和labels命名最佳實踐。
有序的采樣值
有序的采樣值形成了實際的時間序列數據列表。每個采樣值包括:
- 一個64位的浮點值
- 一個精確到毫秒級的時間戳
- 一個樣本數據集是針對一個指定的時間序列在一定時間范圍的數據收集。這個時間序列是由<metric_name>{<label_name>=<label_value>, …}
‘‘小結:指定度量名稱和度量指標下的相關標簽值,則確定了所關心的目標數據,隨著時間推移形成一個個點,在圖表上實時繪制動態變化的線條’’
Notation(符號)
表示一個度量指標和一組鍵值對標簽,需要使用以下符號:
[metric name]{[label name]=[label value], …}
例如,度量指標名稱是api_http_requests_total, 標簽為method=“POST”, handler="/messages" 的示例如下所示:
api_http_requests_total{method=“POST”, handler="/messages"}
這些命名和OpenTSDB使用方法是一樣的
度量指標模型
metrics類型
Prometheus客戶庫提供了四個核心的metrics類型。這四種類型目前僅在客戶庫和wire協議中區分。Prometheus服務還沒有充分利用這些類型。不久的將來就會發生改變。
Counter(計數器)
counter 是一個累計度量指標,它是一個只能遞增的數值。計數器主要用于統計服務的請求數、任務完成數和錯誤出現的次數等等。計數器是一個遞增的值。反例:統計goroutines的數量。計數器的使用方式在下面的各個客戶端例子中:
客戶端使用計數器的文檔
- Go
- Java
- Python
- Ruby
Gauge(測量器)
gauge是一個度量指標,它表示一個既可以遞增, 又可以遞減的值。
測量器主要測量類似于溫度、當前內存使用量等,也可以統計當前服務運行隨時增加或者減少的Goroutines數量
客戶端使用計量器的文檔:
- Go
- Java
- Python
- Ruby
Histogram(柱狀圖)
histogram,是柱狀圖,在Prometheus系統中的查詢語言中,有三種作用:
度量指標名稱: [basename]的柱狀圖, 上面三類的作用度量指標名稱
- [basename]_bucket{le=“上邊界”}, 這個值為小于等于上邊界的所有采樣點數量
- [basename]_sum
- [basename]_count
小結:所以如果定義一個度量類型為Histogram,則Prometheus系統會自動生成三個對應的指標
使用histogram_quantile()函數, 計算直方圖或者是直方圖聚合計算的分位數閾值。 一個直方圖計算Apdex值也是合適的, 當在buckets上操作時,記住直方圖是累計的。詳見直方圖和總結
客戶庫的直方圖使用文檔:
- Go
- Java
- Python
- Ruby
[Summary]總結
類似histogram柱狀圖,summary是采樣點分位圖統計,(通常的使用場景:請求持續時間和響應大小)。 它也有三種作用:
對于每個采樣點進行統計,并形成分位圖。(如:正態分布一樣,統計低于60分不及格的同學比例,統計低于80分的同學比例,統計低于95分的同學比例)
- 統計班上所有同學的總成績(sum)
- 統計班上同學的考試總人數(count)
- 帶有度量指標的[basename]的summary 在抓取時間序列數據展示。
觀察時間的φ-quantiles (0 ≤ φ ≤ 1), 顯示為[basename]{分位數="[φ]"}
- [basename]_sum, 是指所有觀察值的總和
- [basename]_count, 是指已觀察到的事件計數值
詳見histogram和summaries
有關summaries的客戶端使用文檔:
- Go
- Java
- Python
- Ruby
任務與實例
Jobs和Instances(任務和實例)
就Prometheus而言,pull拉取采樣點的端點服務稱之為instance。多個這樣pull拉取采樣點的instance, 則構成了一個job
例如, 一個被稱作api-server的任務有四個相同的實例。
- job: api-server
- instance 1:1.2.3.4:5670
- instance 2:1.2.3.4:5671
- instance 3:5.6.7.8:5670
- instance 4:5.6.7.8:5671
自動化生成的標簽和時間序列
當Prometheus拉取一個目標, 會自動地把兩個標簽添加到度量名稱的標簽列表中,分別是:
- job: 目標所屬的配置任務名稱api-server。
- instance: 采樣點所在服務: host:port
如果以上兩個標簽二者之一存在于采樣點中,這個取決于honor_labels配置選項。詳見文檔
對于每個采樣點所在服務instance,Prometheus都會存儲以下的度量指標采樣點:
- up{job="[job-name]", instance=“instance-id”}: up值=1,表示采樣點所在服務健康; 否則,網絡不通, 或者服務掛掉了
- scrape_duration_seconds{job="[job-name]", instance="[instance-id]"}: 嘗試獲取目前采樣點的時間開銷
- scrape_samples_post_metric_relabeling{job="", instance=""}: 表示度量指標的標簽變化后,標簽沒有變化的度量指標數量。
- scrape_samples_scraped{job="", instance=""}: 這個采樣點目標暴露的樣本點數量
備注:我查了下scrape_samples_post_metric_relabeling 和 scrape_samples_scraped的值好像是一樣的。還是這兩個值沒有理解
up度量指標對服務健康的監控是非常有用的。
查詢
Prometheus提供一個函數式的表達式語言,可以使用戶實時地查找和聚合時間序列數據。表達式計算結果可以在圖表中展示,也可以在Prometheus表達式瀏覽器中以表格形式展示,或者作為數據源, 以HTTP API的方式提供給外部系統使用。
examples
這個文檔僅供參考, 這里先舉幾個容易上手的例子。
表達式語言數據類型
在Prometheus的表達式語言中,任何表達式或者子表達式都可以歸為四種類型:
- instant vector 瞬時向量 - 它是指在同一時刻,抓取的所有度量指標數據。這些度量指標數據的key都是相同的,也即相同的時間戳。
- range vector 范圍向量 - 它是指在任何一個時間范圍內,抓取的所有度量指標數據。
- scalar 標量 - 一個簡單的浮點值
- string 字符串 - 一個當前沒有被使用的簡單字符串
依賴于使用場景(例如:圖表 vs. 表格),根據用戶所寫的表達式,僅僅只有一部分類型才適用這種表達式。例如:瞬時向量類型是唯一可以直接在圖表中使用的。
Literals
字符串
字符串可以用單引號、雙引號或者反引號表示
PromQL遵循與Go相同的轉義規則。在單引號,雙引號中,反斜杠成為了轉義字符,后面可以跟著a, b, f, n, r, t, v或者\。 可以使用八進制(\nnn)或者十六進制(\xnn, \unnnn和\Unnnnnnnn)提供特定字符。
在反引號內不處理轉義字符。與Go不同,Prom不會丟棄反引號中的換行符。例如:
“this is a string”
‘these are unescaped: \n \ \t’
these are not unescaped: \n ’ " \t"’
浮點數
標量浮點值可以直接寫成形式-[.(digits)]。
-2.43
時間序列選擇器
即時向量選擇器
瞬時向量選擇器可以對一組時間序列數據進行篩選,并給出結果中的每個結果鍵值對(時間戳-樣本值): 最簡單的形式是,只有一個度量名稱被指定。在一個瞬時向量中這個結果包含有這個度量指標名稱的所有樣本數據鍵值對。
下面這個例子選擇所有時間序列度量名稱為http_requests_total的樣本數據:
http_requests_total
通過在度量指標后面增加{}一組標簽可以進一步地過濾這些時間序列數據。
下面這個例子選擇了度量指標名稱為http_requests_total,且一組標簽為 job=prometheus, group=canary:
http_requests_total{job=“prometheus”,group=“canary”}
可以采用不匹配的標簽值也是可以的,或者用正則表達式不匹配標簽。標簽匹配操作如下所示:
- =: 精確地匹配標簽給定的值
- !=: 不等于給定的標簽值
- =~: 正則表達匹配給定的標簽值
- !=: 給定的標簽值不符合正則表達式
例如:度量指標名稱為http_requests_total,正則表達式匹配標簽environment為staging, testing, development的值,且http請求方法不等于GET。
http_requests_total{environment=~“staging|testing|development”, method!=“GET”}
匹配空標簽值的標簽匹配器也可以選擇沒有設置任何標簽的所有時間序列數據。正則表達式完全匹配。
向量選擇器必須指定一個度量指標名稱或者至少不能為空字符串的標簽值。以下表達式是非法的:
{job=~".*"} #Bad!
上面這個例子既沒有度量指標名稱,標簽選擇器也可以正則匹配空標簽值,所以不符合向量選擇器的條件
相反地,下面這些表達式是有效的,第一個一定有一個字符。第二個有一個有用的標簽method
{job=~".+"} # Good!
{job=~".*", method=“get”} # Good!
標簽匹配器能夠被應用到度量指標名稱,使用__name__標簽篩選度量指標名稱。例如:表達式http_requests_total等價于{name=“http_requests_total”}。 其他的匹配器,如:= ( !=, =~, !~)都可以使用。下面的表達式選擇了度量指標名稱以job:開頭的時間序列數據:
{name=~"^job:.*"} #
范圍向量選擇器
范圍向量類似瞬時向量, 不同在于,它們從當前實例選擇樣本范圍區間。在語法上,時間長度被追加在向量選擇器尾部的方括號[]中,用以指定對于每個樣本范圍區間中的每個元素應該抓取的時間范圍樣本區間。
時間長度有一個數值決定,后面可以跟下面的單位:
- s - seconds
- m - minutes
- h - hours
- d - days
- w - weeks
- y - years
在下面這個例子中, 選擇過去5分鐘內,度量指標名稱為http_requests_total, 標簽為job="prometheus"的時間序列數據:
http_requests_total{job=“prometheus”}[5m]
偏移修飾符
這個offset偏移修飾符允許在查詢中改變單個瞬時向量和范圍向量中的時間偏移
例如,下面的表達式返回相對于當前時間的前5分鐘時的時刻, 度量指標名稱為http_requests_total的時間序列數據:
http_requests_total offset 5m
注意:offset偏移修飾符必須直接跟在選擇器后面,例如:
sum(http_requests_total{method=“GET”} offset 5m) // GOOD.
然而,下面這種情況是不正確的
sum(http_requests_total{method=“GET”}) offset 5m // INVALID.
offset偏移修飾符在范圍向量上和瞬時向量用法一樣的。下面這個返回了相對于當前時間的前一周時,過去5分鐘的度量指標名稱為http_requests_total的速率:
rate(http_requests_total[5m] offset 1w)
操作符
Prometheus支持二元和聚合操作符。詳見表達式語言操作符
函數
Prometheus提供了一些函數列表操作時間序列數據。詳見表達式語言函數
陷阱
插值和陳舊
當運行查詢后,獨立于當前時刻被選中的時間序列數據所對應的時間戳,這個時間戳主要用來進行聚合操作,包括sum, avg等,大多數聚合的時間序列數據所對應的時間戳沒有對齊。由于它們的獨立性,我們需要在這些時間戳中選擇一個時間戳,并已這個時間戳為基準,獲取小于且最接近這個時間戳的時間序列數據。
如果5分鐘內,沒有獲取到任何的時間序列數據,則這個時間戳不會存在。那么在圖表中看到的數據都是在當前時刻5分鐘前的數據。
注意:差值和陳舊處理可能會發生變化。詳見https://github.com/prometheus/prometheus/issues/398和https://github.com/prometheus/prometheus/issues/581
避免慢查詢和高負載
如果一個查詢需要操作非常大的數據量,圖表繪制很可能會超時,或者服務器負載過高。因此,在對未知數據構建查詢時,始終需要在Prometheus表達式瀏覽器的表格視圖中構建查詢,直到結果是看起來合理的(最多為數百個,而不是數千個)。只有當你已經充分過濾或者聚合數據時,才切換到圖表模式。如果表達式的查詢結果仍然需要很長時間才能繪制出來,則需要通過記錄規則重新清洗數據。
像api_http_requests_total這樣簡單的度量指標名稱選擇器,可以擴展到具有不同標簽的數千個時間序列中,這對于Prometheus的查詢語言是非常重要的。還要記住,聚合操作即使輸出的結果集非常少,但是它會在服務器上產生負載。這類似于關系型數據庫查詢可一個字段的總和,總是非常緩慢。
操作符
二元操作符
Prometheus的查詢語言支持基本的邏輯運算和算術運算。對于兩個瞬時向量, 匹配行為可以被改變。
算術二元運算符
在Prometheus系統中支持下面的二元算術操作符:
- +加法
- -減法
- *乘法
- /除法
- % 模
- ^ 冪等
二元運算操作符支持scalar/scalar(標量/標量)、vector/scalar(向量/標量)、和vector/vector(向量/向量)之間的操作。
在兩個標量之間進行操作符運算,得到的結果也是標量
在向量和標量之間,這個操作符會作用于這個向量的每個樣本值上。例如:如果一個時間序列瞬時向量除以2,操作結果也是一個新的瞬時向量,且度量指標名稱不變, 它是原度量指標瞬時向量的每個樣本值除以2.
在兩個向量之間,一個二元算術操作符作用在左邊瞬時向量的每個樣本值,且該樣本值與操作符右邊能匹配上的樣本值計算,向量匹配。結果寫入到一個沒有度量指標名稱的瞬時向量。
比較二元操作符
在Prometheus系統中,比較二元操作符有:
- == 等于
- != 不等于
- > 大于
- < 小于
- >= 大于等于
- <= 小于等于
比較二元操作符被應用于scalar/scalar(標量/標量)、vector/scalar(向量/標量),和vector/vector(向量/向量)。比較操作符得到的結果是bool布爾類型值,返回1或者0值。
在兩個標量之間的比較運算,bool結果寫入到另一個結果標量中。
瞬時向量和標量之間的比較運算,這個操作符會應用到某個當前時刻的每個時間序列數據上,如果一個時間序列數據值與這個標量比較結果是false,則這個時間序列數據被丟棄掉,如果是true, 則這個時間序列數據被保留在結果中。
在兩個瞬時向量之間的比較運算,左邊度量指標數據中的每個時間序列數據,與右邊度量指標中的每個時間序列數據匹配,沒有匹配上的,或者計算結果為false的,都被丟棄,不在結果中顯示。否則將保留左邊的度量指標和標簽的樣本數據寫入瞬時向量。
邏輯/集合二元操作符
邏輯/集合二元操作符只能作用在即時向量, 包括:
- and 交集
- or 并集
- unless 補集
vector1 and vector2 的邏輯/集合二元操作符,規則:vector1瞬時向量中的每個樣本數據與vector2向量中的所有樣本數據進行標簽匹配,不匹配的,全部丟棄。運算結果是保留左邊的度量指標名稱和值。
vector1 or vector2的邏輯/集合二元操作符,規則: 保留vector1向量中的每一個元素,對于vector2向量元素,則不匹配vector1向量的任何元素,則追加到結果元素中。
vector1 unless vector2的邏輯/集合二元操作符,又稱差積。規則:包含在vector1中的元素,但是該元素不在vector2向量所有元素列表中,則寫入到結果集中
向量匹配
向量之間的匹配是指右邊向量中的每一個元素,在左邊向量中也存在。這里有兩種基本匹配行為特征:
一對一,找到這個操作符的兩邊向量元素的相同元素。默認情況下,操作符的格式是vector1 [operate] vector2。如果它們有相同的標簽和值,則表示相匹配。ingoring關鍵字是指,向量匹配時,可以忽略指定標簽。on關鍵字是指,在指定標簽上進行匹配。格式如下所示
[vector expr] [bin-op] ignoring([label list]) [vector expr]
[vector expr] [bin-op] on([lable list]) [vector expr]
例如樣本數據:
method_code:http_errors:rate5m{method=“get”, code=“500”} 24
method_code:http_errors:rate5m{method=“get”, code=“404”} 30
method_code:http_errors:rate5m{method=“put”, code=“501”} 3
method_code:http_errors:rate5m{method=“post”, code=“404”} 21
method:http_requests:rate5m{method=“get”} 600
method:http_requests:rate5m{method=“delete”} 34
method:http_requests:rate5m{method=“post”} 120
查詢例子:
method_code:http_errors:rate5m{code=“500”} / ignoring(code) method:http_requests:rate5m
兩個向量之間的除法操作運算的向量結果是,每一個向量樣本http請求方法標簽值是500,且在過去5分鐘的運算值。如果沒有忽略code="500"的標簽,這里不能匹配到向量樣本數據。兩個向量的請求方法是put和delete的樣本數據不會出現在結果列表中
{method=“get”} 0.04 // 24 / 600
{method=“post”} 0.05 // 6 / 120
多對一和一對多的匹配,是指向量元素中的一個樣本數據匹配標簽到了多個樣本數據標簽。這里必須直接指定兩個修飾符group_left或者group_right, 左或者右決定了哪邊的向量具有較高的子集
ignoring() group_left()
ignoring() group_right()
on() group_left()
on() group_right()
這個group帶標簽的修飾符標簽列表包含了“一對多”中的“一”一側的額外標簽。對于on標簽只能是這些列表中的一個。結果向量中的每一個時間序列數據都是唯一的。
group修飾符只能被用在比較操作符和算術運算符。
查詢例子:
method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m
在這個例子中,左向量的標簽數量多于左邊向量的標簽數量,所以我們使用group_left。右邊向量的時間序列元素匹配左邊的所有相同method標簽:
{method=“get”, code=“500”} 0.04 // 24 /600
{method=“get”, code=“404”} 0.05 // 30 /600
{method=“post”, code=“500”} 0.05 // 6 /600
{method=“post”, code=“404”} 0.175 // 21 /600
多對一和一對多匹配應該更多地被謹慎使用。經常使用ignoring(<labels>)輸出想要的結果。
聚合操作符
Prometheus支持下面的內置聚合操作符。這些聚合操作符被用于聚合單個即時向量的所有時間序列列表,把聚合的結果值存入到新的向量中。
- sum (在維度上求和)
- max (在維度上求最大值)
- min (在維度上求最小值)
- avg (在維度上求平均值)
- stddev (求標準差)
- stdvar (求方差)
- count (統計向量元素的個數)
- count_values (統計相同數據值的元素數量)
- bottomk (樣本值第k個最小值)
- topk (樣本值第k個最大值)
- quantile (統計分位數)
這些操作符被用于聚合所有標簽維度,或者通過without或者by子句來保留不同的維度。
([parameter,] ) [without | by ()] [keep_common]
parameter只能用于count_values, quantile, topk和bottomk。without移除結果向量中的標簽集合,其他標簽被保留輸出。by關鍵字的作用正好相反,即使它們的標簽值在向量的所有元素之間。keep_common子句允許保留額外的標簽(在元素之間相同,但不在by子句中的標簽)
count_values對每個唯一的樣本值輸出一個時間序列。每個時間序列都附加一個標簽。這個標簽的名字有聚合參數指定,同時這個標簽值是唯一的樣本值。每一個時間序列值是結果樣本值出現的次數。
topk和bottomk與其他輸入樣本子集聚合不同,返回的結果中包括原始標簽。by和without僅僅用在輸入向量的桶中
例如:
如果度量指標名稱http_requests_total包含由group, application, instance的標簽組成的時間序列數據,我們可以通過以下方式計算去除instance標簽的http請求總數
sum(http_requests_total) without (instance)
如果我們對所有應用程序的http請求總數,我們可以簡單地寫下:
sum(http_requests_total)
統計每個編譯版本的二進制文件數量,我們可以如下寫:
count_values(“version”, build_version)
通過所有實例,獲取http請求第5個最大值,我們可以簡單地寫下:
topk(5, http_requests_total)
二元運算符優先級
在Prometheus系統中,二元運算符優先級從高到低:
- ^
- *, /, %
- +, -
- ==, !=, <=, <, >=, >
- and, unless
- or
函數
函數列表
一些函數有默認的參數,例如:year(v=vector(time()) instant-vector)。v是參數值,instant-vector是參數類型。vector(time())是默認值。
abs()
abs(v instant-vector)返回輸入向量的所有樣本的絕對值。
absent()
absent(v instant-vector),如果賦值給它的向量具有樣本數據,則返回空向量;如果傳遞的瞬時向量參數沒有樣本數據,則返回不帶度量指標名稱且帶有標簽的樣本值為1的結果
當監控度量指標時,如果獲取到的樣本數據是空的, 使用absent方法對告警是非常有用的
absent(nonexistent{job=“myjob”}) # => key: value = {job=“myjob”}: 1
absent(nonexistent{job=“myjob”, instance=~".*"}) # => {job=“myjob”} 1
so smart !
absent(sum(nonexistent{job=“myjob”})) # => key:value {}: 0
ceil()
ceil(v instant-vector) 是一個向上舍入為最接近的整數。
changes()
changes(v range-vector) 輸入一個范圍向量, 返回這個范圍向量內每個樣本數據值變化的次數。
clamp_max()
clamp_max(v instant-vector, max scalar)函數,輸入一個瞬時向量和最大值,樣本數據值若大于max,則改為max,否則不變
clamp_min()
clamp_min(v instant-vector)函數,輸入一個瞬時向量和最大值,樣本數據值小于min,則改為min。否則不變
count_saclar()
count_scalar(v instant-vector) 函數, 輸入一個瞬時向量,返回key:value=“scalar”: 樣本個數。而count()函數,輸入一個瞬時向量,返回key:value=向量:樣本個數,其中結果中的向量允許通過by條件分組。
day_of_month()
day_of_month(v=vector(time()) instant-vector)函數,返回被給定UTC時間所在月的第幾天。返回值范圍:1~31。
day_of_week()
day_of_week(v=vector(time()) instant-vector)函數,返回被給定UTC時間所在周的第幾天。返回值范圍:0~6. 0表示星期天。
days_in_month()
days_in_month(v=vector(time()) instant-vector)函數,返回當月一共有多少天。返回值范圍:28~31.
delta()
delta(v range-vector)函數,計算一個范圍向量v的第一個元素和最后一個元素之間的差值。返回值:key:value=度量指標:差值
下面這個表達式例子,返回過去兩小時的CPU溫度差:
delta(cpu_temp_celsius{host=“zeus”}[2h])
delta函數返回值類型只能是gauges。
deriv()
deriv(v range-vector)函數,計算一個范圍向量v中各個時間序列二階導數,使用簡單線性回歸
deriv二階導數返回值類型只能是gauges。
drop_common_labels()
drop_common_labels(instant-vector)函數,輸入一個瞬時向量,返回值是key:value=度量指標:樣本值,其中度量指標是去掉了具有相同標簽。
例如:http_requests_total{code=“200”, host=“127.0.0.1:9090”, method=“get”} : 4, http_requests_total{code=“200”, host=“127.0.0.1:9090”, method=“post”} : 5, 返回值: http_requests_total{method=“get”} : 4, http_requests_total{code=“200”, method=“post”} : 5
exp()
exp(v instant-vector)函數,輸入一個瞬時向量, 返回各個樣本值的e指數值,即為e^N次方。特殊情況如下所示:
Exp(+inf) = +Inf
Exp(NaN) = NaN
floor()
floor(v instant-vector)函數,與ceil()函數相反。 4.3 為 4 。
histogram_quantile()
histogram_quatile(φ float, b instant-vector) 函數計算b向量的φ-直方圖 (0 ≤ φ ≤ 1) 。參考中文文獻[https://www.howtoing.com/how-to-query-prometheus-on-ubuntu-14-04-part-2/]
holt_winters()
holt_winters(v range-vector, sf scalar, tf scalar)函數基于范圍向量v,生成事件序列數據平滑值。平滑因子sf越低, 對老數據越重要。趨勢因子tf越高,越多的數據趨勢應該被重視。0< sf, tf <=1。 holt_winters僅用于gauges
hour()
hour(v=vector(time()) instant-vector)函數返回被給定UTC時間的當前第幾個小時,時間范圍:0~23。
idelta()
idelta(v range-vector)函數,輸入一個范圍向量,返回key: value = 度量指標: 每最后兩個樣本值差值。
increase()
increase(v range-vector)函數, 輸入一個范圍向量,返回:key:value = 度量指標:last值-first值,自動調整單調性,如:服務實例重啟,則計數器重置。與delta()不同之處在于delta是求差值,而increase返回最后一個減第一個值,可為正為負。
下面的表達式例子,返回過去5分鐘,連續兩個時間序列數據樣本值的http請求增加值。
increase(http_requests_total{job=“api-server”}[5m])
increase的返回值類型只能是counters,主要作用是增加圖表和數據的可讀性,使用rate記錄規則的使用率,以便持續跟蹤數據樣本值的變化。
irate
irate(v range-vector)函數, 輸入:范圍向量,輸出:key: value = 度量指標: (last值-last前一個值)/時間戳差值。它是基于最后兩個數據點,自動調整單調性, 如:服務實例重啟,則計數器重置。
下面表達式針對范圍向量中的每個時間序列數據,返回兩個最新數據點過去5分鐘的HTTP請求速率。
irate(http_requests_total{job=“api-server”}[5m])
irate只能用于繪制快速移動的計數器。因為速率的簡單更改可以重置FOR子句,利用警報和緩慢移動的計數器,完全由罕見的尖峰組成的圖形很難閱讀。
label_replace()
對于v中的每個時間序列,label_replace(v instant-vector, dst_label string, replacement string, src_label string, regex string) 將正則表達式與標簽值src_label匹配。如果匹配,則返回時間序列,標簽值dst_label被替換的擴展替換。$1替換為第一個匹配子組,$2替換為第二個等。如果正則表達式不匹配,則時間序列不會更改。
另一種更容易的理解是:label_replace函數,輸入:瞬時向量,輸出:key: value = 度量指標: 值(要替換的內容:首先,針對src_label標簽,對該標簽值進行regex正則表達式匹配。如果不能匹配的度量指標,則不發生任何改變;否則,如果匹配,則把dst_label標簽的標簽紙替換為replacement
下面這個例子返回一個向量值a帶有foo標簽:
label_replace(up{job=“api-server”, serice=“a:c”}, “foo”, “$1”, “service”, “(.):.”)
ln()
ln(v instance-vector)計算瞬時向量v中所有樣本數據的自然對數。特殊例子:
ln(+Inf) = +Inf
ln(0) = -Inf
ln(x<0) = NaN
ln(NaN) = NaN
log2()
log2(v instant-vector)函數計算瞬時向量v中所有樣本數據的二進制對數。
log10()
log10(v instant-vector)函數計算瞬時向量v中所有樣本數據的10進制對數。相當于ln()
minute()
minute(v=vector(time()) instant-vector)函數返回給定UTC時間當前小時的第多少分鐘。結果范圍:0~59。
month()
month(v=vector(time()) instant-vector)函數返回給定UTC時間當前屬于第幾個月,結果范圍:0~12。
predict_linear()
predict_linear(v range-vector, t scalar)預測函數,輸入:范圍向量和從現在起t秒后,輸出:不帶有度量指標,只有標簽列表的結果值。
例如:predict_linear(http_requests_total{code=“200”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”}[5m], 5)
結果:
{code=“200”,handler=“query_range”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 1
{code=“200”,handler=“prometheus”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 4283.449995397104
{code=“200”,handler=“static”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 22.99999999999999
{code=“200”,handler=“query”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 130.90381188596754
{code=“200”,handler=“graph”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 2
{code=“200”,handler=“label_values”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 2
rate()
rate(v range-vector)函數, 輸入:范圍向量,輸出:key: value = 不帶有度量指標,且只有標簽列表:(last值-first值)/時間差s
rate(http_requests_total[5m])
結果:
{code=“200”,handler=“label_values”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 0
{code=“200”,handler=“query_range”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 0
{code=“200”,handler=“prometheus”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 0.2
{code=“200”,handler=“query”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 0.003389830508474576
{code=“422”,handler=“query”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 0
{code=“200”,handler=“static”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 0
{code=“200”,handler=“graph”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 0
{code=“400”,handler=“query”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 0
rate()函數返回值類型只能用counters, 當用圖表顯示增長緩慢的樣本數據時,這個函數是非常合適的。
注意:當rate函數和聚合方式聯合使用時,一般先使用rate函數,再使用聚合操作, 否則,當服務實例重啟后,rate無法檢測到counter重置。
resets()
resets()函數, 輸入:一個范圍向量,輸出:key-value=沒有度量指標,且有標簽列表[在這個范圍向量中每個度量指標被重置的次數]。在兩個連續樣本數據值下降,也可以理解為counter被重置。
示例:
resets(http_requests_total[5m])
結果:
{code=“200”,handler=“label_values”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 0
{code=“200”,handler=“query_range”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 0
{code=“200”,handler=“prometheus”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 0
{code=“200”,handler=“query”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 0
{code=“422”,handler=“query”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 0
{code=“200”,handler=“static”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 0
{code=“200”,handler=“graph”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 0
{code=“400”,handler=“query”,instance=“120.77.65.193:9090”,job=“prometheus”,method=“get”} 0
resets只能和counters一起使用。
round()
round(v instant-vector, to_nearest 1= scalar)函數,與ceil和floor函數類似,輸入:瞬時向量,輸出:指定整數級的四舍五入值, 如果不指定,則是1以內的四舍五入。
scalar()
scalar(v instant-vector)函數, 輸入:瞬時向量,輸出:key: value = “scalar”, 樣本值[如果度量指標樣本數量大于1或者等于0, 則樣本值為NaN, 否則,樣本值本身]
sort()
sort(v instant-vector)函數,輸入:瞬時向量,輸出:key: value = 度量指標:樣本值[升序排列]
sort_desc()
sort(v instant-vector函數,輸入:瞬時向量,輸出:key: value = 度量指標:樣本值[降序排列]
sqrt()
sqrt(v instant-vector)函數,輸入:瞬時向量,輸出:key: value = 度量指標: 樣本值的平方根
time()
time()函數,返回從1970-01-01到現在的秒數,注意:它不是直接返回當前時間,而是時間戳
vector()
vector(s scalar)函數,返回:key: value= {}, 傳入參數值
year()
year(v=vector(time()) instant-vector), 返回年份。
_over_time()
下面的函數列表允許傳入一個范圍向量,返回一個帶有聚合的瞬時向量:
- avg_over_time(range-vector): 范圍向量內每個度量指標的平均值。
- min_over_time(range-vector): 范圍向量內每個度量指標的最小值。
- max_over_time(range-vector): 范圍向量內每個度量指標的最大值。
- sum_over_time(range-vector): 范圍向量內每個度量指標的求和值。
- count_over_time(range-vector): 范圍向量內每個度量指標的樣本數據個數。
- quantile_over_time(scalar, range-vector): 范圍向量內每個度量指標的樣本數據值分位數,φ-quantile (0 ≤ φ ≤ 1)
- stddev_over_time(range-vector): 范圍向量內每個度量指標的總體標準偏差。
- stdvar_over_time(range-vector): 范圍向量內每個度量指標的總體標準方差。
舉例
查詢例子
簡單的時間序列選擇
返回度量指標名稱是http_requests_total的所有時間序列樣本數據:
http_requests_total
返回度量指標名稱是http_requests_total, 標簽分別是job=“apiserver, handler=”/api/comments的所有時間序列樣本數據:
http_requests_total{job=“apiserver”, hanlder="/api/comments"}
返回度量指標名稱是http_requests_total, 標簽分別是job=“apiserver, handler=”/api/comments,且是5分鐘內的所有時間序列樣本數據:
http_requests_total{job=“apiserver”, handler="/api/comments"}[5m]
注意:一個范圍向量表達式結果不能直接在Graph圖表中,但是可以在"console"視圖中展示。
使用正則表達式,你可以通過特定模式匹配標簽為job的特定任務名,獲取這些任務的時間序列。在下面這個例子中, 所有任務名稱以server結尾。
http_requests_total{job=~“server$”}
返回度量指標名稱是http_requests_total, 且http返回碼不以4開頭的所有時間序列數據:
http_requests_total{status!~"^4…$"}
使用函數,操作符等
返回度量指標名稱http_requests_total,且過去5分鐘的所有時間序列數據值速率。
rate(http_requests_total[5m])
假設度量名稱是http_requests_total,且過去5分鐘的所有時間序列數據的速率和,速率的維度是job
sum(rate(http_requests_total)[5m]) by (job)
如果我們有相同維度標簽,我們可以使用二元操作符計算樣本數據,返回值:key: value=標簽列表:計算樣本值。例如,下面這個表達式返回每一個實例剩余內存,單位是M, 如果不同,則需要使用ignoring(label_lists),如果多對一,則采用group_left, 如果是一對多,則采用group_right。
(instance_memory_limit_byte - instant_memory_usage_bytes) / 1024 / 1024
相同表達式,求和可以采用下面表達式:
sum( instance_memory_limit_bytes - instance_memory_usage_bytes) by (app, proc) / 1024 / 1024
如果相同集群調度器任務,顯示CPU使用率度量指標的話,如下所示:
instance_cpu_time_ns{app=“lion”, pro=“web”, rev=“34d0f99”, env=“prod”, job=“cluster-manager”}
instance_cpu_time_ns{app=“elephant”, proc=“worker”, rev=“34d0f99”, env=“prod”, job=“cluster-manager”}
instance_cpu_time_ns{app=“turtle”, proc=“api”, rev=“4d3a513”, env=“prod”, job=“cluster-manager”}
…
我們可以獲取最高的3個CPU使用率,按照標簽列表app和proc分組
topk(3, sum(rate(instance_cpu_time_ns[5m])) by(app, proc))
假設一個服務實例只有一個時間序列數據,那么我們通過下面表達式,可以統計出每個應用的實例數量:
count(instance_cpu_time_ns) by (app)
記錄規則
定義recording rules
配置規則
Prometheus支持可以配置,然后定期執行的兩種規則: recording rules(記錄規則)和alerting rules警告規則。為了在Prometheus系統中包括規則,我們需要創建一個包含規則語句的文件,并通過在Prometheus配置的rule_fields字段加載這個記錄規則文件。
這些規則文件可以通過像Prometheus服務發送SIGNUP信號量,實時重載記錄規則。如果所有的記錄規則有正確的格式和語法,則這些變化能夠生效。
語法檢查規則
在沒有啟動Prometheus服務之前,想快速知道一個規則文件是否正確,可以通過安裝和運行Prometheus的promtool命令行工具檢驗:
go get github.com/prometheus/prometheus/cmd/promtool
promtool check-rules /path/to/examples.rules
當記錄規則文件是有效的,則這個檢查會打印出解析到規則的文本表示,并以返回值0退出程序。
如果有任何語法錯誤的話,則這個命令行會打印出一個錯誤信息到標準輸出,并以返回值1退出程序。無效的輸入參數,則以返回值2退出程序。
記錄規則
記錄規則允許你預先計算經常需要的,或者計算復雜度高的表達式,并將結果保存為一組新的時間序列數據。查詢預計算結果通常比需要時進行計算表達式快得多。對于dashboard是非常有用的,因為dashboard需要實時刷新查詢表達式的結果。
為了增加一個新記錄規則,增加下面的記錄規則到你的規則文件中:
<new time series name>[{<label overrides>}] = <expression to record>
例子:
計算每個job的http請求總數,保存到新的度量指標中>
job:http_inprogree_requests:sum = sum(http_inprogress_requests) by (job)
放棄老標簽,寫入新標簽的結果時間序列數據:
new_time_series{label_to_change=“new_value”, label_to_drop=""} = old_time_series
記錄規則的執行周期有Prometheus的配置文件中的evaluate_interval指定。規則語句的右側表達式一旦被執行,則新的時間戳key為當前時間,value為右邊表達式的樣本值,新的度量指標名稱和標簽列表為左邊名稱。
HTTP API訪問
在Prometheus服務上/api/v1版本api是穩定版。
格式概述
這個API返回是JSON格式。每個請求成功的返回值都是以2xx開頭的編碼。
到達API處理的無效請求,返回一個JSON錯誤對象,并返回下面的錯誤碼:
- 400 Bad Request。當參數錯誤或者丟失時。
- 422 Unprocessable Entity。當一個表達式不能被執行時。
- 503 Service Unavailable。當查詢超時或者中斷時。
在請求到達API之前,其他非2xx的錯誤碼可能會被返回。
JSON返回格式如下所示:
"status": "success" | "error", "data": <data>,// 如果status是"error", 這個數據字段還會包括下面的數據 "errorType": "<string>", "error": "<string>" }輸入時間戳可以被RFC3339格式或者Unix時間戳提供。輸出時間戳以Unix時間戳的方式呈現。
查詢參數名稱可以用[]中括號重復次數。
<series_selector>占位符提供像http_requests_total或者http_requests_total{method=~"^GET|POST$"}的Prometheus時間序列選擇器,并需要在URL中編碼傳輸。
占位符涉及到[0-9]-[smhdwy]。例如:5m表示5分鐘的持續時間。
表達式查詢
查詢語言表達式可以在瞬時向量或者范圍向量中執行。
Instant queries(即時查詢)
瞬時向量的http restful api查詢:
GET /api/v1/query
URL查詢參數:
- query=: Prometheus表達式查詢字符串。
- time=<rfc3339 | uninx_timestamp>: 執行時間戳,可選項。
- timeout=: 執行超時時間設置,默認由-query.timeout標志設置
如果time缺省,則用當前服務器時間表示執行時刻。
這個查詢結果的data部分有下面格式:
{"resultType": "matrix" | "vector" | "scalar" | "string","result": <value> }是一個查詢結果數據,依賴于這個resultType格式, 不同的結果類型,則會有不同的結果數據格式。見表達式查詢結果格式。
下面例子執行了在時刻是2015-07-01T20:10:51.781Z的up表達式:
$ curl 'http://localhost:9090/api/v1/query?query=up&time=2015-07-01T20:10:51.781Z' {"status": "success","data":{"resultType": "vector","result" : [{"metric" : {"__name__" : "up","job" : "prometheus","instance" : "localhost:9090"},"value": [ 1435781451.781, "1" ]},{"metric" : {"__name__" : "up","job" : "node","instance" : "localhost:9100"},"value" : [ 1435781451.781, "0" ]}]} }范圍查詢
下面評估了一個范圍時間的查詢表達式:
GET /api/v1/query_range
URL查詢參數
- query=: Prometheus表達式查詢字符串。
- start=<rfc3339 | unix_timestamp>: 開始時間戳。
- end=<rfc3339 | unix_timestamp>: 結束時間戳。
- step=: 查詢時間步長,范圍時間內每step秒執行一次。
下面查詢結果格式的data部分:
{"resultType": "matrix","result": <value> }對于占位符的格式,詳見范圍向量結果格式。
下面例子執行了在時刻是2015-07-01T20:10:51.781Z的up表達式:
$ curl 'http://localhost:9090/api/v1/query?query=up&time=2015-07-01T20:10:51.781Z' {"status": "success","data":{"resultType": "vector","result" : [{"metric" : {"__name__" : "up","job" : "prometheus","instance" : "localhost:9090"},"value": [ 1435781451.781, "1" ]},{"metric" : {"__name__" : "up","job" : "node","instance" : "localhost:9100"},"value" : [ 1435781451.781, "0" ]}]} }范圍查詢
下面評估了一個范圍時間的查詢表達式:
GET /api/v1/query_range
URL查詢參數
- query=: Prometheus表達式查詢字符串。
- start=<rfc3339 | unix_timestamp>: 開始時間戳。
- end=<rfc3339 | unix_timestamp>: 結束時間戳。
- step=: 查詢時間步長,范圍時間內每step秒執行一次。
下面查詢結果格式的data部分:
{"resultType": "matrix","result": <value> }對于占位符的格式,詳見范圍向量結果格式。
下面例子評估的查詢條件up,且30s范圍的查詢,步長是15s。
$ curl 'http://localhost:9090/api/v1/query_range?query=up&start=2015-07-01T20:10:30.781Z&end=2015-07-01T20:11:00.781Z&step=15s' {"status" : "success","data" : {"resultType" : "matrix","result" : [{"metric" : {"__name__" : "up","job" : "prometheus","instance" : "localhost:9090"},"values" : [[ 1435781430.781, "1" ],[ 1435781445.781, "1" ],[ 1435781460.781, "1" ]]},{"metric" : {"__name__" : "up","job" : "node","instance" : "localhost:9091"},"values" : [[ 1435781430.781, "0" ],[ 1435781445.781, "0" ],[ 1435781460.781, "1" ]]}]} }查詢元數據
通過標簽匹配器找到度量指標列表
下面例子返回了度量指標列表 且不返回時間序列數據值。
GET /api/v1/series
URL查詢參數:
- match[]=<series_selector>: 選擇器是series_selector。這個參數個數必須大于等于1.
- start=<rfc3339 | unix_timestamp>: 開始時間戳。
- end=<rfc3339 | unix_timestamp>: 結束時間戳。
返回結果的data部分,是由key-value鍵值對的對象列表組成的。
下面這個例子返回時間序列數據, 選擇器是up或者process_start_time_seconds{job=“prometheus”}
$ curl -g 'http://localhost:9090/api/v1/series?match[]=up&match[]=process_start_time_seconds{job="prometheus"}' {"status" : "success","data" : [{"__name__" : "up","job" : "prometheus","instance" : "localhost:9090"},{"__name__" : "up","job" : "node","instance" : "localhost:9091"},{"__name__" : "process_start_time_seconds","job" : "prometheus","instance" : "localhost:9090"}] }查詢標簽值
下面這個例子,返回了帶有指定標簽的標簽值列表
GET /api/v1/label/<label_name>/values
這個返回JSON結果的data部分是帶有label_name=job的值列表:
$ curl http://localhost:9090/api/v1/label/job/values {"status" : "success","data" : ["node","prometheus"] }刪除時間序列
下面的例子,是從Prometheus服務中刪除匹配的度量指標和標簽列表:
DELETE /api/v1/series
URL查詢參數
match[]=<series_selector>: 刪除符合series_selector匹配器的時間序列數據。參數個數必須大于等于1.
返回JSON數據中的data部分有以下的格式
{
“numDeleted”:
}
下面的例子刪除符合度量指標名稱是up或者時間序列為process_start_time_seconds{job=“prometheus”}:
$ curl -XDELETE -g 'http://localhost:9090/api/v1/series?match[]=up&match[]=process_start_time_seconds{job="prometheus"}' {"status" : "success","data" : {"numDeleted" : 3} }表達式查詢結果格式
表達式查詢結果格式
表達式查詢結果,在data部分的result部分中,返回下面的數據。<sample_value>占位符有數值樣本值。JSON不支持特殊浮點值,例如:NaN, Inf和-Inf。因此樣本值返回結果是字符串,不是原生的數值。
范圍向量
范圍向量返回的result類型是一個matrix矩陣。下面返回的結果是result部分的數據格式:
[{"metric": { "<label_name>": "<label_value>", ... },"values": [ [ <unix_time>, "<sample_value>" ], ... ]},... ]瞬時向量
瞬時向量的result類型是vector。下面是result部分的數據格式
[{"metric": { "<label_name>": "<label_value>", ... },"value": [ <unix_time>, "<sample_value>" ]},... ]Scalars標量
標量查詢返回result類型是scalar。下面是result部分的數據格式:
[ <unix_time>, “<scalar_value>” ]
字符串
字符串的result類型是string。下面是result部分的數據格式:
[ <unix_time>, “<string_value>” ]
啟動
這是個類似"hello,world"的試驗,教大家怎樣快速安裝、配置和簡單地搭建一個DEMO。你會下載和本地化運行Prometheus服務,并寫一個配置文件,監控Prometheus服務本身和一個簡單的應用,然后配合使用query、rules和圖表展示采樣點數據
下載和運行Prometheus
最新下載頁, 然后提取和運行它,so easy:
tar zxvf prometheus-*.tar.gz cd prometheus-*在開始啟動Prometheus之前,我們要配置它
配置Prometheus監控自身
Prometheus從目標機上通過http方式拉取采樣點數據, 它也可以拉取自身服務數據并監控自身的健康狀況
當然Prometheus服務拉取自身服務采樣數據,并沒有多大的用處,但是它是一個好的DEMO。保存下面的Prometheus配置,并命名為:prometheus.yml:
global:scrape_interval: 15s # 默認情況下,每15s拉取一次目標采樣點數據。# 我們可以附加一些指定標簽到采樣點度量標簽列表中, 用于和第三方系統進行通信, 包括:federation, remote storage, Alertmanagerexternal_labels:monitor: 'codelab-monitor'# 下面就是拉取自身服務采樣點數據配置 scrape_configs:# job名稱會增加到拉取到的所有采樣點上,同時還有一個instance目標服務的host:port標簽也會增加到采樣點上- job_name: 'prometheus'# 覆蓋global的采樣點,拉取時間間隔5sscrape_interval: 5sstatic_configs:- targets: ['localhost:9090']對于一個完整的配置選項,請見配置文檔
啟動Prometheus
指定啟動Prometheus的配置文件,然后運行
./prometheus --config.file=prometheus.yml
這樣Prometheus服務應該起來了。你可以在瀏覽器上輸入:http://localhost:9090, 就可以看到Prometheus的監控界面
你也可以通過輸入http://localhost:9090/metrics,直接拉取到所有最新的采樣點數據集
使用expression browser(暫翻譯:瀏覽器上輸入表達式)
為了使用Prometheus內置瀏覽器表達式,導航到http://localhost:9090/graph,并選擇帶有"Graph"的"Console".
在拉取到的度量采樣點數據中, 有一個metric叫prometheus_target_interval_length_seconds, 兩次拉取實際的時間間隔,在表達式的console中輸入:
prometheus_target_interval_length_seconds
這個應該會返回很多不同的倒排時間序列數據,這些度量名稱都是prometheus_target_interval_length_seconds, 但是帶有不同的標簽列表值,這些標簽列表值指定了不同的延遲百分比和目標組間隔
如果我們僅僅對99%的延遲感興趣,則我們可以使用下面的查詢去清洗信息:
prometheus_target_interval_length_seconds{quantile=“0.99”}
為了統計返回時間序列數據個數,你可以寫:
count(prometheus_target_interval_length_seconds)
有關更多的表達式語言,請見表達式語言文檔
使用graph interface
見圖表表達式,導航到http://localhost:9090/graph, 然后使用"Graph" tab
例如,進入下面表達式,繪圖最近1分鐘產生chunks的速率:
rate(prometheus_tsdb_head_chunks_created_total[1m])
啟動其他一些采樣目標
Go客戶端包括了一個例子,三個服務只見的RPC調用延遲
首先你必須有Go的開發環境,然后才能跑下面的DEMO, 下載Prometheus的Go客戶端,運行三個服務:
git clone https://github.com/prometheus/client_golang.git
cd client_golang/examples/random
go get -d
go build
## 啟動三個服務
./random -listen-address=:8080
./random -listen-address=:8081
./random -listen-address=:8082
現在你在瀏覽器輸入:http://localhost:8080/metrics, http://localhost:8081/metrics, http://localhost:8082/metrics, 能看到所有采集到的采樣點數據
配置Prometheus去監控這三個目標服務
現在我們將會配置Prometheus,拉取三個目標服務的采樣點。我們把這三個目標服務組成一個job, 叫example-radom. 然而,想象成,前兩個服務是生產環境服務,后者是測試環境服務。我們可以通過group標簽分組,在這個例子中,我們通過group="production"標簽和group="test"來區分生產和測試
scrape_configs:- job_name: 'example-random'scrape_interval: 5sstatic_configs:- targets: ['localhost:8080', 'localhost:8081']labels:group: 'production'- targets: ['localhost:8082']labels:group: 'test'進入瀏覽器,輸入rpc_duration_seconds, 驗證Prometheus所拉取到的采樣點中每個點都有group標簽,且這個標簽只有兩個值production, test
聚集到的采樣點數據配置規則
上面的例子沒有什么問題, 但是當采樣點海量時,計算成了瓶頸。查詢、聚合成千上萬的采樣點變得越來越慢。為了提高性能,Prometheus允許你通過配置文件設置規則,對表達式預先記錄為全新的持續時間序列。讓我們繼續看RPCs的延遲速率(rpc_durations_seconds_count), 如果存在很多實例,我們只需要對特定的job和service進行時間窗口為5分鐘的速率計算,我們可以寫成這樣:
avg(rate(rpc_durations_seconds_count[5m])) by (job, service)
為了記錄這個計算結果,我們命名一個新的度量:job_service:rpc_durations_seconds_count:avg_rate5m, 創建一個記錄規則文件,并保存為prometheus.rules.yml:
groups: - name: examplerules:- record: job_service:rpc_durations_seconds_count:avg_rate5mexpr: avg(rate(rpc_durations_seconds_count[5m])) by (job, service)然后再在Prometheus配置文件中,添加rule_files語句到global配置區域, 最后配置文件應該看起來是這樣的:
global:scrape_interval: 15s # By default, scrape targets every 15 seconds.evaluation_interval: 15s # Evaluate rules every 15 seconds.# Attach these extra labels to all timeseries collected by this Prometheus instance.external_labels:monitor: 'codelab-monitor'rule_files:- 'prometheus.rules.yml'scrape_configs:- job_name: 'prometheus'# Override the global default and scrape targets from this job every 5 seconds.scrape_interval: 5sstatic_configs:- targets: ['localhost:9090']- job_name: 'example-random'# Override the global default and scrape targets from this job every 5 seconds.scrape_interval: 5sstatic_configs:- targets: ['localhost:8080', 'localhost:8081']labels:group: 'production'- targets: ['localhost:8082']labels:group: 'test'然后重啟Prometheus服務,并指定最新的配置文件,查詢并驗證job_service:rpc_durations_seconds_count:avg_rate5m度量指標
可視化
Grafana
Grafana支持Prometheus可視化
Grafana支持Prometheus查詢。從Grafana 2.5.0 (2015-10-28)開始Prometheus可以作為它的數據源。
下面的例子:Prometheus查詢在Grafana Dashboard界面的圖表展示
Grafana安裝
如果要Grafana的完整安裝教程,詳見Grafana官方文檔
在Linux安裝Grafana,如下所示:
使用方法
默認情況下,Grafana服務端口http://localhost:3000。默認登錄用戶名和密碼“admin/admin”。
創建一個Prometheus數據源
為了創建一個Prometheus數據源Data source:
點擊Grafana的logo,打開工具欄。
在工具欄中,點擊"Data Source"菜單。
點擊"Add New"。
數據源Type選擇“Prometheus”。
設置Prometheus服務訪問地址(例如:http://localhost:9090)。
調整其他想要的設置(例如:關閉代理訪問)。
點擊“Add”按鈕,保存這個新數據源。
下面顯示了一個Prometheus數據源配置例子:
創建一個Prometheus Graph圖表
下面是添加一個新的Grafana的標準方法:
點擊圖表Graph的title,它在圖表上方中間。然后點擊“Edit”。
在“Metrics”tab下面,選擇你的Prometheus數據源(下面右邊)。
在“Query”字段中輸入你想查詢的Prometheus表達式,同時使用“Metrics”字段通過自動補全查找度量指標。
為了格式化時間序列的圖例名稱,使用“Legend format”圖例格式輸入。例如,為了僅僅顯示這個標簽為method和status的查詢結果,你可以使用圖例格式{{method{} - {{status}}。
調節其他的Graph設置,知道你有一個工作圖表。
下面顯示了一個Prometheus圖表配置:
從Grafana.net導入預構建的dashboard
Grafana.net維護一個共享儀板表,它們能夠被下載,并在Grafana服務中使用。使用Grafana.net的“Filter”選項去瀏覽來自Prometheus數據源的dashboards
你當前必須手動編輯下載下來的JSON文件和更改datasource: 選擇Prometheus服務作為Grafana的數據源,使用“Dashboard”->“Home”->"Import"選項去導入編輯好的dashboard文件到你的Grafana中。
控制模板
控制模板允許使用Go語言模板創建任意的console。這些由Prometheus服務提供
Getting started
Prometheus提供了一系列的控制模板來幫助您。這些可以在Prometheus服務上的console/index.html.example中找到,如果Prometheus服務正在刪除帶有標簽job="node"的Node Exporter, 則會顯示NodeExporter控制臺
這個例子控制臺包括5部分:
- 在頂部的導航欄
- 左邊的一個菜單
- 底部的時間控制
- 在中心的主內容,通常是圖表
- 右邊的表格
這個導航欄是鏈接到其他系統,例如Prometheus其他方面的文檔,以及其他任何使你明白的。該菜單用于在同一個Prometheus服務中導航,它可以快速在另一個tar中打開一個控制臺。這些都是在console_libraries/menu.lib中配置。
時間控制臺允許持久性和圖表范圍的改變。控制臺URLs能夠被分享,并且在其他的控制臺中顯示相同的圖表。
主要內容通常是圖表。這里有一個可配置的JavaScript圖表庫,它可以處理來自Prometheus服務的請求,并通過Rickshaw來渲染
最后,在右邊的表格可以用筆圖表更緊湊的形式顯示統計信息。
例子控制臺
這是一個最基本的控制臺。它顯示任務的數量,其中CPU平均使用率、以及右側表中的平均內存使用率。主要內容具有每秒查詢數據。
{{template "head" .}}{{template "prom_right_table_head"}} <tr><th>MyJob</th><th>{{ template "prom_query_drilldown" (args "sum(up{job='myjob'})") }}/ {{ template "prom_query_drilldown" (args "count(up{job='myjob'})") }}</th> </tr> <tr><td>CPU</td><td>{{ template "prom_query_drilldown" (args"avg by(job)(rate(process_cpu_seconds_total{job='myjob'}[5m]))""s/s" "humanizeNoSmallPrefix") }}</td> </tr> <tr><td>Memory</td><td>{{ template "prom_query_drilldown" (args"avg by(job)(process_resident_memory_bytes{job='myjob'})""B" "humanize1024") }}</td> </tr> {{template "prom_right_table_tail"}}{{template "prom_content_head" .}} <h1>MyJob</h1><h3>Queries</h3> <div id="queryGraph"></div> <script> new PromConsole.Graph({node: document.querySelector("#queryGraph"),expr: "sum(rate(http_query_count{job='myjob'}[5m]))",name: "Queries",yAxisFormatter: PromConsole.NumberFormatter.humanizeNoSmallPrefix,yHoverFormatter: PromConsole.NumberFormatter.humanizeNoSmallPrefix,yUnits: "/s",yTitle: "Queries" }) </script>{{template "prom_content_tail" .}}{{template "tail"}}模板部分不翻譯了,建議用Grafana
工具
客戶端
客戶端庫
在你能夠監控你的服務器之前,你需要通過Prometheus客戶端庫把監控的代碼放在被監控的服務代碼中。下面實現了Prometheus的度量指標類型metric types。
選擇你需要的客戶端語言,在你的服務實例上通過HTTP端口提供內部度量指標
- Go
- Java or Scala
- Python
- Ruby
當Prometheus獲取實例的HTTP端點時,客戶庫發送所有跟蹤的度量指標數據到服務器上。
如果沒有可用的客戶端語言版本,或者你想要避免依賴,你也可以實現一個支持的導入格式到度量指標數據中。
在實現一個新的Prometheus客戶端庫時,請遵循客戶端指南。注意,這個文檔在仍然在更新中。同時也請關注開發郵件列表。我們非常樂意地給出合適的意見或者建議。
總結
以上是生活随笔為你收集整理的开源监控Prometheus介绍,安装,配置,使用详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 软件测试之与大厂测试经理的问答
- 下一篇: LINUX 下C实现线程池《转载》