获取自上次普罗米修斯计数器增加以来经过的时间

get time that passed since the last increase of Prometheus counter

考虑一个普罗米修斯指标foo_total,它计算一个事件的发生总数foo,即只要提供的服务没有重新启动,该指标就会增加。

有什么方法可以获取自该指标上次增加以来的时间跨度(例如秒数)?我知道由于刮擦期,这个值肯定不是那么准确,但几分钟的准确度对我来说应该足够了。

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

下面是 Singlestat 面板的 JSON,它将显示上次更新 up{job="prometheus"} 指标的时间。这不完全是您要求的:这是最后一次,而不是自那以后的时间跨度;它仅用作 Singlestat 面板(即您不能获取该值并绘制它,因为它不是单个值);并且它只会显示仪表板时间范围内的更改。

底层查询是 timestamp(changes(up{job="prometheus"}[$__interval]) > 0) * 1000,因此查询基本上 return 所有在最后 $__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": ""
}

如果你想让它更可靠,你可以定义一个 Prometheus 记录规则,如果最近几次 seconds/minutes 有任何变化(取决于频率),该规则的值等于当前时间戳Prometheus 收集指标)或规则的先前值,否则。例如。 (未测试):

groups:

- name: last-update
  rules:

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

up{job="prometheus"} 替换为您的指标选择器,并将 1m 替换为至少与您的收集间隔一样长并且理想情况下更长的间隔,以涵盖任何收集间隔抖动或错过了擦伤)。

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

编辑: Prometheus 2.7.0 版本中预期的新功能之一(如果他们保持 6 周的发布时间,预计将在 2-3 周内发布时间表)是 subquery support。这意味着您应该能够在没有记录规则帮助的情况下实施后者 "more reliable" 解决方案。

如果我理解正确,查询应该如下所示:

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

但是,和以前一样,这不是一个特别有效的查询,尤其是对于大量系列。您可能还想从中减去 5 分钟,并使用 clamp_min 将其限制为非负值,以针对 5 分钟范围进行调整。

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

time() - max_over_time(timestamp(changes(foo_total[5m]) > 0)[1d:1m])

returned 持续时间的准确性为一分钟(请参阅查询中的 1m)。该查询使用 Prometheus 子查询 - 有关详细信息,请参阅 these docs

P.S。这个查询也可以用VictoriaMetrics. See lag() docs中的lag((changes(foo_total) > 0)[1d:1m])来表示,详见