我正在尝试使用 Prometheus 的
hwmon
和 Grafana 绘制服务器的温度图表。
与此相关的是
prometheus-node-exporter
提供的 2 个时间序列:
node_hwmon_temp_celsius
有实际温度;它有这样的标签:
{chip="platform_coretemp_0",sensor="temp1"}
node_hwmon_sensor_label
,它是具有名称的温度传感器的辅助时间序列(Prometheus 标签称为 label
):
{chip="platform_coretemp_0",sensor="temp1",label="core_0"}
在 https://github.com/prometheus/node_exporter/issues/631 上有这样的解释:
标签并非适用于所有传感器。如果所有传感器都有标签,您可以执行以下操作来加入它们:
node_hwmon_temp_celsius{...} * ignoring(label) group_left(label) node_hwmon_sensor_label
但我的一些传感器没有标签。在这种情况下,上面的 PromQL 查询没有帮助;在这种情况下,
group_left(label)
不会返回任何结果。
相反,我想编写一个始终存在
label
标签的温度查询,如果缺少 unknown-sensor-name
标签,则 defaults为
label
。
如何使用 PromQL 做到这一点?
我终于找到了一个解决方案(不确定是否是最佳的):
(
# For all sensors that have a name (label "label"), join them with `node_hwmon_sensor_label` to get that name.
(node_hwmon_temp_celsius * ignoring(label) group_left(label) node_hwmon_sensor_label)
or
# For all sensors that do NOT a name (label "label") in `node_hwmon_sensor_label`, assign them `label="unknown-sensor-name"`.
# `label_replace()` only adds the new label, it does not remove the old one.
(label_replace((node_hwmon_temp_celsius unless ignoring(label) node_hwmon_sensor_label), "label", "unknown-sensor-name", "", ".*"))
)
我是如何到达那里的:
label
的时间序列本质上相当于 SQL 中的 OUTER JOIN
;在 Google 上搜索 PromQL,我发现了问题 有没有办法在 PromQL 中执行“左外连接”之类的查询? 这解释了这是 PromQL 中的 unless
。label="unknown-sensor-name"
。我们可以使用 label_replace()
来做到这一点,这可能会令人困惑,它只是真正添加了一个新标签,而不会删除旧标签(如here所述)。我们可以将最后 2 个参数保留为 ""
,因为我们只添加一个常量字符串,因此我们可以匹配任何现有标签。or
将其与“如果所有传感器都有标签”系列联合起来。完成。
如果需要,我们还可以通过添加以下内容将其与计算机的主机名连接起来:
* on(instance) group_left(nodename) node_uname_info
这在 https://blog.ruanbekker.com/cheatsheets/prometheus/ 或 在 Prometheus 中将实例重新标记为主机名中进行了描述。
这样,在 Grafana 中,我们可以使用
{{nodename}} {{chip}} {{label}}
作为图表的图例。
Grafana 中的示例(显示
instance
而不是 nodename
):
只需将推荐的查询包装到 label_replace() 函数中即可:
label_replace(
node_hwmon_temp_celsius
* ignoring(label) group_left(label)
node_hwmon_sensor_label,
"label",
"unknown-sensor-name",
"label",
""
)
label_replace()
搜索缺失的 label
值,然后用 label="unknown-sensor-name"
替换它们。它不会更改现有的 label
值,因为它们与 label_replace()
最后一个参数中提供的空正则表达式不匹配。 Prometheus 自动将正则表达式锚定到字符串的开头和结尾,例如实际上它使用 ^$
正则表达式,它只匹配空字符串。
您可以利用
label_replace
允许您提供正则表达式匹配作为替换的要求,并且仅当它与空字符串匹配(即不存在标签)时才进行替换:
label_replace(
<your metric>,
<label>,
<default value>,
<label>,
"^$"
)
或者具体针对您的情况:
label_replace(
<your metric>,
"label",
"unknown-sensor-name",
"label",
"^$"
)
其中
^
是正则表达式中使用的特殊字符,表示字符串的开头,$
与字符串的结尾相同。
通过为缺失的标签添加“默认”值来处理此问题的更好方法。
relabelings
- sourceLabels:[__meta_xx_name]
targetLabel: label_name
- sourceLabels:[__meta_xx_name]
targetLabel: label_name
replacement: unknown
regex: ^$
如果面板变量因缺少此标签而受到影响,这也会很有帮助。