github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/alertmanager/merger/v1_alerts.go (about) 1 package merger 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "sort" 7 8 v1 "github.com/prometheus/alertmanager/api/v1" 9 ) 10 11 const ( 12 statusSuccess = "success" 13 ) 14 15 // V1Alerts implements the Merger interface for GET /v1/alerts. It returns the union of alerts over 16 // all the responses. When the same alert exists in multiple responses, the alert instance in the 17 // earliest response is returned in the final response. We cannot use the UpdatedAt timestamp as 18 // for V2Alerts, because the v1 API does not provide it. 19 type V1Alerts struct{} 20 21 func (V1Alerts) MergeResponses(in [][]byte) ([]byte, error) { 22 type bodyType struct { 23 Status string `json:"status"` 24 Data []*v1.Alert `json:"data"` 25 } 26 27 alerts := make([]*v1.Alert, 0) 28 for _, body := range in { 29 parsed := bodyType{} 30 if err := json.Unmarshal(body, &parsed); err != nil { 31 return nil, err 32 } 33 if parsed.Status != statusSuccess { 34 return nil, fmt.Errorf("unable to merge response of status: %s", parsed.Status) 35 } 36 alerts = append(alerts, parsed.Data...) 37 } 38 39 merged, err := mergeV1Alerts(alerts) 40 if err != nil { 41 return nil, err 42 } 43 body := bodyType{ 44 Status: statusSuccess, 45 Data: merged, 46 } 47 48 return json.Marshal(body) 49 } 50 51 func mergeV1Alerts(in []*v1.Alert) ([]*v1.Alert, error) { 52 // Select an arbitrary alert for each distinct alert. 53 alerts := make(map[string]*v1.Alert) 54 for _, alert := range in { 55 key := alert.Fingerprint 56 if _, ok := alerts[key]; !ok { 57 alerts[key] = alert 58 } 59 } 60 61 result := make([]*v1.Alert, 0, len(alerts)) 62 for _, alert := range alerts { 63 result = append(result, alert) 64 } 65 66 // Mimic Alertmanager which returns alerts ordered by fingerprint (as string). 67 sort.Slice(result, func(i, j int) bool { 68 return result[i].Fingerprint < result[j].Fingerprint 69 }) 70 71 return result, nil 72 }