目录
1.查询语句
1.1 直接使用metrics的name进行查询
1.2 使用标签查询
2.使用记录
2.1 查询语句有加上时间限制
2.2 聚合分组查询
2.3 对区间向量求聚合
2.4 关于Prometheus的api
3 其他
3.1 采集到重复数据
3.2 丢失更新数据
3.3 时区问题
参考文献
例如我定义如下几个度量
CONST.GAUGE0 = Gauge.build()
.name(CONST.HOST_NAME+"_a")
.labelNames("prov","label")
.help(CONST.HOST_DES)
.register();
CONST.GAUGE1 = Gauge.build()
.name(CONST.HOST_NAME+"_s")
.labelNames("host_ip","process_port","label")
.help(CONST.HOST_DES)
.register();
CONST.GAUGE2 = Gauge.build()
.name(CONST.HOST_NAME+"_c")
.labelNames("host_ip","process_port","label","d_label","to_ip","to_port")
.help(CONST.HOST_DES)
.register();
其中CONST.HOST_NAME="online_access_host_1"
在Graph中,直接输入 online_acces_host_1_a,就能看到如下向量集
使用label查询是非常方便的,我们可以通过如下的查询获取所有label=2.1.1的向量。
{label="2.1.1"}
其他的标签也是一样的效果。
其实比较重要的是如何进行聚合查询,例如sum的使用、avg的使用。参考文献1中对这方面有比较好的讲解。
这里记录下我自己在使用过程中的一些体会。
{label="2.1.2"} [5m]
它的结果类型是“matrix”,就是一个数据集,不是向量集。是不能用sum聚合的。sum进行聚合是对向量的聚合,结果还是向量集。
场景:在GAUGE1这个度量中,存在这样情况,一台设备有4个process_port,对应标签50个。
{host_ip="192.168.1.1",label="1.2.1"}
按照上面这样写,可以直接出来四条记录如下:
sum({host_ip="192.168.1.1"}) by (process_port)
使用 by关键字进行分类聚合,结果如下:
sum({label="1.6.2"}) by (host_ip)
灵活的运用标签进行筛选,结合聚合函数,Prometheus能提供非常强大的数据查询效果。
例如:求某一个指标一小时内的最大值,这是对向量的某个固定区间求最大值,而不是不同纬度的最大值。
max_over_time({label='1.4.1'} [3h])
类似用法的还有如下函数
先看下一下代码
public static void main(String[] args) throws Exception
{
String query = URLEncoder.encode("{label=\"2.1.2\"} [5m]","utf-8");
String url = "http://localhost:9090/api/v1/query?query="+query;
String ret = HttpKit.get(url);
System.out.println(ret);
}
这段代码的意思,就是模拟请求Prometheus的api接口,将查询语句直接传递过去,就能获取对应的数据。我们可以自己定制化的开发对应的展示效果。
出参如下:
{
"status": "success",
"data": {
"resultType": "matrix",
"result": [{
"metric": {
"__name__": "online_accse_host_1_a",
"instance": "sp1-exp",
"job": "bis-sp1",
"label": "2.1.2",
"prov": "yunnan"
},
"values": [
[1552558929.044, "3903089"],
[1552559214.044, "3903089"]
]
}]
}
}
这是一个标准的JSON串。一般情况下,我们在使用Prometheus的时候,都会配套的使Grafana等其他数据展示的工具,但其实,我们也可以自己开发自定义的panel。通过访问Prometheus的接口服务,来获取对应的数据。
在使用的过程中,还有以下小细节问题记录。Prometheus通过配置scrape_interval和evaluation_interval参数来设置向exporter采集数据的间隔时间。采集数据的间隔和数据生成的时间间隔大小不同,会对数据采集结果有影响。
假如采集的间隔时间小于数据生成的间隔时间,就会采集到重复的数据。
即:假设Prometheus是每5秒采集一次,但是exporter是每11秒生成一次数据,那么第一次采集成功后,第二次采集的数据还是之前的历史数据,并未更新。
假如采集的时间间隔大于数据生成的时间间隔,那么就会丢失更新数据。上一次的数据还未被采集,就被新的数据覆盖了。
简而言之:Prometheus每次向exporter获取数据的时候,都是获取的当前值,不会取到历史数据。
同样的:在使用pushgetway做中转的时候,也有同样的问题,并不能获取到历史数据,或者避免重复数据。
通过prometheus的UI查询界面查询的到数据在查看graph的时候会发现时间对不上,经过观察比对,会发现时间永远是比当前时间小8个小时。检查Prometheus所在主机的时区以及业务bis_exporter的主机的时区以及时间都相同,但是查看的时候时间数据时间对不上,不过,最怪异的是通过Grafana展示的数据曲线却是正确的,时间也正确。
最后经过搜索发现,Prometheus为了保证时序的准确性,内部所有组件都是会用UTC时间,查了下出的日志文件时间也是少8个小时,这就对的上了。
时间戳必须使用UTC时间么?
是的。为了避免时区的混乱,prometheus所有的组件内部都强制使用Unix时间,对外展示使用UTC时间。如果想改变时区,可以在UI改为合适的时区时间。
【1】Prometheus 查询语言
【2】Prometheus监控系统简介(2.1.0)
【3】Prometheus FAQ