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  }