mirror of
https://github.com/prymitive/karma
synced 2026-05-05 03:16:51 +00:00
fix(backend): add ClusterName() method
This commit is contained in:
committed by
Łukasz Mierzwa
parent
9d8aeaae7e
commit
91c8170433
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"vbom.ml/util/sortorder"
|
||||
@@ -13,7 +12,6 @@ import (
|
||||
"github.com/prymitive/karma/internal/config"
|
||||
"github.com/prymitive/karma/internal/filters"
|
||||
"github.com/prymitive/karma/internal/models"
|
||||
"github.com/prymitive/karma/internal/slices"
|
||||
"github.com/prymitive/karma/internal/uri"
|
||||
)
|
||||
|
||||
@@ -88,23 +86,6 @@ func countersToLabelStats(counters map[string]map[string]int) models.LabelNameSt
|
||||
return data
|
||||
}
|
||||
|
||||
func clusterMembersFromConfig(am *alertmanager.Alertmanager) []string {
|
||||
members := []string{}
|
||||
|
||||
upstreams := alertmanager.GetAlertmanagers()
|
||||
for _, upstream := range upstreams {
|
||||
if upstream.Cluster == am.Cluster {
|
||||
members = append(members, upstream.Name)
|
||||
}
|
||||
}
|
||||
|
||||
return members
|
||||
}
|
||||
|
||||
func clusterMembersFromAPI(am *alertmanager.Alertmanager) []string {
|
||||
return am.ClusterMemberNames()
|
||||
}
|
||||
|
||||
func getUpstreams() models.AlertmanagerAPISummary {
|
||||
summary := models.AlertmanagerAPISummary{}
|
||||
|
||||
@@ -112,21 +93,7 @@ func getUpstreams() models.AlertmanagerAPISummary {
|
||||
upstreams := alertmanager.GetAlertmanagers()
|
||||
for _, upstream := range upstreams {
|
||||
members := upstream.ClusterMemberNames()
|
||||
|
||||
var clusterName string
|
||||
if upstream.Cluster != "" {
|
||||
configPeers := clusterMembersFromConfig(upstream)
|
||||
apiPeers := clusterMembersFromAPI(upstream)
|
||||
missing, extra := slices.StringSliceDiff(configPeers, apiPeers)
|
||||
|
||||
if len(missing) == 0 && len(extra) == 0 {
|
||||
clusterName = upstream.Cluster
|
||||
} else {
|
||||
clusterName = fmt.Sprintf("%s @ %s", strings.Join(members, " | "), upstream.Cluster)
|
||||
}
|
||||
} else {
|
||||
clusterName = strings.Join(members, " | ")
|
||||
}
|
||||
clusterName := upstream.ClusterName()
|
||||
|
||||
if _, found := clusters[clusterName]; !found {
|
||||
clusters[clusterName] = members
|
||||
|
||||
@@ -130,12 +130,14 @@ func alerts(c *gin.Context) {
|
||||
username = c.MustGet(gin.AuthUserKey).(string)
|
||||
}
|
||||
|
||||
upstreams := getUpstreams()
|
||||
|
||||
// initialize response object, set fields that don't require any locking
|
||||
resp := models.AlertsResponse{}
|
||||
resp.Status = "success"
|
||||
resp.Timestamp = string(ts)
|
||||
resp.Version = version
|
||||
resp.Upstreams = getUpstreams()
|
||||
resp.Upstreams = upstreams
|
||||
resp.Settings = models.Settings{
|
||||
Sorting: models.SortSettings{
|
||||
Grid: models.GridSettings{
|
||||
@@ -260,6 +262,16 @@ func alerts(c *gin.Context) {
|
||||
for _, am := range alert.Alertmanager {
|
||||
alertGridLabelValues = append(alertGridLabelValues, am.Name)
|
||||
}
|
||||
case "@cluster":
|
||||
alertGridLabelValues = make([]string, 0, len(alert.Alertmanager))
|
||||
for _, am := range alert.Alertmanager {
|
||||
for _, upstream := range upstreams.Instances {
|
||||
if am.Name == upstream.Name {
|
||||
alertGridLabelValues = append(alertGridLabelValues, upstream.Cluster)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
alertGridLabelValues = []string{alert.Labels[gridLabel]}
|
||||
}
|
||||
|
||||
@@ -277,6 +277,13 @@ func TestGrids(t *testing.T) {
|
||||
{labelValue: "default", alertGroupCount: 10},
|
||||
},
|
||||
},
|
||||
{
|
||||
gridLabel: "@cluster",
|
||||
requestQuery: "",
|
||||
grids: []testCaseGridT{
|
||||
{labelValue: "default", alertGroupCount: 10},
|
||||
},
|
||||
},
|
||||
{
|
||||
gridLabel: "@receiver",
|
||||
requestQuery: "",
|
||||
@@ -1426,7 +1433,7 @@ func TestUpstreamStatus(t *testing.T) {
|
||||
CORSCredentials: "omit",
|
||||
Error: "",
|
||||
Version: "0.20.0",
|
||||
Cluster: "ha1 @ Broken HA",
|
||||
Cluster: "ha1",
|
||||
ClusterMembers: []string{"ha1"},
|
||||
},
|
||||
{
|
||||
@@ -1438,13 +1445,13 @@ func TestUpstreamStatus(t *testing.T) {
|
||||
CORSCredentials: "omit",
|
||||
Error: "",
|
||||
Version: "0.19.0",
|
||||
Cluster: "ha2 @ Broken HA",
|
||||
Cluster: "ha2",
|
||||
ClusterMembers: []string{"ha2"},
|
||||
},
|
||||
},
|
||||
Clusters: map[string][]string{
|
||||
"ha1 @ Broken HA": {"ha1"},
|
||||
"ha2 @ Broken HA": {"ha2"},
|
||||
"ha1": {"ha1"},
|
||||
"ha2": {"ha2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
18
internal/alertmanager/cluster.go
Normal file
18
internal/alertmanager/cluster.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package alertmanager
|
||||
|
||||
func clusterMembersFromConfig(am *Alertmanager) []string {
|
||||
members := []string{}
|
||||
|
||||
upstreams := GetAlertmanagers()
|
||||
for _, upstream := range upstreams {
|
||||
if upstream.Cluster == am.Cluster {
|
||||
members = append(members, upstream.Name)
|
||||
}
|
||||
}
|
||||
|
||||
return members
|
||||
}
|
||||
|
||||
func clusterMembersFromAPI(am *Alertmanager) []string {
|
||||
return am.ClusterMemberNames()
|
||||
}
|
||||
@@ -118,9 +118,10 @@ func TestDedupAutocomplete(t *testing.T) {
|
||||
// 74 hints for everything except @alertmanager and @silence_id
|
||||
// 4 hints for @silence_id 1 and 2
|
||||
// 2 hints per @alertmanager
|
||||
// 2 hits per @cluster
|
||||
// 6 hints for silences in for each alertmanager
|
||||
// silence id might get duplicated so this check isn't very strict
|
||||
expected := 74 + 4 + mockCount*2 + mockCount*6
|
||||
expected := 74 + 4 + mockCount*2 + mockCount*2 + mockCount*6
|
||||
if len(ac) <= int(float64(expected)*0.8) || len(ac) > expected {
|
||||
t.Errorf("Expected %d autocomplete hints, got %d", expected, len(ac))
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ type Alertmanager struct {
|
||||
knownLabels []string
|
||||
lastError string
|
||||
status models.AlertmanagerStatus
|
||||
clusterName string
|
||||
// metrics tracked per alertmanager instance
|
||||
Metrics alertmanagerMetrics
|
||||
// headers to send with each AlertManager request
|
||||
@@ -247,7 +248,7 @@ func (am *Alertmanager) pullAlerts(version string) error {
|
||||
alert.Alertmanager = []models.AlertmanagerInstance{
|
||||
{
|
||||
Name: am.Name,
|
||||
Cluster: am.ClusterID(),
|
||||
Cluster: am.ClusterName(),
|
||||
State: alert.State,
|
||||
StartsAt: alert.StartsAt,
|
||||
Source: alert.GeneratorURL,
|
||||
@@ -336,6 +337,7 @@ func (am *Alertmanager) Pull() error {
|
||||
am.lock.Lock()
|
||||
am.status = *status
|
||||
am.lastError = ""
|
||||
am.clusterName = ""
|
||||
am.lock.Unlock()
|
||||
|
||||
return nil
|
||||
@@ -487,3 +489,29 @@ func (am *Alertmanager) ClusterID() string {
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
func (am *Alertmanager) ClusterName() string {
|
||||
am.lock.RLock()
|
||||
if am.clusterName != "" {
|
||||
am.lock.RUnlock()
|
||||
return am.clusterName
|
||||
}
|
||||
am.lock.RUnlock()
|
||||
|
||||
var clusterName string
|
||||
if am.Cluster != "" {
|
||||
configPeers := clusterMembersFromConfig(am)
|
||||
apiPeers := clusterMembersFromAPI(am)
|
||||
missing, extra := slices.StringSliceDiff(configPeers, apiPeers)
|
||||
|
||||
if len(missing) == 0 && len(extra) == 0 {
|
||||
clusterName = am.Cluster
|
||||
} else {
|
||||
clusterName = strings.Join(am.ClusterMemberNames(), " | ")
|
||||
}
|
||||
} else {
|
||||
clusterName = strings.Join(am.ClusterMemberNames(), " | ")
|
||||
}
|
||||
am.clusterName = clusterName
|
||||
return clusterName
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user