mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Attach image URLs to Google Chat notifications. (#49445)
* Add a test card to see what styles look like * Add text and image cards * Address feedback
This commit is contained in:
parent
b1ba0bc7b0
commit
2ba4f7ed7d
@ -23,6 +23,7 @@ type GoogleChatNotifier struct {
|
||||
URL string
|
||||
log log.Logger
|
||||
ns notifications.WebhookSender
|
||||
images ImageStore
|
||||
tmpl *template.Template
|
||||
content string
|
||||
}
|
||||
@ -41,7 +42,7 @@ func GoogleChatFactory(fc FactoryConfig) (NotificationChannel, error) {
|
||||
Cfg: *fc.Config,
|
||||
}
|
||||
}
|
||||
return NewGoogleChatNotifier(cfg, fc.NotificationService, fc.Template), nil
|
||||
return NewGoogleChatNotifier(cfg, fc.ImageStore, fc.NotificationService, fc.Template), nil
|
||||
}
|
||||
|
||||
func NewGoogleChatConfig(config *NotificationChannelConfig) (*GoogleChatConfig, error) {
|
||||
@ -56,7 +57,7 @@ func NewGoogleChatConfig(config *NotificationChannelConfig) (*GoogleChatConfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewGoogleChatNotifier(config *GoogleChatConfig, ns notifications.WebhookSender, t *template.Template) *GoogleChatNotifier {
|
||||
func NewGoogleChatNotifier(config *GoogleChatConfig, images ImageStore, ns notifications.WebhookSender, t *template.Template) *GoogleChatNotifier {
|
||||
return &GoogleChatNotifier{
|
||||
Base: NewBase(&models.AlertNotification{
|
||||
Uid: config.UID,
|
||||
@ -69,6 +70,7 @@ func NewGoogleChatNotifier(config *GoogleChatConfig, ns notifications.WebhookSen
|
||||
URL: config.URL,
|
||||
log: log.New("alerting.notifier.googlechat"),
|
||||
ns: ns,
|
||||
images: images,
|
||||
tmpl: t,
|
||||
}
|
||||
}
|
||||
@ -138,6 +140,9 @@ func (gcn *GoogleChatNotifier) Notify(ctx context.Context, as ...*types.Alert) (
|
||||
},
|
||||
},
|
||||
}
|
||||
if screenshots := gcn.buildScreenshotCard(ctx, as); screenshots != nil {
|
||||
res.Cards = append(res.Cards, *screenshots)
|
||||
}
|
||||
|
||||
if tmplErr != nil {
|
||||
gcn.log.Warn("failed to template GoogleChat message", "err", tmplErr.Error())
|
||||
@ -176,6 +181,53 @@ func (gcn *GoogleChatNotifier) SendResolved() bool {
|
||||
return !gcn.GetDisableResolveMessage()
|
||||
}
|
||||
|
||||
func (gcn *GoogleChatNotifier) buildScreenshotCard(ctx context.Context, alerts []*types.Alert) *card {
|
||||
card := card{
|
||||
Header: header{
|
||||
Title: "Screenshots",
|
||||
},
|
||||
Sections: []section{},
|
||||
}
|
||||
for _, alert := range alerts {
|
||||
imgToken := getTokenFromAnnotations(alert.Annotations)
|
||||
if len(imgToken) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
timeoutCtx, cancel := context.WithTimeout(ctx, ImageStoreTimeout)
|
||||
imgURL, err := gcn.images.GetURL(timeoutCtx, imgToken)
|
||||
cancel()
|
||||
if err != nil {
|
||||
if !errors.Is(err, ErrImagesUnavailable) {
|
||||
// Ignore errors. Don't log "ImageUnavailable", which means the storage doesn't exist.
|
||||
gcn.log.Warn("failed to retrieve image url from store", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(imgURL) > 0 {
|
||||
section := section{
|
||||
Widgets: []widget{
|
||||
textParagraphWidget{
|
||||
Text: text{
|
||||
Text: fmt.Sprintf("%s: %s", alert.Status(), alert.Name()),
|
||||
},
|
||||
},
|
||||
imageWidget{
|
||||
Image: imageData{
|
||||
ImageURL: imgURL,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
card.Sections = append(card.Sections, section)
|
||||
}
|
||||
}
|
||||
if len(card.Sections) == 0 {
|
||||
return nil
|
||||
}
|
||||
return &card
|
||||
}
|
||||
|
||||
// Structs used to build a custom Google Hangouts Chat message card.
|
||||
// See: https://developers.google.com/hangouts/chat/reference/message-formats/cards
|
||||
type outerStruct struct {
|
||||
@ -208,6 +260,14 @@ type textParagraphWidget struct {
|
||||
Text text `json:"textParagraph"`
|
||||
}
|
||||
|
||||
type imageWidget struct {
|
||||
Image imageData `json:"image"`
|
||||
}
|
||||
|
||||
type imageData struct {
|
||||
ImageURL string `json:"imageUrl"`
|
||||
}
|
||||
|
||||
type text struct {
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
@ -329,10 +329,11 @@ func TestGoogleChatNotifier(t *testing.T) {
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
imageStore := &UnavailableImageStore{}
|
||||
|
||||
ctx := notify.WithGroupKey(context.Background(), "alertname")
|
||||
ctx = notify.WithGroupLabels(ctx, model.LabelSet{"alertname": ""})
|
||||
pn := NewGoogleChatNotifier(cfg, webhookSender, tmpl)
|
||||
pn := NewGoogleChatNotifier(cfg, imageStore, webhookSender, tmpl)
|
||||
ok, err := pn.Notify(ctx, c.alerts...)
|
||||
if c.expMsgError != nil {
|
||||
require.False(t, ok)
|
||||
|
Loading…
Reference in New Issue
Block a user