diff --git a/CHANGELOG.md b/CHANGELOG.md index 33d84e4b6..0547ac640 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,7 @@ For example, let's say we want to store all data that triggered an alert in Infl - [#426](https://github.com/influxdata/kapacitor/issues/426): Add `skip-format` query parameter to the `GET /task` endpoint so that returned TICKscript content is left unmodified from the user input. - [#388](https://github.com/influxdata/kapacitor/issues/388): The duration of an alert is now tracked and exposed as part of the alert data as well as can be set as a field via `.durationField('duration')`. - [#486](https://github.com/influxdata/kapacitor/pull/486): Default config file location. +- [#461](https://github.com/influxdata/kapacitor/pull/461): Make Alerta `event` property configurable. ### Bugfixes diff --git a/alert.go b/alert.go index 4cf828245..4650e748c 100644 --- a/alert.go +++ b/alert.go @@ -232,6 +232,10 @@ func newAlertNode(et *ExecutingTask, n *pipeline.AlertNode, l *log.Logger) (an * if err != nil { return nil, err } + evtmpl, err := text.New("event").Parse(alerta.Event) + if err != nil { + return nil, err + } etmpl, err := text.New("environment").Parse(alerta.Environment) if err != nil { return nil, err @@ -247,6 +251,7 @@ func newAlertNode(et *ExecutingTask, n *pipeline.AlertNode, l *log.Logger) (an * ai := alertaHandler{ AlertaHandler: alerta, resourceTmpl: rtmpl, + eventTmpl: evtmpl, environmentTmpl: etmpl, groupTmpl: gtmpl, valueTmpl: vtmpl, @@ -873,6 +878,7 @@ type alertaHandler struct { *pipeline.AlertaHandler resourceTmpl *text.Template + eventTmpl *text.Template environmentTmpl *text.Template valueTmpl *text.Template groupTmpl *text.Template @@ -907,6 +913,22 @@ func (a *AlertNode) handleAlerta(alerta alertaHandler, ad *AlertData) { resource := buf.String() buf.Reset() + type eventData struct { + idInfo + ID string + } + data := eventData{ + idInfo: ad.info.messageInfo.idInfo, + ID: ad.ID, + } + err = alerta.eventTmpl.Execute(&buf, data) + if err != nil { + a.logger.Printf("E! failed to evaluate Alerta Event template %s", alerta.Event) + return + } + event := buf.String() + buf.Reset() + err = alerta.environmentTmpl.Execute(&buf, ad.info) if err != nil { a.logger.Printf("E! failed to evaluate Alerta Environment template %s", alerta.Environment) @@ -938,7 +960,7 @@ func (a *AlertNode) handleAlerta(alerta alertaHandler, ad *AlertData) { err = a.et.tm.AlertaService.Alert( alerta.Token, resource, - ad.ID, + event, environment, severity, group, diff --git a/integrations/streamer_test.go b/integrations/streamer_test.go index 7777d6311..f14e60ca3 100644 --- a/integrations/streamer_test.go +++ b/integrations/streamer_test.go @@ -2707,6 +2707,9 @@ func TestStream_AlertAlerta(t *testing.T) { if exp := "cpu"; pd.Resource != exp { t.Errorf("unexpected resource got %s exp %s", pd.Resource, exp) } + if exp := "serverA"; pd.Event != exp { + t.Errorf("unexpected event got %s exp %s", pd.Event, exp) + } if exp := "production"; pd.Environment != exp { t.Errorf("unexpected environment got %s exp %s", pd.Environment, exp) } @@ -2726,9 +2729,12 @@ func TestStream_AlertAlerta(t *testing.T) { if exp := "/alert?api-key=anothertesttoken"; r.URL.String() != exp { t.Errorf("unexpected url got %s exp %s", r.URL.String(), exp) } - if exp := "resource: cpu"; pd.Resource != exp { + if exp := "resource: serverA"; pd.Resource != exp { t.Errorf("unexpected resource got %s exp %s", pd.Resource, exp) } + if exp := "event: TestStream_Alert"; pd.Event != exp { + t.Errorf("unexpected event got %s exp %s", pd.Event, exp) + } if exp := "serverA"; pd.Environment != exp { t.Errorf("unexpected environment got %s exp %s", pd.Environment, exp) } @@ -2745,9 +2751,6 @@ func TestStream_AlertAlerta(t *testing.T) { t.Errorf("unexpected origin got %s exp %s", pd.Origin, exp) } } - if exp := "serverA"; pd.Event != exp { - t.Errorf("unexpected event got %s exp %s", pd.Event, exp) - } if exp := "kapacitor/cpu/serverA is CRITICAL @1971-01-01 00:00:10 +0000 UTC"; pd.Text != exp { t.Errorf("unexpected text got %s exp %s", pd.Text, exp) } @@ -2775,7 +2778,8 @@ stream .environment('production') .alerta() .token('anothertesttoken') - .resource('resource: {{ .Name }}') + .resource('resource: {{ index .Tags "host" }}') + .event('event: {{ .TaskName }}') .environment('{{ index .Tags "host" }}') .origin('override') .group('{{ .ID }}') diff --git a/pipeline/alert.go b/pipeline/alert.go index 8e2c9cf72..489d2091a 100644 --- a/pipeline/alert.go +++ b/pipeline/alert.go @@ -751,6 +751,7 @@ func (a *AlertNode) Alerta() *AlertaHandler { alerta := &AlertaHandler{ AlertNode: a, Resource: defaultAlertaResource, + Event: defaultAlertaEvent, Group: defaultAlertaGroup, } a.AlertaHandlers = append(a.AlertaHandlers, alerta) @@ -758,6 +759,7 @@ func (a *AlertNode) Alerta() *AlertaHandler { } const defaultAlertaResource = "{{ .Name }}" +const defaultAlertaEvent = "{{ .ID }}" const defaultAlertaGroup = "{{ .Group }}" // tick:embedded:AlertNode.Alerta @@ -773,6 +775,11 @@ type AlertaHandler struct { // Default: {{ .Name }} Resource string + // Alerta event. + // Can be a template and has access to the same data as the idInfo property. + // Default: {{ .ID }} + Event string + // Alerta environment. // Can be a template and has access to the same data as the AlertNode.Details property. // Defaut is set from the configuration.