Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion pkg/mcp/incidents_tool.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ func (i *IncidentTool) transformPromValueToIncident(dataVec prom.RangeVector, qR
healthyVal := processor.HealthValue(lastSample.Value)
groupId := string(v.Metric["group_id"])
component := string(v.Metric["component"])
clusterName := string(v.Metric["cluster"])
clusterID := string(v.Metric["clusterID"])

if existingInc, ok := incidents[groupId]; ok {
existingInc.ComponentsSet[component] = struct{}{}
Expand Down Expand Up @@ -250,7 +252,9 @@ func (i *IncidentTool) transformPromValueToIncident(dataVec prom.RangeVector, qR
incidents[existingInc.GroupId] = existingInc
} else {
incident := Incident{
GroupId: string(groupId),
Cluster: clusterName,
ClusterID: clusterID,
GroupId: groupId,
Severity: healthyVal.String(),
StartTime: formatToRFC3339(startTime),
EndTime: formatToRFC3339(endTime),
Expand Down Expand Up @@ -326,6 +330,14 @@ func getAlertDataForIncidents(ctx context.Context, incidents map[string]Incident
for _, alertInIncident := range inc.Alerts {
subsetMatcher := common.LabelsSubsetMatcher{Labels: alertInIncident}
for _, firingAlert := range alerts {
// check for multicluster/ACM environment
if inc.ClusterID != "" {
clusterIDMatch := string(firingAlert["clusterID"]) == inc.ClusterID
// if the alert cluster ID does not match incident cluster ID, skip
if !clusterIDMatch {
continue
}
}
match, _ := subsetMatcher.Matches(firingAlert)
if match {

Expand Down Expand Up @@ -381,11 +393,15 @@ func cleanupLabels(m model.LabelSet) model.LabelSet {
updatedLS := m.Clone()
updatedLS["status"] = updatedLS["alertstate"]
updatedLS["name"] = updatedLS["alertname"]
if clusterID := updatedLS["clusterID"]; clusterID != "" {
updatedLS["cluster_id"] = clusterID
}
delete(updatedLS, "__name__")
delete(updatedLS, "prometheus")
delete(updatedLS, "alertstate")
delete(updatedLS, "alertname")
delete(updatedLS, "pod")
delete(updatedLS, "clusterID")
return updatedLS
}

Expand Down
158 changes: 158 additions & 0 deletions pkg/mcp/incidents_tool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,164 @@ func TestGetAlertDataForIncidents(t *testing.T) {
},
},
},
{
name: "Alerts are correctly matched in multicluster environment",
promLoader: func() prom.Loader {
mocked := mocks.NewMockPrometheusLoader(ctrl)
mocked.EXPECT().LoadVectorRange(gomock.Any(), `ALERTS{alertstate!="pending"}`, gomock.Any(), gomock.Any(), gomock.Any()).Return(prom.RangeVector{
{
Metric: model.LabelSet{
"alertname": "Alert1",
"namespace": "foo",
"pod": "red",
"alertstate": "firing",
"severity": "warning",
"clusterID": "1111",
},
Samples: []model.SamplePair{
{
Value: 1,
Timestamp: model.Now().Add(-20 * time.Minute),
},
{
Value: 1,
Timestamp: model.Now().Add(-1 * time.Minute),
},
},
},
{
Metric: model.LabelSet{
"alertname": "Alert1",
"namespace": "foo",
"pod": "red",
"alertstate": "firing",
"severity": "warning",
"clusterID": "2222",
},
Samples: []model.SamplePair{
{
Value: 1,
Timestamp: model.Now().Add(-20 * time.Minute),
},
{
Value: 1,
Timestamp: model.Now().Add(-1 * time.Minute),
},
},
},
{
Metric: model.LabelSet{
"alertname": "Alert1",
"namespace": "bar",
"pod": "blue",
"alertstate": "firing",
"severity": "critical",
"clusterID": "1111",
},
Samples: []model.SamplePair{
{
Value: 1,
Timestamp: model.Now().Add(-20 * time.Minute),
},
{
Value: 1,
Timestamp: model.Now().Add(-1 * time.Minute),
},
},
},
{
Metric: model.LabelSet{
"alertname": "Alert1",
"namespace": "bar",
"pod": "blue",
"alertstate": "firing",
"severity": "critical",
"clusterID": "2222",
},
Samples: []model.SamplePair{
{
Value: 1,
Timestamp: model.Now().Add(-20 * time.Minute),
},
{
Value: 1,
Timestamp: model.Now().Add(-1 * time.Minute),
},
},
},
}, nil)
return mocked
}(),
incidentsMap: map[string]Incident{
"1": {
GroupId: "1",
ClusterID: "1111",
Alerts: []model.LabelSet{
{"alertname": "Alert1", "namespace": "foo", "severity": "warning"},
{"alertname": "Alert1", "namespace": "bar", "severity": "critical"},
},
},
"2": {
GroupId: "2",
ClusterID: "2222",
Alerts: []model.LabelSet{
{"alertname": "Alert1", "namespace": "foo", "severity": "warning"},
{"alertname": "Alert1", "namespace": "bar", "severity": "critical"},
},
},
},
silencedAlerts: []models.Alert{},
expectedIncidents: []Incident{
{
GroupId: "1",
ClusterID: "1111",
Alerts: []model.LabelSet{
{
"name": "Alert1",
"namespace": "foo",
"status": "firing",
"silenced": "false",
"severity": "warning",
"cluster_id": "1111",
"start_time": model.LabelValue(model.Now().Add(-20 * time.Minute).Time().Format(time.RFC3339)),
},
{
"name": "Alert1",
"namespace": "bar",
"status": "firing",
"silenced": "false",
"severity": "critical",
"cluster_id": "1111",
"start_time": model.LabelValue(model.Now().Add(-20 * time.Minute).Time().Format(time.RFC3339)),
},
},
},
{
GroupId: "2",
ClusterID: "2222",
Alerts: []model.LabelSet{
{
"name": "Alert1",
"namespace": "foo",
"status": "firing",
"silenced": "false",
"severity": "warning",
"cluster_id": "2222",
"start_time": model.LabelValue(model.Now().Add(-20 * time.Minute).Time().Format(time.RFC3339)),
},
{
"name": "Alert1",
"namespace": "bar",
"status": "firing",
"silenced": "false",
"severity": "critical",
"cluster_id": "2222",
"start_time": model.LabelValue(model.Now().Add(-20 * time.Minute).Time().Format(time.RFC3339)),
},
},
},
},
},
}

for _, tt := range tests {
Expand Down
2 changes: 2 additions & 0 deletions pkg/mcp/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ type Incident struct {
StartTime string `json:"start_time"`
Status string `json:"status"`
EndTime string `json:"end_time"`
Cluster string `json:"cluster,omitempty"`
ClusterID string `json:"cluster_id,omitempty"`

URL string `json:"url_details"`
Alerts []model.LabelSet `json:"alerts"`
Expand Down