diff --git a/app/vmalert/README.md b/app/vmalert/README.md index b37fe3035..a5738f31c 100644 --- a/app/vmalert/README.md +++ b/app/vmalert/README.md @@ -199,15 +199,16 @@ It is allowed to use [Go templating](https://golang.org/pkg/text/template/) in a or execute expressions. The following variables are available in templating: -| Variable | Description | Example | -|------------------------------------|-----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------| -| $value or .Value | The current alert's value. Avoid using value in labels, it may cause unexpected issues. | {% raw %}"Number of connections is {{ $value }}{% endraw %} | -| $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|quotesEscape|queryEscape }}"{% 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 %} | +| Variable | Description | Example | +|------------------------------------|-----------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------| +| $value or .Value | The current alert's value. Avoid using value in labels, it may cause unexpected issues. | {% raw %}"Number of connections is {{ $value }}"{% endraw %} | +| $activeAt or .ActiveAt | The alert fire time. It a `time.Time` type so you can use its methods like {% raw %}`{{$activeAt.Unix}}`{% endraw %} | {% raw %}"http://vm-grafana.com/panelId=xx?from={{($activeAt.Add (parseDurationTime \"1h\")).Unix}}&to={{($activeAt.Add (parseDurationTime \"-1h\")).Unix}}"{% endraw %} | +| $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|quotesEscape|queryEscape }}"{% 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 %} | Additionally, `vmalert` provides some extra templating functions listed [here](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/app/vmalert/templates/template.go) diff --git a/app/vmalert/notifier/alert.go b/app/vmalert/notifier/alert.go index 88fc59544..a137b48e0 100644 --- a/app/vmalert/notifier/alert.go +++ b/app/vmalert/notifier/alert.go @@ -74,11 +74,12 @@ func (as AlertState) String() string { // AlertTplData is used to execute templating type AlertTplData struct { - Labels map[string]string - Value float64 - Expr string - AlertID uint64 - GroupID uint64 + Labels map[string]string + Value float64 + Expr string + AlertID uint64 + GroupID uint64 + ActiveAt time.Time } var tplHeaders = []string{ @@ -89,6 +90,7 @@ var tplHeaders = []string{ "{{ $externalURL := .ExternalURL }}", "{{ $alertID := .AlertID }}", "{{ $groupID := .GroupID }}", + "{{ $activeAt := .ActiveAt }}", } // ExecTemplate executes the Alert template for given @@ -96,7 +98,7 @@ 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} + tplData := AlertTplData{Value: a.Value, Labels: labels, Expr: a.Expr, AlertID: a.ID, GroupID: a.GroupID, ActiveAt: a.ActiveAt} 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 47a4a11bb..d08f60730 100644 --- a/app/vmalert/notifier/alert_test.go +++ b/app/vmalert/notifier/alert_test.go @@ -4,6 +4,7 @@ import ( "fmt" "reflect" "testing" + "time" "github.com/VictoriaMetrics/VictoriaMetrics/app/vmalert/datasource" "github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal" @@ -122,6 +123,52 @@ func TestAlert_ExecTemplate(t *testing.T) { "url": "/api/v1/alert?alertID=42&groupID=24", }, }, + { + name: "ActiveAt time", + alert: &Alert{ + ActiveAt: time.Date(2022, 8, 19, 20, 34, 58, 651387237, time.UTC), + }, + annotations: map[string]string{ + "diagram": "![](http://example.com?render={{$activeAt.Unix}}", + }, + expTpl: map[string]string{ + "diagram": "![](http://example.com?render=1660941298", + }, + }, + { + name: "ActiveAt time is nil", + alert: &Alert{}, + annotations: map[string]string{ + "default_time": "{{$activeAt}}", + }, + expTpl: map[string]string{ + "default_time": "0001-01-01 00:00:00 +0000 UTC", + }, + }, + { + name: "ActiveAt custome format", + alert: &Alert{ + ActiveAt: time.Date(2022, 8, 19, 20, 34, 58, 651387237, time.UTC), + }, + annotations: map[string]string{ + "fire_time": `{{$activeAt.Format "2006/01/02 15:04:05"}}`, + }, + expTpl: map[string]string{ + "fire_time": "2022/08/19 20:34:58", + }, + }, + { + name: "ActiveAt query range", + alert: &Alert{ + ActiveAt: time.Date(2022, 8, 19, 20, 34, 58, 651387237, time.UTC), + }, + annotations: map[string]string{ + "grafana_url": `vm-grafana.com?from={{($activeAt.Add (parseDurationTime "1h")).Unix}}&to={{($activeAt.Add (parseDurationTime "-1h")).Unix}}`, + }, + expTpl: map[string]string{ + "grafana_url": "vm-grafana.com?from=1660944898&to=1660937698", + }, + }, } qFn := func(q string) ([]datasource.Metric, error) { diff --git a/app/vmalert/templates/template.go b/app/vmalert/templates/template.go index e1f88b5b1..7635f37c4 100644 --- a/app/vmalert/templates/template.go +++ b/app/vmalert/templates/template.go @@ -255,6 +255,15 @@ func templateFuncs() textTpl.FuncMap { return d.Seconds(), nil }, + // same with parseDuration but returns a time.Duration + "parseDurationTime": func(s string) (time.Duration, error) { + d, err := promutils.ParseDuration(s) + if err != nil { + return 0, err + } + return d, nil + }, + /* Numbers */ // humanize converts given number to a human readable format diff --git a/docs/vmalert.md b/docs/vmalert.md index ef2c3769d..46db8bab4 100644 --- a/docs/vmalert.md +++ b/docs/vmalert.md @@ -203,15 +203,16 @@ It is allowed to use [Go templating](https://golang.org/pkg/text/template/) in a or execute expressions. The following variables are available in templating: -| Variable | Description | Example | -|------------------------------------|-----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------| -| $value or .Value | The current alert's value. Avoid using value in labels, it may cause unexpected issues. | {% raw %}"Number of connections is {{ $value }}{% endraw %} | -| $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|quotesEscape|queryEscape }}"{% 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 %} | +| Variable | Description | Example | +|------------------------------------|-----------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------| +| $value or .Value | The current alert's value. Avoid using value in labels, it may cause unexpected issues. | {% raw %}"Number of connections is {{ $value }}"{% endraw %} | +| $activeAt or .ActiveAt | The alert fire time. It a `time.Time` type so you can use its methods like {% raw %}`{{$activeAt.Unix}}`{% endraw %} | {% raw %}"http://vm-grafana.com/panelId=xx?from={{($activeAt.Add (parseDurationTime \"1h\")).Unix}}&to={{($activeAt.Add (parseDurationTime \"-1h\")).Unix}}"{% endraw %} | +| $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|quotesEscape|queryEscape }}"{% 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 %} | Additionally, `vmalert` provides some extra templating functions listed [here](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/app/vmalert/templates/template.go)