【时序 4 种类型】
Prometheus定义了4种不同的指标类型(metric type):Counter(计数器)、Gauge(仪表盘)、Histogram(直方图)、Summary(摘要)
一个样本(sample),样本由以下三部分组成:
指标(metric):metric name和描述当前样本特征的labelsets;
时间戳(timestamp):一个精确到毫秒的时间戳;
样本值(value): 一个float64的浮点型数据表示当前样本的值。
<--------------- metric ---------------------><-timestamp -><-value->
http_request_total{status="200", method="GET"}@1434417560938 => 94355
http_request_total{status="200", method="GET"}@1434417561287 => 94334
【prometheus.yml 四个模块详解】
global: 全局配置(如果有内部单独设定,会覆盖这个参数)
alerting: 告警插件定义。这里会设定alertmanager这个报警插件。
rule_files: 告警规则。 按照设定参数进行扫描加载,用于自定义报警规则,其报警媒介和route路由由alertmanager插件实现。
scrape_configs:采集配置。配置数据源,包含分组job_name以及具体target。又分为静态配置和服务发现
global指标说明:
# my global config
global:
scrape_interval: 15s # 默认15s 全局每次数据收集的间隔
evaluation_interval: 15s # 规则扫描时间间隔是15秒,默认不填写是 1分钟
scrape_timeout: 5s #超时时间
external_labels: # 用于外部系统标签的,不是用于metrics(度量)数据
【PromQL 基本使用】
[运算符说明]
= :等于
!= :不等于
=~ :正则匹配
!~ :正则不匹配
[时间单位说明]
s 秒
m 分
h 小时
d 天
w 周
y 年
[集合运算符]
and 并且(交集)
or 或者(并集)
unless 排除 (差集)
up{instance="localhost:9090"} and up{job="prometheus"}
up{instance="localhost:9090"} or up{job="prometheus"}
up unless up{job="prometheus"}
[过滤器]
{job=~".*"} # 非法! 所有的 PromQL 表达式必须至少包含一个指标名称,或者一个不会匹配到空字符串的标签过滤器
{job=~".+"} # 合法!
{job=~".*",method="get"} # 合法!
[查询条件]
up{instance=~"localhost:39.*"}
http_requests_total{code="200"} // 表示查询名字为 http_requests_total,code 为 "200" 的数据
http_requests_total{code!="200"} // 表示查询 code 不为 "200" 的数据
http_requests_total{code=~"2.."} // 正则表达式,表示查询 code 为 "2xx" 的数据
http_requests_total{code!~"2.."} // 正则表达式,表示查询 code 不为 "2xx" 的数据
rate(http_requests_total[5m]) //http_requests_total 5分钟内,平均每秒数据
quantile (分位数)
count_values('code',prometheus_http_requests_total) //count_values用于时间序列中每一个样本值出现的次数,统计标签带code的请求
[正则匹配]
正向匹配。使用 label=~regx 表示选择那些标签符合正则表达式定义的时间序列
反向匹配。使用 label!~regx 进行排除
如:prometheus_http_requests_total{handler=~"/api/v1/.*"}
[范围查询]
prometheus_http_requests_total 表达式查询时间序列时,同一个指标同一标签只会返回一条数据。这样的表达式我们称之为瞬间向量表达式,而返回的结果称之为瞬间向量。
而如果我们想查询一段时间范围内的样本数据,那么我们就需要用到区间向量表达式,其查询出来的结果称之为区间向量。时间范围通过时间范围选择器 [] 进行定义
例如,通过以下表达式可以选择最近5分钟内的所有样本数据:
prometheus_http_requests_total{}[5m]
PromQL的时间范围选择器支持其它时间单位:s(秒)、m(分钟)、h(小时)、d(天)、w(周)、y(年)
[时间位移操作]
#查询1小时前 5分钟的最新数据
prometheus_http_requests_total{}[5m] offset 1h
[查询结果类型]
PromQL 查询结果主要有 3 种类型:
瞬时数据 (Instant vector): 包含一组时序,每个时序只有一个点,例如:http_requests_total
区间数据 (Range vector): 包含一组时序,每个时序有多个点,例如:http_requests_total[5m]
纯量数据 (Scalar): 纯量只有一个数字,没有时序,例如:count(http_requests_total)
[子查询]
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): 区间向量内每个度量指标的总体标准方差
[内置函数]
predict_linear(v range-vector, t scalar) //predict_linear(node_filesystem_free_bytes[1h],3600) 通过简单线性回归预测t秒后的样本值,与gauge一起使用。根据过去1小时的文件系统剩余空间量,预测1小时之后的剩余空间
absent(v instant-vector) //absent(up{job="node"} == 1) 如果向量有元素,则返回一个空向量;如果向量没有元素,则返回值为 1。
absent_over_time(v range-vector) //absent_over_time(up{job="node1"}[1h]) 如果范围向量有元素,则返回一个空向量;如果范围向量没有元素,则返回值为 1。
round(v instant-vector, to_nearest=1 scalar) //对样本值四舍五入取整,to_nearest参数是可选的,默认为 1,表示样本返回的是最接近 1 的整数倍的值
resets(v range-vector) //返回样本范围时间内的复位次数。与counter使用,两个连续样本之间值如有减少则被视为计数器复位
changes(v range-vector) //返回某段时间内样本值改变的次数
floor(vector(time())/60)%60
floor(avg(http_requests_total{code="200"})) //将所有元素的样本值v向下舍入到最接近的整数
ceil(avg(http_requests_total{code="200"})) //将所有元素的样本值v向上舍入到最接近的整数
clamp(v instant-vector, min scalar, max scalar) //将所有元素的样本值钳制在v下限为min和上限为max
clamp_max(v instant-vector, max scalar) //将所有元素的样本值钳制在v上限为max,输入一个瞬时向量和最大值,样本数据值若大于 max,则改为 max,否则不变
clamp_min(v instant-vector, min scalar) //将所有元素的样本值钳制在v下限为min,输入一个瞬时向量和最小值,样本数据值若小于 min,则改为 min,否则不变
increase(node_cpu[2m]) / 120 //node_cpu[2m]获取时间序列最近两分钟的所有样本,increase计算出最近两分钟的增长量,最后除以时间120秒得到node_cpu样本在最近两分钟的平均增长率
increase(http_requests_total{job="apiserver"}[5m]) //返回区间向量中每个时间序列过去 5 分钟内 HTTP 请求数的增长数,increase 的返回值类型只能是计数器类型
rate(node_cpu[2m]) //rate函数可以直接计算区间向量v在时间窗口内平均增长速率,rate函数是通过第一个和最后一个样本计算
irate(node_cpu[2m]) //irate函数是通过区间向量中最后两个样本数据来计算区间向量的增长速率
scalar()将单个瞬时向量转换为标量
vector(s scalar)将标量作为没有标签的向量返回。
sort(v instant-vector)返回按样本值升序排序的向量元素。
sort_desc() 与sort()相反,按降序排序。
topk(3, http_requests_total) //查询最靠前的 3 个值
bottomk(5, prometheus_http_requests_total) //查询后5个数据
avg_over_time(node_filesystem_files_free[1d])
sum_over_time //计算指定间隔内所有值的总和
如:
有如下两个时序数据:(间隔为秒)
request_count{a=1} 1,1,1,1,1
request_count{a=2} 1,1,1,1,1
执行 sum_over_time(request_count[5s]) 返回如下的时序:
request_count{a=1} 5
request_count{a=2} 5
假设您在指定的时间间隔内拥有以下数据系列:5, 5, 5, 5, 6, 6, 7, 8, 8, 8
increase = 8-5 = 3
sum_over_time = 5+5+5+5+6+6+7+8+8+8 = 63
[时间日期]
day_of_month(vector(time())
day_of_month(v=vector(time()) instant-vector) //如果样本值是utc时间,则返回这个时间所属月份中的日期(1-31)v=vector(time()) 为默认参数
day_of_week(v=vector(time()) instant-vector) //同上,如果样本值是utc时间,则返回这个时间所属星期几(0-6)
days_in_month(v=vector(time()) instant-vector) //如果样本值是utc时间,则返回这个时间所属月份的天数(28-31)
hour(v=vector(time()) instant-vector) //如果样本值是utc时间,则返回这个时间所属一天中的第几个小时(1-13)
minute(v=vector(time()) instant-vector) //如果样本值是utc时间,则返回这个时间所属小时中的第几分钟(1-59)
month(v=vector(time()) instant-vector) //如果样本值是utc时间,则返回这个时间所属的月份(1-12)
year(v=vector(time()) instant-vector) //如果样本值是utc时间,则返回这个时间所属的年份
time() //返回自1970 年 1 月 1 日 UTC 以来的秒数,不是系统时间,而是表达式计算时那一刻的时间
timestamp(v instant-vector)返回每个样本值的时间戳,自 1970 年 1 月 1 日 UTC 以来的秒数
[label_replace和label_join]
label_replace和label_join是PromQL的预置函数,支持将label的value进行截取和拼接,生成新的label。
值得注意的是,它们不改变源label的name及value,仅生成新label。
label_replace(v instant-vector, dst_label string, replacement string, src_label string, regex string)
label_replace(up{job="node"},"hello","$1","job","(.*)") //up{hello="node", instance="localhost:9182", job="node"}
label_join(v instant-vector, dst_label string, separator string, src_label_1 string, src_label_2 string, ...)
label_join(up{instance="localhost:9100", job="node"},"new_label","-","instance","job") //up{instance="localhost:9100", job="node", new_label="localhost:9100-node"}
[聚合]
sum by (node) ({__name__=~"metricA|metricB"}) //对两个不同指标求和
sum by(handler) (increase(prometheus_http_requests_total{}[5m]))
sum(sum_over_time(sumline[5m]))
[predict_linear 增长预测]
//基于2小时的样本数据,来预测主机可用磁盘空间的是否在4个小时候被占满
predict_linear(node_filesystem_free{job="node"}[2h], 4 * 3600) < 0
without用于从计算结果中移除列举的标签,而保留其它标签。
by则正好相反,结果向量中只保留列出的标签,其余标签则移除
sum(http_requests_total) without (instance) 等价于 sum(http_requests_total) by (application, group)
[ignoring 、without]
up{instance="localhost:9090", job="prometheus"}/ignoring(hello) label_replace(up{instance="localhost:9090", job="prometheus"},"hello","$1","job","(.*)")
sum(kms_requests_total_from_sumline) by(exported_instance,instance,job,retcode) //等价于sum(kms_requests_total_from_sumline) without(cmdid)
【匹配模式详解】
PromQL中有两种典型的匹配模式:一对一(one-to-one),多对一(many-to-one)或一对多(one-to-many)
在操作符两边表达式标签不一致的情况下,可以使用on(label list)或者ignoring(label list)来修改便签的匹配行为。使用ignoreing可以在匹配时忽略某些便签。而on则用于将匹配行为限定在某些便签之内
[一对一匹配]
//该表达式会返回在过去5分钟内,HTTP请求状态码为500的在所有请求中的比例。如果没有使用ignoring(code),
//操作符两边表达式返回的瞬时向量中将找不到任何一个标签完全相同的匹配项。
method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m
[多对一和一对多]
//该表达式中,左向量method_code:http_errors:rate5m包含两个标签method和code。而右向量method:http_requests:rate5m中只包含一个标签method,因此匹配时需要使用ignoring限定匹配的标签为code。 在限定匹配标签后,右向量中的元素可能匹配到多个左向量中的元素 因此该表达式的匹配模式为多对一,需要使用group修饰符group_left指定左向量具有更好的基数
method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m
#当前访问量
sum(increase(test_total{id="14",groupid=~"123"}[2m])) /2
#昨日访问量
sum(increase(test_total{id="14",groupid=~"123"}[2m] offset 1d)) /2
[接口]
1、/api/v1/query(GET/POST)
即时查询,使用参数如下:
- query=<查询语句>
- time=<rfc3339 | unix_timestamp>时间戳,可选项
- timeout=<duration>: 超时时间,-query.timeout限制,可选项
若time不给定,默认为服务器当前时间。
curl 'http://localhost:9090/api/v1/query?query=up'
curl 'http://localhost:9090/api/v1/query?query=up&time=2022-11-28T02:10:30.781Z'
2、/api/v1/query_range(GET/POST)
范围查询,使用参数如下:
- query=<查询语句>
- start=<rfc3339 | unix_timestamp>:开始时间(包含该值)
- end=<rfc3339 | unix_timestamp>:结束时间(包含该值)
- step=<duration | float>duration:浮点格式的步长
- timeout=<duration>: 超时时间
curl 'http://localhost:9090/api/v1/query_range?query=up&start=2022-11-28T02:10:30.781Z&end=2022-11-29T20:11:00.781Z&step=15m'
3、/api/v1/series(GET/POST)
元数据序列查询,使用参数如下:
- match[]=<series_selector>:选择返回参数
- start=<rfc3339 | unix_timestamp>:开始时间
- end=<rfc3339 | unix_timestamp>:结束时间
curl -g 'http://localhost:9090/api/v1/series?''match[]=up'
4、/api/v1/labels
获取元数据标签
- match[]=<series_selector>:选择返回参数
- start=<rfc3339 | unix_timestamp>:开始时间
- end=<rfc3339 | unix_timestamp>:结束时间
curl 'localhost:9090/api/v1/labels'
curl -g 'http://localhost:9090/api/v1/series?match[]=up&match[]=process_start_time_seconds{job="prometheus"}' #标签匹配器找到度量指标列表
curl 'localhost:9090/api/v1/labels' #获取标签名
curl http://localhost:9090/api/v1/targets #返回Prometheus目标发现的当前状态概述
curl http://localhost:9090/api/v1/rules #回当前加载的警报和记录规则列表