Files
grafana/pkg/services/ngalert/notifier/alert_reception.go
Ganesh Vernekar ecbc98ba5d AlertingNG: Add alert provider and basic structure with dispatcher, silences and delivery stages (#31833)
* AlertingNG: Add alert provider

Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>

* Add unit tests

Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>

* Alertmanager WIP

* Merge alertmanager into notifier

Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>

* Fixes for PR 31833 (#31990)

Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>

* Use alertmanager from upgrad-uuid temporarily to unblock

Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>

* Fix lint

Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>

Co-authored-by: Josue Abreu <josue@grafana.com>
2021-03-16 10:44:52 +01:00

109 lines
2.8 KiB
Go

package notifier
import (
"context"
"time"
"github.com/go-kit/kit/log"
"github.com/prometheus/alertmanager/api/v2/models"
"github.com/prometheus/alertmanager/notify"
"github.com/prometheus/alertmanager/provider"
"github.com/prometheus/alertmanager/provider/mem"
"github.com/prometheus/alertmanager/types"
"github.com/prometheus/common/model"
)
type PostableAlert struct {
models.PostableAlert
// List of receiver names to sent alert to
Receivers []string `json:"receivers"`
}
type AlertProvider struct {
provider.Alerts
logger log.Logger
// TODO(codesome): This stage is temporary to get code out quickly.
// Eventually, the alerts meant directly for receivers and not routing
// will be stored in memory and provided via an iterator, for example
// GetPendingLegacy() AlertIterator, and the external code will use this
// iterator to send to the stage.
stage notify.Stage
}
func NewAlertProvider(s notify.Stage, m types.Marker, l log.Logger) (*AlertProvider, error) {
alerts, err := mem.NewAlerts(context.Background(), m, 30*time.Minute, l)
if err != nil {
return nil, err
}
return &AlertProvider{
Alerts: alerts,
stage: s,
logger: l,
}, nil
}
func (ap *AlertProvider) PutPostableAlert(alerts ...*PostableAlert) error {
var alertsWithReceivers []*PostableAlert
var alertsWithoutReceivers []*types.Alert
for _, a := range alerts {
if len(a.Receivers) > 0 {
alertsWithReceivers = append(alertsWithReceivers, a)
} else {
alertsWithoutReceivers = append(alertsWithoutReceivers, alertForDelivery(a))
}
}
// Without receiver names, alerts go through routing.
if err := ap.Alerts.Put(alertsWithoutReceivers...); err != nil {
return err
}
if len(alertsWithReceivers) == 0 {
return nil
}
// Group alerts with receivers based on the receiver names.
groupedAlerts := make(map[string][]*types.Alert)
for _, a := range alertsWithReceivers {
for _, recv := range a.Receivers {
groupedAlerts[recv] = append(groupedAlerts[recv], alertForDelivery(a))
}
}
for recv, alerts := range groupedAlerts {
ctx := notify.WithReceiverName(context.Background(), recv)
_, _, err := ap.stage.Exec(ctx, ap.logger, alerts...)
if err != nil {
return err
}
}
return nil
}
func alertForDelivery(a *PostableAlert) *types.Alert {
lbls := model.LabelSet{}
annotations := model.LabelSet{}
for k, v := range a.Labels {
lbls[model.LabelName(k)] = model.LabelValue(v)
}
for k, v := range a.Annotations {
annotations[model.LabelName(k)] = model.LabelValue(v)
}
return &types.Alert{
Alert: model.Alert{
Labels: lbls,
Annotations: annotations,
StartsAt: time.Time(a.StartsAt),
EndsAt: time.Time(a.EndsAt),
GeneratorURL: a.GeneratorURL.String(),
},
UpdatedAt: time.Time{}, // TODO(codesome) what should this be?
Timeout: false, // TODO(codesome).
}
}