Skip to content

Commit

Permalink
Merge 631541d into 140c9e9
Browse files Browse the repository at this point in the history
  • Loading branch information
Nixolay committed Oct 27, 2020
2 parents 140c9e9 + 631541d commit 4df2c4f
Show file tree
Hide file tree
Showing 10 changed files with 305 additions and 107 deletions.
20 changes: 20 additions & 0 deletions api/dto/triggers.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"strconv"
"time"

"github.com/moira-alert/moira/templating"

"github.com/moira-alert/moira"
"github.com/moira-alert/moira/api"
"github.com/moira-alert/moira/api/middleware"
Expand Down Expand Up @@ -174,10 +176,12 @@ func (trigger *Trigger) Bind(request *http.Request) error {
return api.ErrInvalidRequestContent{ValidationError: fmt.Errorf("pattern \"*\" is not allowed to use")}
}
}

middleware.SetTimeSeriesNames(request, metricsDataNames)
if _, err := triggerExpression.Evaluate(); err != nil {
return err
}

return nil
}

Expand Down Expand Up @@ -312,6 +316,22 @@ func (*Trigger) Render(w http.ResponseWriter, r *http.Request) error {
return nil
}

func (trigger *Trigger) PopulatedDescription(events moira.NotificationEvents) error {
if trigger.Desc == nil {
return nil
}

templatingEvents := moira.NotificationEventsToTemplatingEvents(events)
description, err := templating.Populate(trigger.Name, *trigger.Desc, templatingEvents)
if err != nil {
return fmt.Errorf("you have an error in your Go template: %v", err)
}

*trigger.Desc = description

return nil
}

type TriggerCheck struct {
*moira.CheckData
TriggerID string `json:"trigger_id"`
Expand Down
43 changes: 24 additions & 19 deletions api/handler/trigger.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (

"github.com/go-chi/chi"
"github.com/go-chi/render"
"github.com/moira-alert/moira"
"github.com/moira-alert/moira/metric_source/local"
"github.com/moira-alert/moira/metric_source/remote"

Expand Down Expand Up @@ -54,16 +53,11 @@ func updateTrigger(writer http.ResponseWriter, request *http.Request) {
render.Render(writer, request, api.ErrorInternalServer(err)) //nolint
}

return
}

if trigger.Desc != nil {
triggerData := moira.TriggerData{Desc: *trigger.Desc, Name: trigger.Name}
if _, err := triggerData.GetPopulatedDescription(moira.NotificationEvents{}); err != nil {
render.Render(writer, request, api.ErrorRender( //nolint
fmt.Errorf("You have an error in your Go template: %v", err)))
return
if err := checkingTemplateFilling(request, *trigger); err != nil {
render.Render(writer, request, err)
}

return
}

timeSeriesNames := middleware.GetTimeSeriesNames(request)
Expand Down Expand Up @@ -92,28 +86,39 @@ func getTrigger(writer http.ResponseWriter, request *http.Request) {
if triggerID == "testlog" {
panic("Test for multi line logs")
}

trigger, err := controller.GetTrigger(database, triggerID)
if err != nil {
render.Render(writer, request, err) //nolint
return
}

if needToPopulate := middleware.GetPopulated(request); needToPopulate && trigger.Desc != nil {
triggerData := moira.TriggerData{Desc: *trigger.Desc, Name: trigger.Name}

eventsList, err := controller.GetTriggerEvents(database, triggerID, 0, 3)
if err != nil {
render.Render(writer, request, err) //nolint
}

*trigger.Desc, _ = triggerData.GetPopulatedDescription(eventsList.List)
if err := checkingTemplateFilling(request, *trigger); err != nil {
middleware.GetLoggerEntry(request).Warning(err)
}

if err := render.Render(writer, request, trigger); err != nil {
render.Render(writer, request, api.ErrorRender(err)) //nolint
}
}

func checkingTemplateFilling(request *http.Request, trigger dto.Trigger) *api.ErrorResponse {
if !middleware.GetPopulated(request) {
return nil
}

eventsList, err := controller.GetTriggerEvents(database, trigger.ID, 0, 3)
if err != nil {
return err
}

if err := trigger.PopulatedDescription(eventsList.List); err != nil {
return api.ErrorRender(err)
}

return nil
}

func getTriggerState(writer http.ResponseWriter, request *http.Request) {
triggerID := middleware.GetTriggerID(request)
triggerState, err := controller.GetTriggerLastCheck(database, triggerID)
Expand Down
9 changes: 9 additions & 0 deletions api/handler/triggers.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ func createTrigger(writer http.ResponseWriter, request *http.Request) {
}
return
}

if trigger.Desc != nil {
err := trigger.PopulatedDescription(moira.NotificationEvents{{}})
if err != nil {
render.Render(writer, request, api.ErrorRender(err))
return
}
}

timeSeriesNames := middleware.GetTimeSeriesNames(request)
response, err := controller.CreateTrigger(database, &trigger.TriggerModel, timeSeriesNames)
if err != nil {
Expand Down
66 changes: 24 additions & 42 deletions datatypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ package moira
import (
"bytes"
"fmt"
"html/template"
"math"
"sort"
"strconv"
"strings"
"time"

"github.com/moira-alert/moira/templating"
)

const (
Expand Down Expand Up @@ -106,21 +107,31 @@ func (event *NotificationEvent) CreateMessage(location *time.Location) string {
// NotificationEvents represents slice of NotificationEvent
type NotificationEvents []NotificationEvent

type templateData struct {
Trigger templateTrigger
Events []templateEvent
}
func (trigger *TriggerData) PopulatedDescription(events NotificationEvents) error {
description, err := templating.Populate(trigger.Name, trigger.Desc, NotificationEventsToTemplatingEvents(events))
if err != nil {
description = "Your description is using the wrong template. Since we were unable to populate your template with " +
"data, we return it so you can parse it.\n\n"+trigger.Desc
}

type templateEvent struct {
Metric string
MetricElements []string
Timestamp int64
Value *float64
State State
trigger.Desc = description

return err
}

type templateTrigger struct {
Name string `json:"name"`
func NotificationEventsToTemplatingEvents(events NotificationEvents) []templating.Event {
templatingEvents := make([]templating.Event, 0, len(events))
for _, event := range events {
templatingEvents = append(templatingEvents, templating.Event{
Metric: event.Metric,
MetricElements: strings.Split(event.Metric, "."),
Timestamp: event.Timestamp,
State: string(event.State),
Value: event.Value,
})
}

return templatingEvents
}

// TriggerData represents trigger object
Expand All @@ -135,35 +146,6 @@ type TriggerData struct {
Tags []string `json:"__notifier_trigger_tags"`
}

func (trigger TriggerData) GetPopulatedDescription(events NotificationEvents) (string, error) {
buffer := new(bytes.Buffer)
templateEvents := make([]templateEvent, 0, len(events))

for _, data := range events {
event := templateEvent{
Metric: data.Metric,
MetricElements: strings.Split(data.Metric, "."),
Timestamp: data.Timestamp,
State: data.State,
Value: data.Value,
}

templateEvents = append(templateEvents, event)
}

dataToExecute := templateData{
Trigger: templateTrigger{Name: trigger.Name},
Events: templateEvents,
}

triggerTemplate := template.Must(template.New("populate-description").Parse(trigger.Desc))
if err := triggerTemplate.Execute(buffer, dataToExecute); err != nil {
return "", err
}

return buffer.String(), nil
}

// GetTriggerURI gets frontUri and returns triggerUrl, returns empty string on selfcheck and test notifications
func (trigger TriggerData) GetTriggerURI(frontURI string) string {
if trigger.ID != "" {
Expand Down
42 changes: 0 additions & 42 deletions datatypes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,48 +246,6 @@ func TestTriggerData_GetTags(t *testing.T) {
})
}

func TestTriggerData_TemplateDescription(t *testing.T) {
Convey("Test templates", t, func() {
var trigger = TriggerData{Name: "TestName"}
trigger.Desc = "\n" +
"Trigger name: {{.Trigger.Name}}\n" +
"{{range $v := .Events }}\n" +
"Metric: {{$v.Metric}}\n" +
"MetricElements: {{$v.MetricElements}}\n" +
"Timestamp: {{$v.Timestamp}}\n" +
"Value: {{$v.Value}}\n" +
"State: {{$v.State}}\n" +
"{{end}}\n" +
"https://grafana.yourhost.com/some-dashboard{{ range $i, $v := .Events }}{{ if ne $i 0 }}&{{ else }}?{{ end }}var-host={{ $v.Metric }}{{ end }}\n"

var data = NotificationEvents{{Metric: "1"}, {Metric: "2"}}

Convey("Test nil data", func() {
expected, err := trigger.GetPopulatedDescription(nil)
So(err, ShouldBeNil)
So(`
Trigger name: TestName
https://grafana.yourhost.com/some-dashboard
`, ShouldResemble, expected)
})

Convey("Test data", func() {
expected, err := trigger.GetPopulatedDescription(data)
So(err, ShouldBeNil)
So("\nTrigger name: TestName\n\nMetric: 1\nMetricElements: [1]\nTimestamp: 0\nValue: <nil>\nState: \n\nMetric: 2\nMetricElements: [2]\nTimestamp: 0\nValue: <nil>\nState: \n\nhttps://grafana.yourhost.com/some-dashboard?var-host=1&var-host=2\n", ShouldResemble, expected)
})

Convey("Test description without templates", func() {
anotherText := "Another text"
trigger.Desc = anotherText
expected, err := trigger.GetPopulatedDescription(data)
So(err, ShouldBeNil)
So(anotherText, ShouldEqual, expected)
})
})
}

func TestScheduledNotification_GetKey(t *testing.T) {
Convey("Get key", t, func() {
notification := ScheduledNotification{
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,4 @@ require (
gopkg.in/yaml.v2 v2.3.0
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
honnef.co/go/tools v0.0.1-2020.1.5 // indirect
)
)
2 changes: 1 addition & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -956,4 +956,4 @@ modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
10 changes: 8 additions & 2 deletions notifier/notifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,13 @@ func (notifier *StandardNotifier) resend(pkg *NotificationPackage, reason string
}

func (notifier *StandardNotifier) runSender(sender moira.Sender, ch chan NotificationPackage) {
defer func() {
if err := recover(); err != nil {
notifier.logger.Warningf("Panic notifier: %v, ", err)
}
}()
defer notifier.waitGroup.Done()

for pkg := range ch {
plots, err := notifier.buildNotificationPackagePlots(pkg)
if err != nil {
Expand All @@ -167,9 +173,9 @@ func (notifier *StandardNotifier) runSender(sender moira.Sender, ch chan Notific
}
}

pkg.Trigger.Desc, err = pkg.Trigger.GetPopulatedDescription(pkg.Events)
err = pkg.Trigger.PopulatedDescription(pkg.Events)
if err != nil {
notifier.logger.Errorf("Error populate description: %v", err)
notifier.logger.Warningf("Error populate description:\n%v", err)
}

err = sender.SendEvents(pkg.Events, pkg.Contact, pkg.Trigger, plots, pkg.Throttled)
Expand Down

0 comments on commit 4df2c4f

Please sign in to comment.