Sorting Alertmanager email templates in Go templating

1.9k views Asked by At

I'm trying to customize an Email template from AlertManager that uses a Go html template that prints a list of alerts using the following construct :

{{ range .Alerts.Firing }}

It gets inserted into the template like this :

func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
   ...
   data = n.tmpl.Data(receiverName(ctx), groupLabels(ctx), as...)
   ...
}

Alert being defined like this :

type Alert struct {
    Labels LabelSet `json:"labels"`

    Annotations LabelSet `json:"annotations"`

    StartsAt     time.Time `json:"startsAt,omitempty"`
    EndsAt       time.Time `json:"endsAt,omitempty"`
    GeneratorURL string    `json:"generatorURL"`
}

I would like to do the sorting on the StartsAt field.

I tried using the sort function but it wasn't available in the email template.

{{ range sort .Alerts.Firing }}

I'm getting

function \"sort\" not defined

Any ideas on how I can get it to sort on StartsAt ?

2

There are 2 answers

1
icza On BEST ANSWER

Sort the alerts before you pass it to template execution. It's easier, also a template should not alter the data it's destined to display.

Example:

type ByStart []*types.Alert

func (a ByStart) Len() int           { return len(a) }
func (a ByStart) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByStart) Less(i, j int) bool { return a[i].StartAt.Before(a[j].StartAt) }

func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
    ...
    sort.Sort(ByStart(as))
    data = n.tmpl.Data(receiverName(ctx), groupLabels(ctx), as...)
    ...
}

Edit:

Sorting functionality is not available from templates by default. You can register custom functions that can be called from templates, but this must be done prior to parsing the templates, and from Go code (not from the template text; see Template.Funcs()). This is so because templates must be statically analyzable, and knowing what custom functions are valid is key when parsing the template text.

Just from the template text, without the help of custom functions, you can't achieve this.

0
Emmanuel On

In that alertmanager email template I noticed this line :

  {{ range .Annotations.SortedPairs }}{{ .Name }} = {{ .Value }}<br />{{ end }}

So perhaps you could try:

{{ range .Alerts.Firing.Sorted }}