一年前给客户部署配置过grafana,告警配置也是用的原始的,客户在使用过程中只需要一些核心点信息,想要实现这个就需要用Grafana的自定义告警模板以及编辑邮件模板。

通知模板

模板信息的配置中查阅了相关资料,自己组装了一套,主要用于邮件标题,想要实现的效果如:“服务器: ***, ****, 内存使用率超过**告警”,告警事项这儿用alertname直接固定 比如配置的是内存超过90阈值就发邮件,那就把alertname设置成“内存使用率超过90告警”即可。重点是获取异常的服务器信息。
查阅相关资料后,编写代码如下:

{{ define "email.message" }}
{{- if gt (len .Alerts.Firing) 0 -}}
  服务器:{{ range $i, $alert := .Alerts.Firing }}
      {{ index $alert.Labels "instance" }},
    {{ end }}
    {{ range $i, $alert := .Alerts.Firing }}
      {{if eq $i 0 }}
        {{ index $alert.Labels "alertname" }}
      {{end}}
    {{ end }}
{{- end }}
{{- if gt (len .Alerts.Resolved) 0 -}}
  服务器:{{ range $i, $alert := .Alerts.Resolved }}
      {{ index $alert.Labels "instance" }},
    {{ end }}
    {{ range $i, $alert := .Alerts.Resolved }}
      {{if eq $i 0 }}
        {{ index $alert.Labels "alertname" }}
      {{end}}
    {{ end }}
{{- end }}
{{ end }}

在Contact points->Optional Email settings->Subject配置自定义模板名称

grafana 添加模版 grafana模板_服务器

代码编写完成后在旧版(9.1)上一直不行,后来grafana官方资料发现,告警规则中的查询表达式若是用的经典模式(Classic condition)在不能使用“$alert.Labels "instance"”获取服务器信息,变更告警规则为Reduce,发现可以收取到正确格式的相关邮件标题,然后进入下一步更改 邮件模板

邮件模板

邮件模板主要是根据客户需要展示具体事项、服务器和事项的当前值即可。

找到grafana的安装目录(默认:C:\Program Files\GrafanaLabs\grafana\public\emails\),打开
ng_alert_notification.html文件 按照要求注释更改部分html代码即可。部分代码片段如下:
 

{{ range .Labels.SortedPairs }}
  <tr style="vertical-align: top; padding: 0;" align="left">
    <td colspan="2" class="value" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 24px 0 0;" align="left" valign="top">
      {{if eq .Name "instance" }}
      <span class="value-heading" style="font-weight: bold;">服务器:</span> <span class="value-value" style="padding-left: 8px;">{{ .Value }}</span>
      {{else if eq .Name "alertname" }}
      <span class="value-heading" style="font-weight: bold;">事项:</span> <span class="value-value" style="padding-left: 8px;">{{ .Value }}</span>
      {{else}}

      {{end}}
    </td>
  </tr>
  {{ end }}
  {{ if gt (len .Annotations.SortedPairs) 0 }}
      <tr style="vertical-align: top; padding: 0;" align="left">
        <td colspan="2" class="annotations" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 24px 0 12px;" align="left" valign="top">
          {{ range .Annotations.SortedPairs }}
            {{if eq .Name "description" }}
            <p style="color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0 0 10px; padding: 0;" align="left"><span class="annotations-heading" style="font-weight: bold; text-transform: capitalize;">当前值:</span> <span class="annotations-value" style="padding-left: 8px;">{{ .Value }}</span></p>
            {{end}}
          {{ end }}
        </td>
      </tr>
  {{ end }}

此处针对当前值,9.1版本里的{{ .ValueString }}是一个字符串,本人对go语言不熟以及对对照官方给出的方法在这个模板html里无法解析出服务器信息,所以在告警里的annotations的Description里获取了当前值,代码用“{{ printf "%.2f" $values.B.Value }}”(当前值保留2位小数)。

收取的邮件效果如下

grafana 添加模版 grafana模板_服务器_02

重新在告警规则中的查询表达式中对表达式B使用Reduce,表达式C使用Classic condition配置阈值,发现邮件未按阈值进行邮件发送,且annotations的Description里的表达式也获取不到正确的值。查询官方资料( 具体链接:template-notifications/reference),发现最新版里有一个Values是KV,应该是可以解析出服务器信息和对应的value值。

下载安装完最新版(10.4.1),在配置告警时发现和9.1有明细的变化,

grafana 添加模版 grafana模板_grafana_03

直接配置完相关信息,发送邮件可以实现按阈值进行邮件发送,满足客户需要。后面再对新版本的邮件模板html进行改造

部分代码片段如下:

{{ __dangerouslyInjectHTML `<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]-->` }}
	<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
	  <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
		<tbody>
		  {{ if .Labels.SortedPairs }}
		  <!--<tr>
			<td align="left" class="txt" style="font-size:0px;padding:10px 25px;word-break:break-word;">
			  <div style="font-family: Inter, Helvetica, Arial; font-size: 13px; line-height: 150%; text-align: left; color: #000000;"><strong>Labels</strong></div>
			</td>
		  </tr>-->
		  <tr>
			<td align="left" class="txt" style="font-size:0px;padding:10px 25px;word-break:break-word;">
			  <table cellpadding="0" cellspacing="0" width="100%" border="0" style="color:#000000;font-family:Inter, Helvetica, Arial;font-size:13px;line-height:22px;table-layout:auto;width:100%;border:none;">
				<mj-raw>{{ range .Labels.SortedPairs }}</mj-raw>
				{{if eq .Name "instance" }}
				<tr>
				  <td>
					<strong>服务器</strong>
				  </td>
				  <td>{{ .Value }}</td>
				</tr>
				{{else if eq .Name "alertname" }}
				 <tr>
				  <td>
					<strong>事项</strong>
				  </td>
				  <td>{{ .Value }}</td>
				</tr>
				{{ else }}
				{{ end }}
				<mj-raw>{{ end }}</mj-raw>
				
				<mj-raw>{{ range $refID, $value := .Values }}</mj-raw>
				{{ if eq $refID "B" }}
				<tr>
				  <td>
					<strong>当前值</strong>
				  </td>
				  <td>{{ printf "%.2f" $value }}</td>
				</tr>
				{{ end }}
				<mj-raw>{{ end }}</mj-raw>
			  </table>
			</td>
		  </tr>
		  {{ end }}{{ if (without .Annotations.SortedPairs.Names "description" "summary") }}
		  <tr>
			<td align="left" class="txt" style="font-size:0px;padding:10px 25px;word-break:break-word;">
			  <div style="font-family: Inter, Helvetica, Arial; font-size: 13px; line-height: 150%; text-align: left; color: #000000;"><strong>Annotations</strong></div>
			</td>
		  </tr>
		  <tr>
			<td align="left" class="txt" style="font-size:0px;padding:10px 25px;word-break:break-word;">
			  <table cellpadding="0" cellspacing="0" width="100%" border="0" style="color:#000000;font-family:Inter, Helvetica, Arial;font-size:13px;line-height:22px;table-layout:auto;width:100%;border:none;">
				<mj-raw>{{ range .Annotations.SortedPairs }}</mj-raw>
				<mj-raw>{{ if and (ne .Name "description") (ne .Name "summary") }}</mj-raw>
				<tr>
				  <td>
					<strong>{{ .Name }}</strong>
				  </td>
				  <td>{{ .Value }}</td>
				</tr>
				<mj-raw>{{ end }}</mj-raw>
				<mj-raw>{{ end }}</mj-raw>
			  </table>
			</td>
		  </tr>
		  {{ end }}
		</tbody>
	  </table>
	</div>
{{ __dangerouslyInjectHTML `<!--[if mso | IE]></td></tr></table><![endif]-->` }}

邮件收取效果如图:

grafana 添加模版 grafana模板_ci_04

另外关于邮件里跳转链接的配置,在grafana的安装路径的grafana\conf下,打开defaults.ini文件找到“[server]”,编辑 domain = 192.168.**.**,这样就可以从邮件里直接跳转到相关的grafana页面。