fix(api): use slices for labels instead of maps

This commit is contained in:
Łukasz Mierzwa
2021-10-29 13:14:35 +01:00
committed by Łukasz Mierzwa
parent 7d24a7ece0
commit 8f7cca40cc
20 changed files with 746 additions and 506 deletions

View File

@@ -141,14 +141,14 @@ func resolveLabelValue(name, value string) string {
}
func getGroupLabel(group *models.APIAlertGroup, label string) string {
if v, found := group.Labels[label]; found {
return resolveLabelValue(label, v)
if v := group.Labels.Get(label); v != nil {
return resolveLabelValue(label, v.Value)
}
if v, found := group.Shared.Labels[label]; found {
return resolveLabelValue(label, v)
if v := group.Shared.Labels.Get(label); v != nil {
return resolveLabelValue(label, v.Value)
}
if v, found := group.Alerts[0].Labels[label]; found {
return resolveLabelValue(label, v)
if v := group.Alerts[0].Labels.Get(label); v != nil {
return resolveLabelValue(label, v.Value)
}
return ""
}
@@ -283,14 +283,14 @@ func autoGridLabel(dedupedAlerts []models.AlertGroup) string {
for _, ag := range dedupedAlerts {
alertsCount += ag.Alerts.Len()
for _, alert := range ag.Alerts {
for key, val := range alert.Labels {
if _, ok := labelToAlertCount[key]; !ok {
labelToAlertCount[key] = map[string]int{}
for _, l := range alert.Labels {
if _, ok := labelToAlertCount[l.Name]; !ok {
labelToAlertCount[l.Name] = map[string]int{}
}
if _, ok := labelToAlertCount[key][val]; !ok {
labelToAlertCount[key][val] = 0
if _, ok := labelToAlertCount[l.Name][l.Value]; !ok {
labelToAlertCount[l.Name][l.Value] = 0
}
labelToAlertCount[key][val]++
labelToAlertCount[l.Name][l.Value]++
}
}
}

View File

@@ -6,6 +6,7 @@ import (
"net/http"
"net/http/httptest"
"reflect"
"strings"
"testing"
"time"
@@ -18,7 +19,7 @@ import (
)
type groupTest struct {
labels map[string]string
labels models.Labels
receiver string
alerts []models.Alert
id string
@@ -28,8 +29,8 @@ type groupTest struct {
var groupTests = []groupTest{
{
receiver: "by-name",
labels: map[string]string{
"alertname": "Memory_Usage_Too_High",
labels: models.Labels{
{Name: "alertname", Value: "Memory_Usage_Too_High"},
},
alerts: []models.Alert{
{
@@ -38,10 +39,10 @@ var groupTests = []groupTest{
models.Annotation{Visible: true, Name: "alert", Value: "Memory usage exceeding threshold"},
models.Annotation{Visible: true, Name: "dashboard", Value: "http://localhost/dashboard.html", IsLink: true},
},
Labels: map[string]string{
"cluster": "prod",
"instance": "server2",
"job": "node_exporter",
Labels: models.Labels{
{Name: "cluster", Value: "prod"},
{Name: "instance", Value: "server2"},
{Name: "job", Value: "node_exporter"},
},
State: models.AlertStateActive,
Alertmanager: []models.AlertmanagerInstance{
@@ -64,9 +65,9 @@ var groupTests = []groupTest{
},
{
receiver: "by-cluster-service",
labels: map[string]string{
"alertname": "Memory_Usage_Too_High",
"cluster": "prod",
labels: models.Labels{
{Name: "alertname", Value: "Memory_Usage_Too_High"},
{Name: "cluster", Value: "prod"},
},
alerts: []models.Alert{
{
@@ -83,9 +84,9 @@ var groupTests = []groupTest{
SilencedBy: []string{},
},
},
Labels: map[string]string{
"instance": "server2",
"job": "node_exporter",
Labels: models.Labels{
{Name: "instance", Value: "server2"},
{Name: "job", Value: "node_exporter"},
},
State: models.AlertStateActive,
Receiver: "by-cluster-service",
@@ -100,9 +101,9 @@ var groupTests = []groupTest{
},
{
receiver: "by-cluster-service",
labels: map[string]string{
"alertname": "Host_Down",
"cluster": "staging",
labels: models.Labels{
{Name: "alertname", Value: "Host_Down"},
{Name: "cluster", Value: "staging"},
},
alerts: []models.Alert{
{
@@ -116,9 +117,9 @@ var groupTests = []groupTest{
SilencedBy: []string{},
},
},
Labels: map[string]string{
"instance": "server3",
"ip": "127.0.0.3",
Labels: models.Labels{
{Name: "instance", Value: "server3"},
{Name: "ip", Value: "127.0.0.3"},
},
State: models.AlertStateActive,
Receiver: "by-cluster-service",
@@ -133,9 +134,9 @@ var groupTests = []groupTest{
SilencedBy: []string{},
},
},
Labels: map[string]string{
"instance": "server4",
"ip": "127.0.0.4",
Labels: models.Labels{
{Name: "instance", Value: "server4"},
{Name: "ip", Value: "127.0.0.4"},
},
State: models.AlertStateActive,
Receiver: "by-cluster-service",
@@ -150,9 +151,9 @@ var groupTests = []groupTest{
SilencedBy: []string{},
},
},
Labels: map[string]string{
"instance": "server5",
"ip": "127.0.0.5",
Labels: models.Labels{
{Name: "instance", Value: "server5"},
{Name: "ip", Value: "127.0.0.5"},
},
State: models.AlertStateActive,
Receiver: "by-cluster-service",
@@ -167,9 +168,9 @@ var groupTests = []groupTest{
},
{
receiver: "by-cluster-service",
labels: map[string]string{
"alertname": "Host_Down",
"cluster": "dev",
labels: models.Labels{
{Name: "alertname", Value: "Host_Down"},
{Name: "cluster", Value: "dev"},
},
alerts: []models.Alert{
{
@@ -183,9 +184,9 @@ var groupTests = []groupTest{
SilencedBy: []string{"168f139d-77e4-41d6-afb5-8fe2cfd0cc9d"},
},
},
Labels: map[string]string{
"instance": "server6",
"ip": "127.0.0.6",
Labels: models.Labels{
{Name: "instance", Value: "server6"},
{Name: "ip", Value: "127.0.0.6"},
},
State: models.AlertStateSuppressed,
Receiver: "by-cluster-service",
@@ -201,9 +202,9 @@ var groupTests = []groupTest{
SilencedBy: []string{"168f139d-77e4-41d6-afb5-8fe2cfd0cc9d", "378eaa69-097d-41c4-a8c2-fe6568c3abfc"},
},
},
Labels: map[string]string{
"instance": "server7",
"ip": "127.0.0.7",
Labels: models.Labels{
{Name: "instance", Value: "server7"},
{Name: "ip", Value: "127.0.0.7"},
},
State: models.AlertStateSuppressed,
Receiver: "by-cluster-service",
@@ -219,9 +220,9 @@ var groupTests = []groupTest{
SilencedBy: []string{"168f139d-77e4-41d6-afb5-8fe2cfd0cc9d"},
},
},
Labels: map[string]string{
"instance": "server8",
"ip": "127.0.0.8",
Labels: models.Labels{
{Name: "instance", Value: "server8"},
{Name: "ip", Value: "127.0.0.8"},
},
State: models.AlertStateSuppressed,
Receiver: "by-cluster-service",
@@ -236,8 +237,8 @@ var groupTests = []groupTest{
},
{
receiver: "by-name",
labels: map[string]string{
"alertname": "Host_Down",
labels: models.Labels{
{Name: "alertname", Value: "Host_Down"},
},
alerts: []models.Alert{
{
@@ -245,10 +246,10 @@ var groupTests = []groupTest{
Annotations: models.Annotations{
models.Annotation{Visible: true, Name: "url", Value: "http://localhost/example.html", IsLink: true},
},
Labels: map[string]string{
"cluster": "prod",
"instance": "server1",
"ip": "127.0.0.1",
Labels: models.Labels{
{Name: "cluster", Value: "prod"},
{Name: "instance", Value: "server1"},
{Name: "ip", Value: "127.0.0.1"},
},
State: models.AlertStateActive,
Alertmanager: []models.AlertmanagerInstance{
@@ -264,10 +265,10 @@ var groupTests = []groupTest{
{
StartsAt: time.Date(2019, time.January, 1, 0, 1, 0, 0, time.UTC),
Annotations: models.Annotations{},
Labels: map[string]string{
"cluster": "prod",
"instance": "server2",
"ip": "127.0.0.2",
Labels: models.Labels{
{Name: "cluster", Value: "prod"},
{Name: "instance", Value: "server2"},
{Name: "ip", Value: "127.0.0.2"},
},
State: models.AlertStateActive,
Alertmanager: []models.AlertmanagerInstance{
@@ -283,10 +284,10 @@ var groupTests = []groupTest{
{
StartsAt: time.Date(2019, time.January, 1, 0, 1, 0, 1, time.UTC),
Annotations: models.Annotations{},
Labels: map[string]string{
"cluster": "staging",
"instance": "server3",
"ip": "127.0.0.3",
Labels: models.Labels{
{Name: "cluster", Value: "staging"},
{Name: "instance", Value: "server3"},
{Name: "ip", Value: "127.0.0.3"},
},
State: models.AlertStateActive,
Alertmanager: []models.AlertmanagerInstance{
@@ -302,10 +303,10 @@ var groupTests = []groupTest{
{
StartsAt: time.Date(2019, time.January, 1, 0, 0, 59, 0, time.UTC),
Annotations: models.Annotations{},
Labels: map[string]string{
"cluster": "staging",
"instance": "server4",
"ip": "127.0.0.4",
Labels: models.Labels{
{Name: "cluster", Value: "staging"},
{Name: "instance", Value: "server4"},
{Name: "ip", Value: "127.0.0.4"},
},
State: models.AlertStateActive,
Alertmanager: []models.AlertmanagerInstance{
@@ -321,10 +322,10 @@ var groupTests = []groupTest{
{
StartsAt: time.Date(2019, time.January, 10, 0, 0, 0, 0, time.UTC),
Annotations: models.Annotations{},
Labels: map[string]string{
"cluster": "staging",
"instance": "server5",
"ip": "127.0.0.5",
Labels: models.Labels{
{Name: "cluster", Value: "staging"},
{Name: "instance", Value: "server5"},
{Name: "ip", Value: "127.0.0.5"},
},
State: models.AlertStateActive,
Alertmanager: []models.AlertmanagerInstance{
@@ -340,10 +341,10 @@ var groupTests = []groupTest{
{
StartsAt: time.Date(2019, time.January, 10, 1, 0, 0, 0, time.UTC),
Annotations: models.Annotations{},
Labels: map[string]string{
"cluster": "dev",
"instance": "server6",
"ip": "127.0.0.6",
Labels: models.Labels{
{Name: "cluster", Value: "dev"},
{Name: "instance", Value: "server6"},
{Name: "ip", Value: "127.0.0.6"},
},
State: models.AlertStateSuppressed,
Alertmanager: []models.AlertmanagerInstance{
@@ -359,10 +360,10 @@ var groupTests = []groupTest{
{
StartsAt: time.Date(2019, time.January, 10, 0, 20, 0, 0, time.UTC),
Annotations: models.Annotations{},
Labels: map[string]string{
"cluster": "dev",
"instance": "server7",
"ip": "127.0.0.7",
Labels: models.Labels{
{Name: "cluster", Value: "dev"},
{Name: "instance", Value: "server7"},
{Name: "ip", Value: "127.0.0.7"},
},
State: models.AlertStateSuppressed,
Alertmanager: []models.AlertmanagerInstance{
@@ -378,10 +379,10 @@ var groupTests = []groupTest{
{
StartsAt: time.Date(2019, time.January, 10, 0, 21, 0, 0, time.UTC),
Annotations: models.Annotations{},
Labels: map[string]string{
"cluster": "dev",
"instance": "server8",
"ip": "127.0.0.8",
Labels: models.Labels{
{Name: "cluster", Value: "dev"},
{Name: "instance", Value: "server8"},
{Name: "ip", Value: "127.0.0.8"},
},
State: models.AlertStateSuppressed,
Alertmanager: []models.AlertmanagerInstance{
@@ -404,9 +405,9 @@ var groupTests = []groupTest{
},
{
receiver: "by-cluster-service",
labels: map[string]string{
"alertname": "Free_Disk_Space_Too_Low",
"cluster": "staging",
labels: models.Labels{
{Name: "alertname", Value: "Free_Disk_Space_Too_Low"},
{Name: "cluster", Value: "staging"},
},
alerts: []models.Alert{
{
@@ -423,10 +424,10 @@ var groupTests = []groupTest{
SilencedBy: []string{},
},
},
Labels: map[string]string{
"instance": "server5",
"job": "node_exporter",
"disk": "sda",
Labels: models.Labels{
{Name: "disk", Value: "sda"},
{Name: "instance", Value: "server5"},
{Name: "job", Value: "node_exporter"},
},
State: models.AlertStateActive,
Receiver: "by-cluster-service",
@@ -441,9 +442,9 @@ var groupTests = []groupTest{
},
{
receiver: "by-cluster-service",
labels: map[string]string{
"alertname": "Host_Down",
"cluster": "prod",
labels: models.Labels{
{Name: "alertname", Value: "Host_Down"},
{Name: "cluster", Value: "prod"},
},
alerts: []models.Alert{
{
@@ -459,9 +460,9 @@ var groupTests = []groupTest{
SilencedBy: []string{},
},
},
Labels: map[string]string{
"instance": "server1",
"ip": "127.0.0.1",
Labels: models.Labels{
{Name: "instance", Value: "server1"},
{Name: "ip", Value: "127.0.0.1"},
},
State: models.AlertStateActive,
Receiver: "by-cluster-service",
@@ -476,9 +477,9 @@ var groupTests = []groupTest{
SilencedBy: []string{},
},
},
Labels: map[string]string{
"instance": "server2",
"ip": "127.0.0.2",
Labels: models.Labels{
{Name: "instance", Value: "server2"},
{Name: "ip", Value: "127.0.0.2"},
},
State: models.AlertStateActive,
Receiver: "by-cluster-service",
@@ -493,8 +494,8 @@ var groupTests = []groupTest{
},
{
receiver: "by-name",
labels: map[string]string{
"alertname": "HTTP_Probe_Failed",
labels: models.Labels{
{Name: "alertname", Value: "HTTP_Probe_Failed"},
},
alerts: []models.Alert{
{
@@ -510,8 +511,8 @@ var groupTests = []groupTest{
Source: "http://localhost/prometheus",
},
},
Labels: map[string]string{
"instance": "web1",
Labels: models.Labels{
{Name: "instance", Value: "web1"},
},
State: models.AlertStateSuppressed,
Receiver: "by-name",
@@ -527,8 +528,8 @@ var groupTests = []groupTest{
SilencedBy: []string{},
},
},
Labels: map[string]string{
"instance": "web2",
Labels: models.Labels{
{Name: "instance", Value: "web2"},
},
State: models.AlertStateActive,
Receiver: "by-name",
@@ -543,8 +544,8 @@ var groupTests = []groupTest{
},
{
receiver: "by-name",
labels: map[string]string{
"alertname": "Free_Disk_Space_Too_Low",
labels: models.Labels{
{Name: "alertname", Value: "Free_Disk_Space_Too_Low"},
},
alerts: []models.Alert{
{
@@ -561,11 +562,11 @@ var groupTests = []groupTest{
SilencedBy: []string{},
},
},
Labels: map[string]string{
"cluster": "staging",
"instance": "server5",
"job": "node_exporter",
"disk": "sda",
Labels: models.Labels{
{Name: "cluster", Value: "staging"},
{Name: "disk", Value: "sda"},
{Name: "instance", Value: "server5"},
{Name: "job", Value: "node_exporter"},
},
State: models.AlertStateActive,
Receiver: "by-name",
@@ -580,9 +581,9 @@ var groupTests = []groupTest{
},
{
receiver: "by-cluster-service",
labels: map[string]string{
"alertname": "HTTP_Probe_Failed",
"cluster": "dev",
labels: models.Labels{
{Name: "alertname", Value: "HTTP_Probe_Failed"},
{Name: "cluster", Value: "dev"},
},
alerts: []models.Alert{
{
@@ -599,8 +600,8 @@ var groupTests = []groupTest{
SilencedBy: []string{"0804764c-6163-4c64-b0a9-08feebe2db4b"},
},
},
Labels: map[string]string{
"instance": "web1",
Labels: models.Labels{
{Name: "instance", Value: "web1"},
},
State: models.AlertStateSuppressed,
Receiver: "by-cluster-service",
@@ -616,8 +617,8 @@ var groupTests = []groupTest{
SilencedBy: []string{},
},
},
Labels: map[string]string{
"instance": "web2",
Labels: models.Labels{
{Name: "instance", Value: "web2"},
},
State: models.AlertStateActive,
Receiver: "by-cluster-service",
@@ -641,12 +642,12 @@ func compareAlertGroups(testCase groupTest, group models.APIAlertGroup) bool {
if len(testCase.labels) != len(group.Labels) {
return false
}
for key, val := range testCase.labels {
v, found := group.Labels[key]
if !found {
for _, l := range testCase.labels {
v := group.Labels.Get(l.Name)
if v == nil {
return false
}
if val != v {
if l.Value != v.Value {
return false
}
}
@@ -660,12 +661,12 @@ func compareAlerts(expectedAlert, gotAlert models.Alert) bool {
if len(gotAlert.Labels) != len(expectedAlert.Labels) {
return false
}
for key, val := range expectedAlert.Labels {
v, found := gotAlert.Labels[key]
if !found {
for _, l := range expectedAlert.Labels {
v := gotAlert.Labels.Get(l.Name)
if v == nil {
return false
}
if val != v {
if l.Value != v.Value {
return false
}
}
@@ -1000,22 +1001,23 @@ func TestSortOrder(t *testing.T) {
} else {
values := []string{}
for _, ag := range ur.Grids[0].AlertGroups {
v := ag.Labels[testCase.expectedLabel]
v := ag.Labels.GetValue(testCase.expectedLabel)
if v == "" {
v = ag.Shared.Labels[testCase.expectedLabel]
v = ag.Shared.Labels.GetValue(testCase.expectedLabel)
}
if v != "" {
values = append(values, v)
} else {
for _, alert := range ag.Alerts {
v = alert.Labels[testCase.expectedLabel]
v = alert.Labels.GetValue(testCase.expectedLabel)
values = append(values, v)
}
}
}
if diff := cmp.Diff(testCase.expectedValues, values); diff != "" {
t.Errorf("Incorrectly sorted values (-want +got):\n%s", diff)
t.Errorf("Incorrectly sorted values for filter=%q order=%s label=%q reverse=%v (-want +got):\n%s",
strings.Join(testCase.filter, " "), testCase.sortOrder, testCase.sortLabel, testCase.sortReverse, diff)
}
}
}
@@ -1023,22 +1025,22 @@ func TestSortOrder(t *testing.T) {
}
}
func verifyStrippedLabels(t *testing.T, labels map[string]string, keep, strip []string) {
func verifyStrippedLabels(t *testing.T, labels models.Labels, keep, strip []string) {
for _, l := range strip {
if val, ok := labels[l]; ok {
t.Errorf("Found stripped label %s=%s on %v", l, val, labels)
if val := labels.Get(l); val != nil {
t.Errorf("Found stripped label %s=%s on %v", val.Name, val.Value, labels)
}
}
if len(keep) > 0 && len(strip) == 0 {
for k, v := range labels {
for _, ll := range labels {
ok := false
for _, l := range keep {
if k == l {
if ll.Name == l {
ok = true
}
}
if !ok {
t.Errorf("Found label %s=%s that's not on the keep list: %v", k, v, keep)
t.Errorf("Found label %s=%s that's not on the keep list: %v", ll.Name, ll.Value, keep)
}
}
}

View File

@@ -224,7 +224,6 @@ func alerts(w http.ResponseWriter, r *http.Request) {
return
}
// use full URI (including query args) as cache key
cacheKey := fmt.Sprintf("%x", structhash.Sha1(request, 1))
data, found := apiCache.Get(cacheKey)
@@ -265,14 +264,14 @@ func alerts(w http.ResponseWriter, r *http.Request) {
for _, ag := range filtered {
perGridAlertGroup := map[string]*models.AlertGroup{}
for k := range ag.Labels {
labelMap[k] = struct{}{}
for _, l := range ag.Labels {
labelMap[l.Name] = struct{}{}
}
for _, alert := range ag.Alerts {
alert := alert // scopelint pin
for k := range alert.Labels {
labelMap[k] = struct{}{}
for _, l := range alert.Labels {
labelMap[l.Name] = struct{}{}
}
allReceivers[alert.Receiver] = true
@@ -292,7 +291,7 @@ func alerts(w http.ResponseWriter, r *http.Request) {
alertGridLabelValues[am.Cluster] = true
}
default:
alertGridLabelValues[alert.Labels[gridLabel]] = true
alertGridLabelValues[alert.Labels.GetValue(gridLabel)] = true
}
for alertGridLabelValue := range alertGridLabelValues {
@@ -390,13 +389,13 @@ func alerts(w http.ResponseWriter, r *http.Request) {
}
}
for key, value := range alert.Labels {
if keyMap, foundKey := dedupedColors[key]; foundKey {
if color, foundColor := keyMap[value]; foundColor {
if _, found := colors[key]; !found {
colors[key] = map[string]models.LabelColors{}
for _, l := range alert.Labels {
if keyMap, foundKey := dedupedColors[l.Name]; foundKey {
if color, foundColor := keyMap[l.Value]; foundColor {
if _, found := colors[l.Name]; !found {
colors[l.Name] = map[string]models.LabelColors{}
}
colors[key][value] = color
colors[l.Name][l.Value] = color
}
}
}
@@ -684,7 +683,7 @@ func silences(w http.ResponseWriter, r *http.Request) {
}
type AlertList struct {
Alerts []map[string]string `json:"alerts"`
Alerts []models.Labels `json:"alerts"`
}
func alertList(w http.ResponseWriter, r *http.Request) {
@@ -711,12 +710,9 @@ func alertList(w http.ResponseWriter, r *http.Request) {
labelMap := map[string]map[string]string{}
for _, ag := range filtered {
for _, alert := range ag.Alerts {
labels := map[string]string{}
for k, v := range ag.Labels {
labels[k] = v
}
for k, v := range alert.Labels {
labels[k] = v
labels := ag.Labels.Map()
for _, l := range alert.Labels {
labels[l.Name] = l.Value
}
h := fmt.Sprintf("%x", structhash.Sha1(labels, 1))
labelMap[h] = labels
@@ -736,10 +732,15 @@ func alertList(w http.ResponseWriter, r *http.Request) {
sort.Strings(sortKeys)
al := AlertList{
Alerts: []map[string]string{},
Alerts: []models.Labels{},
}
for _, labels := range labelMap {
al.Alerts = append(al.Alerts, labels)
alert := models.Labels{}
for k, v := range labels {
alert = alert.Set(k, v)
}
sort.Sort(alert)
al.Alerts = append(al.Alerts, alert)
}
sortSliceOfLabels(al.Alerts, sortKeys, "alertname")
@@ -751,20 +752,22 @@ func alertList(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write(data)
}
func sortSliceOfLabels(labels []map[string]string, sortKeys []string, fallback string) {
func sortSliceOfLabels(labels []models.Labels, sortKeys []string, fallback string) {
sort.SliceStable(labels, func(i, j int) bool {
for _, k := range sortKeys {
if labels[i][k] != "" && labels[j][k] == "" {
vi := labels[i].GetValue(k)
vj := labels[j].GetValue(k)
if vi != "" && vj == "" {
return true
}
if labels[i][k] == "" && labels[j][k] != "" {
if vi == "" && vj != "" {
return false
}
if labels[i][k] != labels[j][k] {
return sortorder.NaturalLess(labels[i][k], labels[j][k])
if vi != vj {
return sortorder.NaturalLess(vi, vj)
}
}
return sortorder.NaturalLess(labels[i][fallback], labels[j][fallback])
return sortorder.NaturalLess(labels[i].GetValue(fallback), labels[j].GetValue(fallback))
})
}
@@ -814,8 +817,8 @@ func counters(w http.ResponseWriter, r *http.Request) {
}
countLabel(counters, "@state", alert.State)
countLabel(counters, "@receiver", alert.Receiver)
for key, value := range alert.Labels {
countLabel(counters, key, value)
for _, l := range alert.Labels {
countLabel(counters, l.Name, l.Value)
}
}
}

View File

@@ -3474,87 +3474,87 @@ func TestAlertList(t *testing.T) {
{
args: "",
alerts: AlertList{
Alerts: []map[string]string{
Alerts: []models.Labels{
{
"alertname": "Free_Disk_Space_Too_Low",
"cluster": "staging",
"disk": "sda",
"instance": "server5",
"job": "node_exporter",
{Name: "alertname", Value: "Free_Disk_Space_Too_Low"},
{Name: "cluster", Value: "staging"},
{Name: "disk", Value: "sda"},
{Name: "instance", Value: "server5"},
{Name: "job", Value: "node_exporter"},
},
{
"alertname": "HTTP_Probe_Failed",
"cluster": "dev",
"instance": "web1",
"job": "node_exporter",
{Name: "alertname", Value: "HTTP_Probe_Failed"},
{Name: "cluster", Value: "dev"},
{Name: "instance", Value: "web1"},
{Name: "job", Value: "node_exporter"},
},
{
"alertname": "HTTP_Probe_Failed",
"cluster": "dev",
"instance": "web2",
"job": "node_exporter",
{Name: "alertname", Value: "HTTP_Probe_Failed"},
{Name: "cluster", Value: "dev"},
{Name: "instance", Value: "web2"},
{Name: "job", Value: "node_exporter"},
},
{
"alertname": "Host_Down",
"cluster": "dev",
"instance": "server6",
"ip": "127.0.0.6",
"job": "node_ping",
{Name: "alertname", Value: "Host_Down"},
{Name: "cluster", Value: "dev"},
{Name: "instance", Value: "server6"},
{Name: "ip", Value: "127.0.0.6"},
{Name: "job", Value: "node_ping"},
},
{
"alertname": "Host_Down",
"cluster": "dev",
"instance": "server7",
"ip": "127.0.0.7",
"job": "node_ping",
{Name: "alertname", Value: "Host_Down"},
{Name: "cluster", Value: "dev"},
{Name: "instance", Value: "server7"},
{Name: "ip", Value: "127.0.0.7"},
{Name: "job", Value: "node_ping"},
},
{
"alertname": "Host_Down",
"cluster": "dev",
"instance": "server8",
"ip": "127.0.0.8",
"job": "node_ping",
{Name: "alertname", Value: "Host_Down"},
{Name: "cluster", Value: "dev"},
{Name: "instance", Value: "server8"},
{Name: "ip", Value: "127.0.0.8"},
{Name: "job", Value: "node_ping"},
},
{
"alertname": "Host_Down",
"cluster": "prod",
"instance": "server1",
"ip": "127.0.0.1",
"job": "node_ping",
{Name: "alertname", Value: "Host_Down"},
{Name: "cluster", Value: "prod"},
{Name: "instance", Value: "server1"},
{Name: "ip", Value: "127.0.0.1"},
{Name: "job", Value: "node_ping"},
},
{
"alertname": "Host_Down",
"cluster": "prod",
"instance": "server2",
"ip": "127.0.0.2",
"job": "node_ping",
{Name: "alertname", Value: "Host_Down"},
{Name: "cluster", Value: "prod"},
{Name: "instance", Value: "server2"},
{Name: "ip", Value: "127.0.0.2"},
{Name: "job", Value: "node_ping"},
},
{
"alertname": "Host_Down",
"cluster": "staging",
"instance": "server3",
"ip": "127.0.0.3",
"job": "node_ping",
{Name: "alertname", Value: "Host_Down"},
{Name: "cluster", Value: "staging"},
{Name: "instance", Value: "server3"},
{Name: "ip", Value: "127.0.0.3"},
{Name: "job", Value: "node_ping"},
},
{
"alertname": "Host_Down",
"cluster": "staging",
"instance": "server4",
"ip": "127.0.0.4",
"job": "node_ping",
{Name: "alertname", Value: "Host_Down"},
{Name: "cluster", Value: "staging"},
{Name: "instance", Value: "server4"},
{Name: "ip", Value: "127.0.0.4"},
{Name: "job", Value: "node_ping"},
},
{
"alertname": "Host_Down",
"cluster": "staging",
"instance": "server5",
"ip": "127.0.0.5",
"job": "node_ping",
{Name: "alertname", Value: "Host_Down"},
{Name: "cluster", Value: "staging"},
{Name: "instance", Value: "server5"},
{Name: "ip", Value: "127.0.0.5"},
{Name: "job", Value: "node_ping"},
},
{
"alertname": "Memory_Usage_Too_High",
"cluster": "prod",
"instance": "server2",
"job": "node_exporter",
{Name: "alertname", Value: "Memory_Usage_Too_High"},
{Name: "cluster", Value: "prod"},
{Name: "instance", Value: "server2"},
{Name: "job", Value: "node_exporter"},
},
},
},
@@ -3562,13 +3562,13 @@ func TestAlertList(t *testing.T) {
{
args: "q=alertname=Free_Disk_Space_Too_Low",
alerts: AlertList{
Alerts: []map[string]string{
Alerts: []models.Labels{
{
"alertname": "Free_Disk_Space_Too_Low",
"cluster": "staging",
"disk": "sda",
"instance": "server5",
"job": "node_exporter",
{Name: "alertname", Value: "Free_Disk_Space_Too_Low"},
{Name: "cluster", Value: "staging"},
{Name: "disk", Value: "sda"},
{Name: "instance", Value: "server5"},
{Name: "job", Value: "node_exporter"},
},
},
},
@@ -3576,18 +3576,18 @@ func TestAlertList(t *testing.T) {
{
args: "q=alertname=HTTP_Probe_Failed",
alerts: AlertList{
Alerts: []map[string]string{
Alerts: []models.Labels{
{
"alertname": "HTTP_Probe_Failed",
"cluster": "dev",
"instance": "web1",
"job": "node_exporter",
{Name: "alertname", Value: "HTTP_Probe_Failed"},
{Name: "cluster", Value: "dev"},
{Name: "instance", Value: "web1"},
{Name: "job", Value: "node_exporter"},
},
{
"alertname": "HTTP_Probe_Failed",
"cluster": "dev",
"instance": "web2",
"job": "node_exporter",
{Name: "alertname", Value: "HTTP_Probe_Failed"},
{Name: "cluster", Value: "dev"},
{Name: "instance", Value: "web2"},
{Name: "job", Value: "node_exporter"},
},
},
},
@@ -3595,19 +3595,19 @@ func TestAlertList(t *testing.T) {
{
args: "q=instance=server2",
alerts: AlertList{
Alerts: []map[string]string{
Alerts: []models.Labels{
{
"alertname": "Host_Down",
"cluster": "prod",
"instance": "server2",
"ip": "127.0.0.2",
"job": "node_ping",
{Name: "alertname", Value: "Host_Down"},
{Name: "cluster", Value: "prod"},
{Name: "instance", Value: "server2"},
{Name: "ip", Value: "127.0.0.2"},
{Name: "job", Value: "node_ping"},
},
{
"alertname": "Memory_Usage_Too_High",
"cluster": "prod",
"instance": "server2",
"job": "node_exporter",
{Name: "alertname", Value: "Memory_Usage_Too_High"},
{Name: "cluster", Value: "prod"},
{Name: "instance", Value: "server2"},
{Name: "job", Value: "node_exporter"},
},
},
},
@@ -3615,20 +3615,20 @@ func TestAlertList(t *testing.T) {
{
args: "q=alertname=Host_Down&q=cluster=prod",
alerts: AlertList{
Alerts: []map[string]string{
Alerts: []models.Labels{
{
"alertname": "Host_Down",
"cluster": "prod",
"instance": "server1",
"ip": "127.0.0.1",
"job": "node_ping",
{Name: "alertname", Value: "Host_Down"},
{Name: "cluster", Value: "prod"},
{Name: "instance", Value: "server1"},
{Name: "ip", Value: "127.0.0.1"},
{Name: "job", Value: "node_ping"},
},
{
"alertname": "Host_Down",
"cluster": "prod",
"instance": "server2",
"ip": "127.0.0.2",
"job": "node_ping",
{Name: "alertname", Value: "Host_Down"},
{Name: "cluster", Value: "prod"},
{Name: "instance", Value: "server2"},
{Name: "ip", Value: "127.0.0.2"},
{Name: "job", Value: "node_ping"},
},
},
},
@@ -3636,7 +3636,7 @@ func TestAlertList(t *testing.T) {
{
args: "q=foo=bar",
alerts: AlertList{
Alerts: []map[string]string{},
Alerts: []models.Labels{},
},
},
}
@@ -3675,85 +3675,85 @@ func TestAlertList(t *testing.T) {
func TestSortSliceOfLabels(t *testing.T) {
type testCaseT struct {
labels []map[string]string
labels []models.Labels
sortKeys []string
fallback string
output []map[string]string
output []models.Labels
}
testCases := []testCaseT{
{
labels: []map[string]string{
{"alertname": "alert2"},
{"alertname": "alert1"},
labels: []models.Labels{
{{Name: "alertname", Value: "alert2"}},
{{Name: "alertname", Value: "alert1"}},
},
sortKeys: []string{},
fallback: "",
output: []map[string]string{
{"alertname": "alert2"},
{"alertname": "alert1"},
output: []models.Labels{
{{Name: "alertname", Value: "alert2"}},
{{Name: "alertname", Value: "alert1"}},
},
},
{
labels: []map[string]string{
{"alertname": "alert2"},
{"alertname": "alert1"},
labels: []models.Labels{
{{Name: "alertname", Value: "alert2"}},
{{Name: "alertname", Value: "alert1"}},
},
sortKeys: []string{"alertname"},
fallback: "alertname",
output: []map[string]string{
{"alertname": "alert1"},
{"alertname": "alert2"},
output: []models.Labels{
{{Name: "alertname", Value: "alert1"}},
{{Name: "alertname", Value: "alert2"}},
},
},
{
labels: []map[string]string{
{"alertname": "alert2"},
{"alertname": "alert1"},
labels: []models.Labels{
{{Name: "alertname", Value: "alert2"}},
{{Name: "alertname", Value: "alert1"}},
},
sortKeys: []string{},
fallback: "alertname",
output: []map[string]string{
{"alertname": "alert1"},
{"alertname": "alert2"},
output: []models.Labels{
{{Name: "alertname", Value: "alert1"}},
{{Name: "alertname", Value: "alert2"}},
},
},
{
labels: []map[string]string{
{"alertname": "alert2"},
{"alertname": "alert1"},
labels: []models.Labels{
{{Name: "alertname", Value: "alert2"}},
{{Name: "alertname", Value: "alert1"}},
},
sortKeys: []string{"foo"},
fallback: "alertname",
output: []map[string]string{
{"alertname": "alert1"},
{"alertname": "alert2"},
output: []models.Labels{
{{Name: "alertname", Value: "alert1"}},
{{Name: "alertname", Value: "alert2"}},
},
},
{
labels: []map[string]string{
{"alertname": "alert1"},
{"alertname": "alert1"},
labels: []models.Labels{
{{Name: "alertname", Value: "alert1"}},
{{Name: "alertname", Value: "alert1"}},
},
sortKeys: []string{"alertname"},
fallback: "alertname",
output: []map[string]string{
{"alertname": "alert1"},
{"alertname": "alert1"},
output: []models.Labels{
{{Name: "alertname", Value: "alert1"}},
{{Name: "alertname", Value: "alert1"}},
},
},
{
labels: []map[string]string{
{"alertname": "alert2", "job": "a"},
{"alertname": "alert1"},
{"alertname": "alert3", "job": "b"},
labels: []models.Labels{
{{Name: "alertname", Value: "alert2"}, {Name: "job", Value: "a"}},
{{Name: "alertname", Value: "alert1"}},
{{Name: "alertname", Value: "alert3"}, {Name: "job", Value: "b"}},
},
sortKeys: []string{"job"},
fallback: "alertname",
output: []map[string]string{
{"alertname": "alert2", "job": "a"},
{"alertname": "alert3", "job": "b"},
{"alertname": "alert1"},
output: []models.Labels{
{{Name: "alertname", Value: "alert2"}, {Name: "job", Value: "a"}},
{{Name: "alertname", Value: "alert3"}, {Name: "job", Value: "b"}},
{{Name: "alertname", Value: "alert1"}},
},
},
}