获取自Prometheus计数器的上一次增加以来经过的时间

muf*_*fel 2 prometheus

考虑一个Prometheus度量标准foo_total,该度量标准统计事件的发生总数foo,即,只要不重新启动提供服务,该度量标准就只会增加。

自该指标的最后一次增加以来,是否有任何方法可以获取时间跨度(例如秒数)?我知道由于刮板的时间,该值肯定不是那么准确,但是对我来说,几分钟的准确度就足够了。

背景:我想在Grafana中使用这种查询来概述是否定期使用某些服务以及是否在定义的宽限期内完成了某些工作。我对指标本身没有任何影响。

Ali*_*ean 7

以下是Singlestat面板的JSON,该面板将显示最近一次更新up{job="prometheus"}指标的时间。这与您要求的不完全相同:这是最后一次而不是之后的时间;它仅在Singlestat面板中有用(即,由于它不是单个值,因此您无法获取该值并以图形形式对其进行绘制);并且只会显示仪表板时间范围内的更改。

基础查询为timestamp(changes(up{job="prometheus"}[$__interval]) > 0) * 1000,因此该查询基本上将返回所有时间戳,这些时间戳在最后$__interval几秒钟内发生了任何更改(由时间范围和Singlestat面板的大小(以像素为单位)动态确定)。然后,Singlestat面板将显示最后一个值(如果有)。(之所以* 1000在这里是因为Grafana期望时间戳以毫秒为单位。)

{
  "type": "singlestat",
  "title": "Last Change",
  "gridPos": {
    "x": 0,
    "y": 0,
    "w": 12,
    "h": 9
  },
  "id": 8,
  "targets": [
    {
      "expr": "timestamp(changes(up{job=\"prometheus\"}[$__interval]) > 0) * 1000",
      "intervalFactor": 1,
      "format": "time_series",
      "refId": "A",
      "interval": "10s"
    }
  ],
  "links": [],
  "maxDataPoints": 100,
  "interval": null,
  "cacheTimeout": null,
  "format": "dateTimeAsIso",
  "prefix": "",
  "postfix": "",
  "nullText": null,
  "valueMaps": [
    {
      "value": "null",
      "op": "=",
      "text": "N/A"
    }
  ],
  "mappingTypes": [
    {
      "name": "value to text",
      "value": 1
    },
    {
      "name": "range to text",
      "value": 2
    }
  ],
  "rangeMaps": [
    {
      "from": "null",
      "to": "null",
      "text": "N/A"
    }
  ],
  "mappingType": 1,
  "nullPointMode": "connected",
  "valueName": "current",
  "prefixFontSize": "50%",
  "valueFontSize": "80%",
  "postfixFontSize": "50%",
  "thresholds": "",
  "colorBackground": false,
  "colorValue": false,
  "colors": [
    "#299c46",
    "rgba(237, 129, 40, 0.89)",
    "#d44a3a"
  ],
  "sparkline": {
    "show": false,
    "full": false,
    "lineColor": "rgb(31, 120, 193)",
    "fillColor": "rgba(31, 118, 189, 0.18)"
  },
  "gauge": {
    "show": false,
    "minValue": 0,
    "maxValue": 100,
    "thresholdMarkers": true,
    "thresholdLabels": false
  },
  "tableColumn": ""
}
Run Code Online (Sandbox Code Playgroud)

如果您希望此方法更可靠,则可以定义一个Prometheus记录规则,如果最近几秒/分钟(取决于Prometheus收集度量标准的频率)有任何变化,则其值应等于当前时间戳。否则规则的先前值。例如(未测试):

groups:

- name: last-update
  rules:

  - record: last-update
    expr: |
      timestamp(changes(up{job="prometheus"}[1m]) > 0)
        or
      last-update
Run Code Online (Sandbox Code Playgroud)

up{job="prometheus"}用指标选择器和1m至少与收集间隔一样长的间隔进行替换,最好是更长一些,以覆盖任何收集间隔抖动或遗漏的碎片。

然后,您将使用类似time() - last-updateGrafana 的表达式来获取自上次更改以来的时间跨度。您可以在任何类型的面板中使用它,而不必依赖面板为您选择最后一个值。

编辑: Prometheus 2.7.0版本(如果按照他们的6周发布时间表,大约在2-3周内就会发布)预期在2.7.0版本中提供的新功能之一是子查询支持。这意味着您无需借助记录规则即可实现后一种“更可靠”的解决方案。

如果我正确理解这一点,查询应该看起来像这样:

time() - max_over_time(timestamp(changes(up{job="prometheus"}[5m]) > 0)[24h:1m])
Run Code Online (Sandbox Code Playgroud)

但是,就像以前一样,这并不是一个特别有效的查询,尤其是对于大量序列而言。您可能还希望从中减去5分钟,然后将其限制clamp_min为非负值,以调整5分钟范围。


val*_*ala 6

foo_total如果增加不超过一天前,以下查询应返回自上次增加以来的持续时间(请1d参见查询):

time() - max_over_time(timestamp(changes(foo_total[5m]) > 0)[1d:1m])
Run Code Online (Sandbox Code Playgroud)

返回的持续时间的精确度是一分钟(参见1m查询)。该查询使用 Prometheus 子查询 - 有关详细信息,请参阅这些文档

PS 此查询也可以表示lag((changes(foo_total) > 0)[1d:1m])VictoriaMetrics。有关详细信息,请参阅lag() 文档

更新:VictoriaMetrics(我从事的项目)还支持tlast_change_over_time()函数,该函数返回输入时间序列最后一次更改的时间戳。例如,将返回最后一天时间序列tlast_change_over_time(foo_total[1d])最后一次更改的时间戳。foo_total