diff --git a/app/vmalert/README.md b/app/vmalert/README.md index d5a49ac21..842fc42b6 100644 --- a/app/vmalert/README.md +++ b/app/vmalert/README.md @@ -213,7 +213,8 @@ The following variables are available in templating: | $labels or .Labels | The list of labels of the current alert. Use as ".Labels.". | {% raw %}Too high number of connections for {{ .Labels.instance }}{% endraw %} | | $alertID or .AlertID | The current alert's ID generated by vmalert. | {% raw %}Link: vmalert/alert?group_id={{.GroupID}}&alert_id={{.AlertID}}{% endraw %} | | $groupID or .GroupID | The current alert's group ID generated by vmalert. | {% raw %}Link: vmalert/alert?group_id={{.GroupID}}&alert_id={{.AlertID}}{% endraw %} | -| $expr or .Expr | Alert's expression. Can be used for generating links to Grafana or other systems. | {% raw %}/api/v1/query?query={{ $expr|queryEscape }}{% endraw %} | +| $expr or .Expr | Alert's expression. Can be used for generating links to Grafana or other systems. | {% raw %}/api/v1/query?query={{ $expr|queryEscape }}{% endraw %} | +| $for or .For | Alert's configured for param. | {% raw %}Number of connections is too high for more than {{ .For }}{% endraw %} | | $externalLabels or .ExternalLabels | List of labels configured via `-external.label` command-line flag. | {% raw %}Issues with {{ $labels.instance }} (datacenter-{{ $externalLabels.dc }}){% endraw %} | | $externalURL or .ExternalURL | URL configured via `-external.url` command-line flag. Used for cases when vmalert is hidden behind proxy. | {% raw %}Visit {{ $externalURL }} for more details{% endraw %} | diff --git a/app/vmalert/alerting.go b/app/vmalert/alerting.go index 18221c7d5..368785105 100644 --- a/app/vmalert/alerting.go +++ b/app/vmalert/alerting.go @@ -456,6 +456,7 @@ func (ar *AlertingRule) newAlert(m datasource.Metric, ls *labelSet, start time.T Value: m.Values[0], ActiveAt: start, Expr: ar.Expr, + For: ar.For, } a.Annotations, err = a.ExecTemplate(qFn, ls.origin, ar.Annotations) return a, err diff --git a/app/vmalert/notifier/alert.go b/app/vmalert/notifier/alert.go index fa9699048..35a68c54c 100644 --- a/app/vmalert/notifier/alert.go +++ b/app/vmalert/notifier/alert.go @@ -45,6 +45,8 @@ type Alert struct { ID uint64 // Restored is true if Alert was restored after restart Restored bool + // For defines for how long Alert needs to be active to become StateFiring + For time.Duration } // AlertState type indicates the Alert state @@ -80,6 +82,7 @@ type AlertTplData struct { AlertID uint64 GroupID uint64 ActiveAt time.Time + For time.Duration } var tplHeaders = []string{ @@ -91,6 +94,7 @@ var tplHeaders = []string{ "{{ $alertID := .AlertID }}", "{{ $groupID := .GroupID }}", "{{ $activeAt := .ActiveAt }}", + "{{ $for := .For }}", } // ExecTemplate executes the Alert template for given @@ -98,7 +102,15 @@ var tplHeaders = []string{ // Every alert could have a different datasource, so function // requires a queryFunction as an argument. func (a *Alert) ExecTemplate(q templates.QueryFn, labels, annotations map[string]string) (map[string]string, error) { - tplData := AlertTplData{Value: a.Value, Labels: labels, Expr: a.Expr, AlertID: a.ID, GroupID: a.GroupID, ActiveAt: a.ActiveAt} + tplData := AlertTplData{ + Value: a.Value, + Labels: labels, + Expr: a.Expr, + AlertID: a.ID, + GroupID: a.GroupID, + ActiveAt: a.ActiveAt, + For: a.For, + } tmpl, err := templates.GetWithFuncs(templates.FuncsWithQuery(q)) if err != nil { return nil, fmt.Errorf("error getting a template: %w", err) diff --git a/app/vmalert/notifier/alert_test.go b/app/vmalert/notifier/alert_test.go index 7032bceab..9999f6f42 100644 --- a/app/vmalert/notifier/alert_test.go +++ b/app/vmalert/notifier/alert_test.go @@ -54,14 +54,15 @@ func TestAlert_ExecTemplate(t *testing.T) { "job": "staging", "instance": "localhost", }, + For: 5 * time.Minute, }, annotations: map[string]string{ "summary": "Too high connection number for {{$labels.instance}} for job {{$labels.job}}", - "description": "It is {{ $value }} connections for {{$labels.instance}}", + "description": "It is {{ $value }} connections for {{$labels.instance}} for more than {{ .For }}", }, expTpl: map[string]string{ "summary": "Too high connection number for localhost for job staging", - "description": "It is 10000 connections for localhost", + "description": "It is 10000 connections for localhost for more than 5m0s", }, }, { @@ -152,7 +153,7 @@ func TestAlert_ExecTemplate(t *testing.T) { }, }, { - name: "ActiveAt custome format", + name: "ActiveAt custom format", alert: &Alert{ ActiveAt: time.Date(2022, 8, 19, 20, 34, 58, 651387237, time.UTC), }, diff --git a/app/vmalert/templates/template.go b/app/vmalert/templates/template.go index 9c35de1ab..faab29a94 100644 --- a/app/vmalert/templates/template.go +++ b/app/vmalert/templates/template.go @@ -361,7 +361,7 @@ func templateFuncs() textTpl.FuncMap { return fmt.Sprintf("%.4g%s", v, prefix), nil }, - // humanizeDuration converts given seconds to a human readable duration + // humanizeDuration converts given seconds to a human-readable duration "humanizeDuration": func(i interface{}) (string, error) { v, err := toFloat64(i) if err != nil { diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index eb4cbde1f..f0cb0e72a 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -14,6 +14,7 @@ The following tip changes can be tested by building VictoriaMetrics components f * [How to build vmctl](https://docs.victoriametrics.com/vmctl.html#how-to-build) ## tip +* FEATURE: [vmalert](https://docs.victoriametrics.com/vmalert.html): support `$for` or `.For` template variables in alert's annotations. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3246). * BUGFIX: [DataDog protocol parser](https://docs.victoriametrics.com/#how-to-send-data-from-datadog-agent): do not re-use `host` and `device` fields from the previously parsed messages if these fields are missing in the currently parsed message. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3432). diff --git a/docs/vmalert.md b/docs/vmalert.md index d1c890aaf..1c81a7921 100644 --- a/docs/vmalert.md +++ b/docs/vmalert.md @@ -217,7 +217,8 @@ The following variables are available in templating: | $labels or .Labels | The list of labels of the current alert. Use as ".Labels.". | {% raw %}Too high number of connections for {{ .Labels.instance }}{% endraw %} | | $alertID or .AlertID | The current alert's ID generated by vmalert. | {% raw %}Link: vmalert/alert?group_id={{.GroupID}}&alert_id={{.AlertID}}{% endraw %} | | $groupID or .GroupID | The current alert's group ID generated by vmalert. | {% raw %}Link: vmalert/alert?group_id={{.GroupID}}&alert_id={{.AlertID}}{% endraw %} | -| $expr or .Expr | Alert's expression. Can be used for generating links to Grafana or other systems. | {% raw %}/api/v1/query?query={{ $expr|queryEscape }}{% endraw %} | +| $expr or .Expr | Alert's expression. Can be used for generating links to Grafana or other systems. | {% raw %}/api/v1/query?query={{ $expr|queryEscape }}{% endraw %} | +| $for or .For | Alert's configured for param. | {% raw %}Number of connections is too high for more than {{ .For }}{% endraw %} | | $externalLabels or .ExternalLabels | List of labels configured via `-external.label` command-line flag. | {% raw %}Issues with {{ $labels.instance }} (datacenter-{{ $externalLabels.dc }}){% endraw %} | | $externalURL or .ExternalURL | URL configured via `-external.url` command-line flag. Used for cases when vmalert is hidden behind proxy. | {% raw %}Visit {{ $externalURL }} for more details{% endraw %} |