Skip to content

Commit

Permalink
feat: Add templates to trigger description #484
Browse files Browse the repository at this point in the history
* Added templates to trigger description
* Added presentation of trigger description in non-editing for api

Closed #484
  • Loading branch information
SantFlamel authored and RooNix committed Feb 14, 2020
1 parent e411f20 commit ae2adaf
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 1 deletion.
25 changes: 24 additions & 1 deletion api/handler/trigger.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ 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 All @@ -20,7 +21,7 @@ import (
func trigger(router chi.Router) {
router.Use(middleware.TriggerContext)
router.Put("/", updateTrigger)
router.Get("/", getTrigger)
router.With(middleware.TriggerContext, middleware.Populate(false)).Get("/", getTrigger)
router.Delete("/", removeTrigger)
router.Get("/state", getTriggerState)
router.Route("/throttling", func(router chi.Router) {
Expand Down Expand Up @@ -79,11 +80,33 @@ 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)
return
}

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

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

desc, errPopulate := triggerData.PopulateDescription(eventsList.List)
if err != nil {
render.Render(writer, request, api.ErrorRender(errPopulate))
}

*trigger.Desc = desc
}

if err := render.Render(writer, request, trigger); err != nil {
render.Render(writer, request, api.ErrorRender(err))
}
Expand Down
15 changes: 15 additions & 0 deletions api/middleware/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,21 @@ func Paginate(defaultPage, defaultSize int64) func(next http.Handler) http.Handl
}
}

// Populate gets bool value populate from URI query and set it to request context. If query has not values sets given values
func Populate(defaultPopulated bool) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
populate, err := strconv.ParseBool(request.URL.Query().Get("populated"))
if err != nil {
populate = defaultPopulated
}

ctxTemplate := context.WithValue(request.Context(), populateKey, populate)
next.ServeHTTP(writer, request.WithContext(ctxTemplate))
})
}
}

// DateRange gets from and to values from URI query and set it to request context. If query has not values sets given values
func DateRange(defaultFrom, defaultTo string) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
Expand Down
6 changes: 6 additions & 0 deletions api/middleware/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ var (
databaseKey ContextKey = "database"
searcherKey ContextKey = "searcher"
triggerIDKey ContextKey = "triggerID"
populateKey ContextKey = "populated"
contactIDKey ContextKey = "contactID"
tagKey ContextKey = "tag"
subscriptionIDKey ContextKey = "subscriptionID"
Expand Down Expand Up @@ -46,6 +47,11 @@ func GetTriggerID(request *http.Request) string {
return request.Context().Value(triggerIDKey).(string)
}

// GetTemplated get populate bool from request context, which was sets in TriggerContext middleware
func GetTemplated(request *http.Request) bool {
return request.Context().Value(populateKey).(bool)
}

// GetTag gets tag string from request context, which was sets in TagContext middleware
func GetTag(request *http.Request) string {
return request.Context().Value(tagKey).(string)
Expand Down
48 changes: 48 additions & 0 deletions datatypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"math"
"strconv"
"strings"
"text/template"
"time"
)

Expand Down Expand Up @@ -103,6 +104,23 @@ func (event *NotificationEvent) CreateMessage(location *time.Location) string {
// NotificationEvents represents slice of NotificationEvent
type NotificationEvents []NotificationEvent

type templateData struct {
Trigger templateTrigger
Events []templateEvent
}

type templateEvent struct {
Metric string
MetricElements []string
Timestamp int64
Value *float64
State State
}

type templateTrigger struct {
Name string `json:"name"`
}

// TriggerData represents trigger object
type TriggerData struct {
ID string `json:"id"`
Expand All @@ -115,6 +133,36 @@ type TriggerData struct {
Tags []string `json:"__notifier_trigger_tags"`
}

func (trigger TriggerData) PopulateDescription(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,
}

if data.Value != nil {
event.Value = data.Value
}

templateEvents = append(templateEvents, event)
}

triggerTemplate := template.Must(template.New("populate-description").Parse(trigger.Desc))
if err := triggerTemplate.Execute(buffer, templateData{
Trigger: templateTrigger{Name: trigger.Name},
Events: templateEvents,
}); err != nil {
return trigger.Desc, 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
59 changes: 59 additions & 0 deletions datatypes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,65 @@ 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.PopulateDescription(nil)
So(err, ShouldBeNil)
So(`
Trigger name: TestName
https://grafana.yourhost.com/some-dashboard
`, ShouldResemble, expected)
})

Convey("Test data", func() {
expected, err := trigger.PopulateDescription(data)
So(err, ShouldBeNil)
So("\n"+
"Trigger name: TestName\n"+
"\n"+
"Metric: 1\n"+
"MetricElements: [1]\n"+
"Timestamp: 0\n"+
"Value: <nil>\n"+
"State: \n"+
"\n"+
"Metric: 2\n"+
"MetricElements: [2]\n"+
"Timestamp: 0\n"+
"Value: <nil>\n"+
"State: \n"+
"\n"+
"https://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.PopulateDescription(data)
So(err, ShouldBeNil)
So(anotherText, ShouldEqual, expected)
})
})
}

func TestScheduledNotification_GetKey(t *testing.T) {
Convey("Get key", t, func() {
notification := ScheduledNotification{
Expand Down
6 changes: 6 additions & 0 deletions notifier/notifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,12 @@ func (notifier *StandardNotifier) runSender(sender moira.Sender, ch chan Notific
notifier.logger.Errorf(buildErr)
}
}

desc, err := pkg.Trigger.PopulateDescription(pkg.Events)
if err == nil {
pkg.Trigger.Desc = desc
}

err = sender.SendEvents(pkg.Events, pkg.Contact, pkg.Trigger, plot, pkg.Throttled)
if err == nil {
if metric, found := notifier.metrics.SendersOkMetrics.GetRegisteredMeter(pkg.Contact.Type); found {
Expand Down

0 comments on commit ae2adaf

Please sign in to comment.