如何以编程方式访问Grafana Contact Point的.ValueString数据?
配置环境
针对配置为Slack的Contact Point,其「Text Body」字段内容如下:
{{ if eq .Status "firing" }} Type: {{ .CommonLabels.type }} {{ range .Alerts }} Status: {{ .Status }} {{ range .Labels.SortedPairs }} {{ .Name }}: {{ .Value }} {{ end }} {{ .ValueString }} DashboardURL: {{ .DashboardURL }} {{ end }} {{ else }} Stabilized threshhold: {{ .CommonLabels.threshold }} type: {{ .CommonLabels.type }} {{ end }}
上述模板运行正常,但存在一个问题:{{ .ValueString }}输出的内容包含大量有效数据,但目前只能以字符串形式获取,示例输出如下:
"[ metric='twinkie_product_collection Rate' labels={job=twinkie_product_collection, types=runRate} value=1.1111111111111112 ], [ metric='concert_ticket_collection Rate' labels={job=concert_ticket_collection, types=runRate} value=1.1111111111111112 ]"
这个字符串格式不够规整,希望能像访问.Labels数据(如下代码所示)那样,以更细粒度的方式提取metric、types、value等数据并格式化展示:
{{ range .Labels.SortedPairs }} {{ .Name }}: {{ .Value }} {{ end }}
查过官方文档后发现,Alert对象上除了.Labels,只有.Annotations是键值对类型,但按同样方式访问时没有数据。核心问题是:如何以编程方式访问并展示{{ .ValueString }}中的数据?
方案1:直接访问原始评估数据(推荐)
Grafana的Alert实例中自带结构化的指标评估数据,存储在.Evaluations字段中,完全不需要解析ValueString这个格式化后的字符串。你可以直接遍历该字段提取所需信息:
修改模板中对应部分为:
{{ if eq .Status "firing" }} Type: {{ .CommonLabels.type }} {{ range .Alerts }} Status: {{ .Status }} {{ range .Labels.SortedPairs }} {{ .Name }}: {{ .Value }} {{ end }} {{/* 替换原有的 .ValueString 为以下代码 */}} {{ range .Evaluations }} Metric: {{ .Metric }} {{ range .Labels.SortedPairs }} {{ .Name }}: {{ .Value }} {{ end }} Value: {{ .Value }} --- {{ end }} DashboardURL: {{ .DashboardURL }} {{ end }} {{ else }} Stabilized threshhold: {{ .CommonLabels.threshold }} type: {{ .CommonLabels.type }} {{ end }}
这样就能以和.Labels一致的结构化方式访问每个指标的metric名称、标签和数值,输出格式更规整,也避免了解析字符串的潜在问题。
方案2:正则解析ValueString(备选)
如果你的Grafana版本不支持.Evaluations字段,可以通过Go模板的正则函数解析ValueString的内容:
首先在模板开头定义一个可复用的解析片段:
{{ define "parseValueString" }} {{ $rawStr := trim . "[]\"" }} {{ range split $rawStr "],[" }} {{ $entry := trim . " " }} {{/* 提取metric名称 */}} {{ $metric := index (regexp.MustCompile(`metric='([^']+)'`).FindStringSubmatch $entry) 1 }} {{/* 提取标签部分 */}} {{ $labelsRaw := index (regexp.MustCompile(`labels=\{([^}]+)\}`).FindStringSubmatch $entry) 1 }} {{/* 提取数值 */}} {{ $value := index (regexp.MustCompile(`value=([\d.]+)`).FindStringSubmatch $entry) 1 }} Metric: {{ $metric }} {{ range split $labelsRaw ", " }} {{ $kv := split . "=" }} {{ index $kv 0 }}: {{ index $kv 1 }} {{ end }} Value: {{ $value }} --- {{ end }} {{ end }}
然后在模板中调用该片段替换原有的{{ .ValueString }}:
{{ template "parseValueString" .ValueString }}
注意:该方案依赖Grafana支持的模板函数(regexp.MustCompile、split、trim等),不同版本的函数支持可能有差异,使用前需确认你的Grafana版本兼容。
内容的提问来源于stack exchange,提问作者Cumulo Nimbus

