github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/alertmanager/merger/v2_alerts.go (about) 1 package merger 2 3 import ( 4 "errors" 5 "sort" 6 "time" 7 8 "github.com/go-openapi/swag" 9 v2_models "github.com/prometheus/alertmanager/api/v2/models" 10 ) 11 12 // V2Alerts implements the Merger interface for GET /v2/alerts. It returns the union 13 // of alerts over all the responses. When the same alert exists in multiple responses, the 14 // instance of that alert with the most recent UpdatedAt timestamp is returned in the response. 15 type V2Alerts struct{} 16 17 func (V2Alerts) MergeResponses(in [][]byte) ([]byte, error) { 18 alerts := make(v2_models.GettableAlerts, 0) 19 for _, body := range in { 20 parsed := make(v2_models.GettableAlerts, 0) 21 if err := swag.ReadJSON(body, &parsed); err != nil { 22 return nil, err 23 } 24 alerts = append(alerts, parsed...) 25 } 26 27 merged, err := mergeV2Alerts(alerts) 28 if err != nil { 29 return nil, err 30 } 31 32 return swag.WriteJSON(merged) 33 } 34 35 func mergeV2Alerts(in v2_models.GettableAlerts) (v2_models.GettableAlerts, error) { 36 // Select the most recently updated alert for each distinct alert. 37 alerts := make(map[string]*v2_models.GettableAlert) 38 for _, alert := range in { 39 if alert.Fingerprint == nil { 40 return nil, errors.New("unexpected nil fingerprint") 41 } 42 if alert.UpdatedAt == nil { 43 return nil, errors.New("unexpected nil updatedAt") 44 } 45 46 key := *alert.Fingerprint 47 if current, ok := alerts[key]; ok { 48 if time.Time(*alert.UpdatedAt).After(time.Time(*current.UpdatedAt)) { 49 alerts[key] = alert 50 } 51 } else { 52 alerts[key] = alert 53 } 54 } 55 56 result := make(v2_models.GettableAlerts, 0, len(alerts)) 57 for _, alert := range alerts { 58 result = append(result, alert) 59 } 60 61 // Mimic Alertmanager which returns alerts ordered by fingerprint (as string). 62 sort.Slice(result, func(i, j int) bool { 63 return *result[i].Fingerprint < *result[j].Fingerprint 64 }) 65 66 return result, nil 67 }