From 27911ae179bc6c591212d77ca0a676d9705379fc Mon Sep 17 00:00:00 2001 From: kreedom <60944649+kreedom@users.noreply.github.com> Date: Mon, 18 May 2020 11:55:16 +0300 Subject: [PATCH] vmalert - add expr to variables, add escape functions (#495) * vmalert - add expr to variables, add escape functions Co-authored-by: kreedom --- app/vmalert/main.go | 2 +- app/vmalert/notifier/alert.go | 6 +++-- app/vmalert/notifier/alert_test.go | 26 +++++++++++++++++++--- app/vmalert/notifier/template_func.go | 6 +++++ app/vmalert/rule.go | 1 + app/vmalert/testdata/dir/rules0-good.rules | 1 + 6 files changed, 36 insertions(+), 6 deletions(-) diff --git a/app/vmalert/main.go b/app/vmalert/main.go index 9d71e8511a..0452f4c072 100644 --- a/app/vmalert/main.go +++ b/app/vmalert/main.go @@ -121,7 +121,7 @@ func main() { }() rh := &requestHandler{m: manager} - go httpserver.Serve(*httpListenAddr, (rh).handler) + go httpserver.Serve(*httpListenAddr, rh.handler) sig := procutil.WaitForSigterm() logger.Infof("service received signal %s", sig) diff --git a/app/vmalert/notifier/alert.go b/app/vmalert/notifier/alert.go index b883aa1933..b1cd05018e 100644 --- a/app/vmalert/notifier/alert.go +++ b/app/vmalert/notifier/alert.go @@ -18,6 +18,7 @@ type Alert struct { Annotations map[string]string State AlertState + Expr string Start time.Time End time.Time Value float64 @@ -52,14 +53,15 @@ func (as AlertState) String() string { type alertTplData struct { Labels map[string]string Value float64 + Expr string } -const tplHeader = `{{ $value := .Value }}{{ $labels := .Labels }}` +const tplHeader = `{{ $value := .Value }}{{ $labels := .Labels }}{{ $expr := .Expr }}` // ExecTemplate executes the Alert template for give // map of annotations. func (a *Alert) ExecTemplate(annotations map[string]string) (map[string]string, error) { - tplData := alertTplData{Value: a.Value, Labels: a.Labels} + tplData := alertTplData{Value: a.Value, Labels: a.Labels, Expr: a.Expr} return templateAnnotations(annotations, tplHeader, tplData) } diff --git a/app/vmalert/notifier/alert_test.go b/app/vmalert/notifier/alert_test.go index 9d7cc3608d..3583da05e0 100644 --- a/app/vmalert/notifier/alert_test.go +++ b/app/vmalert/notifier/alert_test.go @@ -1,22 +1,27 @@ package notifier import ( - "fmt" + "net/url" "testing" ) func TestAlert_ExecTemplate(t *testing.T) { + u, _ := url.Parse("https://victoriametrics.com/path") + InitTemplateFunc(u) testCases := []struct { + name string alert *Alert annotations map[string]string expTpl map[string]string }{ { + name: "empty-alert", alert: &Alert{}, annotations: map[string]string{}, expTpl: map[string]string{}, }, { + name: "no-template", alert: &Alert{ Value: 1e4, Labels: map[string]string{ @@ -27,6 +32,7 @@ func TestAlert_ExecTemplate(t *testing.T) { expTpl: map[string]string{}, }, { + name: "label-template", alert: &Alert{ Value: 1e4, Labels: map[string]string{ @@ -43,10 +49,24 @@ func TestAlert_ExecTemplate(t *testing.T) { "description": "It is 10000 connections for localhost", }, }, + { + name: "expression-template", + alert: &Alert{ + Expr: "vm_rows>0", + }, + annotations: map[string]string{ + "exprEscapedQuery": "{{ $expr|queryEscape }}", + "exprEscapedPath": "{{ $expr|pathEscape }}", + }, + expTpl: map[string]string{ + "exprEscapedQuery": "vm_rows%3E0", + "exprEscapedPath": "vm_rows%3E0", + }, + }, } - for i, tc := range testCases { - t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { tpl, err := tc.alert.ExecTemplate(tc.annotations) if err != nil { t.Fatal(err) diff --git a/app/vmalert/notifier/template_func.go b/app/vmalert/notifier/template_func.go index 45f5e349f4..88547d1a5b 100644 --- a/app/vmalert/notifier/template_func.go +++ b/app/vmalert/notifier/template_func.go @@ -142,6 +142,12 @@ func InitTemplateFunc(externalURL *url.URL) { "externalURL": func() string { return externalURL.String() }, + "pathEscape": func(u string) string { + return url.PathEscape(u) + }, + "queryEscape": func(q string) string { + return url.QueryEscape(q) + }, } } diff --git a/app/vmalert/rule.go b/app/vmalert/rule.go index bdb0d9134e..c604361cd9 100644 --- a/app/vmalert/rule.go +++ b/app/vmalert/rule.go @@ -152,6 +152,7 @@ func (r *Rule) newAlert(m datasource.Metric) (*notifier.Alert, error) { Labels: map[string]string{}, Value: m.Value, Start: time.Now(), + Expr: r.Expr, // TODO: support End time } for _, l := range m.Labels { diff --git a/app/vmalert/testdata/dir/rules0-good.rules b/app/vmalert/testdata/dir/rules0-good.rules index ec5b0bc9d2..1798580531 100644 --- a/app/vmalert/testdata/dir/rules0-good.rules +++ b/app/vmalert/testdata/dir/rules0-good.rules @@ -6,6 +6,7 @@ groups: expr: vm_rows > 0 labels: label: bar + expr: "{{ $expr|queryEscape }}" annotations: summary: "{{ $value|humanize }}" description: "{{$labels}}"