Transfer template functions into types+methods

This commit is contained in:
Fabian Reinartz 2015-11-30 18:00:38 +01:00
parent 7465e4abe5
commit 6dc397de5c
2 changed files with 117 additions and 55 deletions

View File

@ -1,14 +1,13 @@
{{ define "__alertmanager" }}AlertManager{{ end }} {{ define "__alertmanager" }}AlertManager{{ end }}
{{ define "__alertmanagerURL" }}{{ .ExternalURL }}/#/alerts?receiver={{ .Receiver }}{{ end }} {{ define "__alertmanagerURL" }}{{ .ExternalURL }}/#/alerts?receiver={{ .Receiver }}{{ end }}
{{ define "__subject" }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .GroupLabels.SortedPairs.Values | join " " }} {{ if gt (len .CommonLabels) (len .GroupLabels) }}({{ with .CommonLabels.Remove .GroupLabels.Names }}{{ .Values | join " " }}{{ end }}){{ end }}{{ end }}
{{ define "__subject" }}{{$dot := .}}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts | firing | len }}{{ end }}] {{ range .GroupLabels | sortedPairs }}{{ .Value }} {{ end }}{{ if gt (len .CommonLabels) (len .GroupLabels) }}({{ range .CommonLabels | sortedPairs }}{{ if eq "" (index $dot.GroupLabels .Name) }}{{ .Value }} {{ end }}{{ end }}){{ end }}{{ end }}
{{ define "__description" }}{{ end }} {{ define "__description" }}{{ end }}
{{ define "__text_alert_list" }}{{ range . }}Labels: {{ define "__text_alert_list" }}{{ range . }}Labels:
{{ range .Labels | sortedPairs }} - {{ .Name }} = {{ .Value }} {{ range .Labels.SortedPairs }} - {{ .Name }} = {{ .Value }}
{{ end }}Annotations: {{ end }}Annotations:
{{ range .Annotations | sortedPairs }} - {{ .Name }} = {{ .Value }} {{ range .Annotations.SortedPairs }} - {{ .Name }} = {{ .Value }}
{{ end}} {{ end}}
{{ end }}{{ end }} {{ end }}{{ end }}

View File

@ -94,14 +94,50 @@ var DefaultFuncs = FuncMap{
"toUpper": strings.ToUpper, "toUpper": strings.ToUpper,
"toLower": strings.ToLower, "toLower": strings.ToLower,
"title": strings.Title, "title": strings.Title,
// sortedPairs allows for in-order iteration of key/value pairs. // join is equal to strings.Join but inverts the argument order
"sortedPairs": func(m map[string]string) []Pair { // for easier pipelining in templates.
"join": func(sep string, s []string) string {
return strings.Join(s, sep)
},
}
// Pair is a key/value string pair.
type Pair struct {
Name, Value string
}
// Pairs is a list of key/value string pairs.
type Pairs []Pair
// Names returns a list of names of the pairs.
func (ps Pairs) Names() []string {
ns := make([]string, 0, len(ps))
for _, p := range ps {
ns = append(ns, p.Name)
}
return ns
}
// Values returns a list of values of the pairs.
func (ps Pairs) Values() []string {
vs := make([]string, 0, len(ps))
for _, p := range ps {
vs = append(vs, p.Value)
}
return vs
}
// KV is a set of key/value string pairs.
type KV map[string]string
// SortedPairs returns a sorted list of key/value pairs.
func (kv KV) SortedPairs() Pairs {
var ( var (
pairs = make([]Pair, 0, len(m)) pairs = make([]Pair, 0, len(kv))
keys = make([]string, 0, len(m)) keys = make([]string, 0, len(kv))
sortStart = 0 sortStart = 0
) )
for k := range m { for k := range kv {
if k == string(model.AlertNameLabel) { if k == string(model.AlertNameLabel) {
keys = append([]string{k}, keys...) keys = append([]string{k}, keys...)
sortStart = 1 sortStart = 1
@ -112,33 +148,35 @@ var DefaultFuncs = FuncMap{
sort.Strings(keys[sortStart:]) sort.Strings(keys[sortStart:])
for _, k := range keys { for _, k := range keys {
pairs = append(pairs, Pair{k, m[k]}) pairs = append(pairs, Pair{k, kv[k]})
} }
return pairs return pairs
},
"firing": func(alerts []Alert) []Alert {
res := []Alert{}
for _, a := range alerts {
if a.Status == string(model.AlertFiring) {
res = append(res, a)
}
}
return res
},
"resolved": func(alerts []Alert) []Alert {
res := []Alert{}
for _, a := range alerts {
if a.Status == string(model.AlertResolved) {
res = append(res, a)
}
}
return res
},
} }
// Pair is a key/value string pair. // Remove returns a copy of the key/value set without the given keys.
type Pair struct { func (kv KV) Remove(keys []string) KV {
Name, Value string keySet := make(map[string]struct{}, len(keys))
for _, k := range keys {
keySet[k] = struct{}{}
}
res := KV{}
for k, v := range kv {
if _, ok := keySet[k]; !ok {
res[k] = v
}
}
return res
}
// Names returns the names of the label names in the LabelSet.
func (kv KV) Names() []string {
return kv.SortedPairs().Names()
}
// Values returns a list of the values in the LabelSet.
func (kv KV) Values() []string {
return kv.SortedPairs().Values()
} }
// Data is the data passed to notification templates. // Data is the data passed to notification templates.
@ -148,11 +186,11 @@ type Pair struct {
type Data struct { type Data struct {
Receiver string Receiver string
Status string Status string
Alerts []Alert Alerts Alerts
GroupLabels map[string]string GroupLabels KV
CommonLabels map[string]string CommonLabels KV
CommonAnnotations map[string]string CommonAnnotations KV
ExternalURL string ExternalURL string
} }
@ -160,8 +198,33 @@ type Data struct {
// Alert holds one alert for notification templates. // Alert holds one alert for notification templates.
type Alert struct { type Alert struct {
Status string Status string
Labels map[string]string Labels KV
Annotations map[string]string Annotations KV
}
// Alerts is a list of Alert objects.
type Alerts []Alert
// Firing returns the subset of alerts that are firing.
func (as Alerts) Firing() []Alert {
res := []Alert{}
for _, a := range as {
if a.Status == string(model.AlertFiring) {
res = append(res, a)
}
}
return res
}
// Resolved returns the subset of alerts that are resolved.
func (as Alerts) Resolved() []Alert {
res := []Alert{}
for _, a := range as {
if a.Status == string(model.AlertResolved) {
res = append(res, a)
}
}
return res
} }
// Data assembles data for template expansion. // Data assembles data for template expansion.
@ -171,18 +234,18 @@ func (t *Template) Data(recv string, groupLabels model.LabelSet, as ...*types.Al
data := &Data{ data := &Data{
Receiver: strings.SplitN(recv, "/", 2)[0], Receiver: strings.SplitN(recv, "/", 2)[0],
Status: string(alerts.Status()), Status: string(alerts.Status()),
Alerts: make([]Alert, 0, len(alerts)), Alerts: make(Alerts, 0, len(alerts)),
GroupLabels: map[string]string{}, GroupLabels: KV{},
CommonLabels: map[string]string{}, CommonLabels: KV{},
CommonAnnotations: map[string]string{}, CommonAnnotations: KV{},
ExternalURL: t.ExternalURL.String(), ExternalURL: t.ExternalURL.String(),
} }
for _, a := range alerts { for _, a := range alerts {
alert := Alert{ alert := Alert{
Status: string(a.Status()), Status: string(a.Status()),
Labels: make(map[string]string, len(a.Labels)), Labels: make(KV, len(a.Labels)),
Annotations: make(map[string]string, len(a.Annotations)), Annotations: make(KV, len(a.Annotations)),
} }
for k, v := range a.Labels { for k, v := range a.Labels {
alert.Labels[string(k)] = string(v) alert.Labels[string(k)] = string(v)