Alerting: Add support for images in Kafka alerts (#50758)

This commit is contained in:
George Robinson
2022-06-22 11:03:08 +01:00
committed by GitHub
parent 765b995b1b
commit 6e44b36a30
2 changed files with 30 additions and 8 deletions

View File

@@ -13,6 +13,7 @@ import (
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models"
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/services/notifications"
)
@@ -23,6 +24,7 @@ type KafkaNotifier struct {
Endpoint string
Topic string
log log.Logger
images ImageStore
ns notifications.WebhookSender
tmpl *template.Template
}
@@ -41,7 +43,7 @@ func KafkaFactory(fc FactoryConfig) (NotificationChannel, error) {
Cfg: *fc.Config,
}
}
return NewKafkaNotifier(cfg, fc.NotificationService, fc.Template), nil
return NewKafkaNotifier(cfg, fc.ImageStore, fc.NotificationService, fc.Template), nil
}
func NewKafkaConfig(config *NotificationChannelConfig) (*KafkaConfig, error) {
@@ -61,7 +63,7 @@ func NewKafkaConfig(config *NotificationChannelConfig) (*KafkaConfig, error) {
}
// NewKafkaNotifier is the constructor function for the Kafka notifier.
func NewKafkaNotifier(config *KafkaConfig, ns notifications.WebhookSender, t *template.Template) *KafkaNotifier {
func NewKafkaNotifier(config *KafkaConfig, images ImageStore, ns notifications.WebhookSender, t *template.Template) *KafkaNotifier {
return &KafkaNotifier{
Base: NewBase(&models.AlertNotification{
Uid: config.UID,
@@ -73,6 +75,7 @@ func NewKafkaNotifier(config *KafkaConfig, ns notifications.WebhookSender, t *te
Endpoint: config.Endpoint,
Topic: config.Topic,
log: log.New("alerting.notifier.kafka"),
images: images,
ns: ns,
tmpl: t,
}
@@ -102,6 +105,21 @@ func (kn *KafkaNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool,
ruleURL := joinUrlPath(kn.tmpl.ExternalURL.String(), "/alerting/list", kn.log)
bodyJSON.Set("client_url", ruleURL)
var contexts []interface{}
_ = withStoredImages(ctx, kn.log, kn.images,
func(index int, image *ngmodels.Image) error {
if image != nil && image.URL != "" {
imageJSON := simplejson.New()
imageJSON.Set("type", "image")
imageJSON.Set("src", image.URL)
contexts = append(contexts, imageJSON)
}
return nil
}, as...)
if len(contexts) > 0 {
bodyJSON.Set("contexts", contexts)
}
groupKey, err := notify.ExtractGroupKey(ctx)
if err != nil {
return false, err

View File

@@ -16,6 +16,8 @@ import (
func TestKafkaNotifier(t *testing.T) {
tmpl := templateForTests(t)
images := newFakeImageStore(2)
externalURL, err := url.Parse("http://localhost")
require.NoError(t, err)
tmpl.ExternalURL = externalURL
@@ -29,7 +31,7 @@ func TestKafkaNotifier(t *testing.T) {
expMsgError error
}{
{
name: "One alert",
name: "A single alert with image",
settings: `{
"kafkaRestProxy": "http://localhost",
"kafkaTopic": "sometopic"
@@ -38,7 +40,7 @@ func TestKafkaNotifier(t *testing.T) {
{
Alert: model.Alert{
Labels: model.LabelSet{"alertname": "alert1", "lbl1": "val1"},
Annotations: model.LabelSet{"ann1": "annv1", "__dashboardUid__": "abcd", "__panelId__": "efgh"},
Annotations: model.LabelSet{"ann1": "annv1", "__dashboardUid__": "abcd", "__panelId__": "efgh", "__alertScreenshotToken__": "test-image-1"},
},
},
},
@@ -50,6 +52,7 @@ func TestKafkaNotifier(t *testing.T) {
"alert_state": "alerting",
"client": "Grafana",
"client_url": "http://localhost/alerting/list",
"contexts": [{"type": "image", "src": "https://www.example.com/test-image-1.jpg"}],
"description": "[FIRING:1] (val1)",
"details": "**Firing**\n\nValue: [no value]\nLabels:\n - alertname = alert1\n - lbl1 = val1\nAnnotations:\n - ann1 = annv1\nSilence: http://localhost/alerting/silence/new?alertmanager=grafana&matcher=alertname%3Dalert1&matcher=lbl1%3Dval1\nDashboard: http://localhost/d/abcd\nPanel: http://localhost/d/abcd?viewPanel=efgh\n",
"incident_key": "6e3538104c14b583da237e9693b76debbc17f0f8058ef20492e5853096cf8733"
@@ -59,7 +62,7 @@ func TestKafkaNotifier(t *testing.T) {
}`,
expMsgError: nil,
}, {
name: "Multiple alerts",
name: "Multiple alerts with images",
settings: `{
"kafkaRestProxy": "http://localhost",
"kafkaTopic": "sometopic"
@@ -68,12 +71,12 @@ func TestKafkaNotifier(t *testing.T) {
{
Alert: model.Alert{
Labels: model.LabelSet{"alertname": "alert1", "lbl1": "val1"},
Annotations: model.LabelSet{"ann1": "annv1"},
Annotations: model.LabelSet{"ann1": "annv1", "__alertScreenshotToken__": "test-image-1"},
},
}, {
Alert: model.Alert{
Labels: model.LabelSet{"alertname": "alert1", "lbl1": "val2"},
Annotations: model.LabelSet{"ann1": "annv2"},
Annotations: model.LabelSet{"ann1": "annv2", "__alertScreenshotToken__": "test-image-2"},
},
},
},
@@ -85,6 +88,7 @@ func TestKafkaNotifier(t *testing.T) {
"alert_state": "alerting",
"client": "Grafana",
"client_url": "http://localhost/alerting/list",
"contexts": [{"type": "image", "src": "https://www.example.com/test-image-1.jpg"}, {"type": "image", "src": "https://www.example.com/test-image-2.jpg"}],
"description": "[FIRING:2] ",
"details": "**Firing**\n\nValue: [no value]\nLabels:\n - alertname = alert1\n - lbl1 = val1\nAnnotations:\n - ann1 = annv1\nSilence: http://localhost/alerting/silence/new?alertmanager=grafana&matcher=alertname%3Dalert1&matcher=lbl1%3Dval1\n\nValue: [no value]\nLabels:\n - alertname = alert1\n - lbl1 = val2\nAnnotations:\n - ann1 = annv2\nSilence: http://localhost/alerting/silence/new?alertmanager=grafana&matcher=alertname%3Dalert1&matcher=lbl1%3Dval2\n",
"incident_key": "6e3538104c14b583da237e9693b76debbc17f0f8058ef20492e5853096cf8733"
@@ -127,7 +131,7 @@ func TestKafkaNotifier(t *testing.T) {
ctx := notify.WithGroupKey(context.Background(), "alertname")
ctx = notify.WithGroupLabels(ctx, model.LabelSet{"alertname": ""})
pn := NewKafkaNotifier(cfg, webhookSender, tmpl)
pn := NewKafkaNotifier(cfg, images, webhookSender, tmpl)
ok, err := pn.Notify(ctx, c.alerts...)
if c.expMsgError != nil {
require.False(t, ok)