Skip to content

Commit

Permalink
Update log alerts (highlight#6847)
Browse files Browse the repository at this point in the history
## Summary
The log alerts and comment alerts were not updated to the new styling.
Give them an update:

Log alert
<img width="508" alt="Screenshot 2023-10-11 at 2 25 12 PM"
src="https://github.com/highlight/highlight/assets/17744174/b7db5636-4aa1-4c75-ad55-2b0fcb6ad5ce">

<img width="542" alt="Screenshot 2023-10-11 at 2 33 16 PM"
src="https://github.com/highlight/highlight/assets/17744174/22654ea6-7d0b-48d3-b1c2-01fea43ddc60">

Comment alert
<img width="499" alt="Screenshot 2023-10-11 at 2 59 34 PM"
src="https://github.com/highlight/highlight/assets/17744174/72103b49-d8c7-4655-b933-27f6c45ee4bb">

## How did you test this change?
1) Create a new log alert that is easy to fire
2) Add a Discord and Slack channel to alert
3) Run the log alert watcher locally: `make start-log-alerts-watch`
- [ ] Confirm alert is sent to Slack
- [ ] Confirm alert is sent to Discord
4) Comment on a session
- [ ] Confirm alert is sent to appropriate Slack channel
5) Reply to comment
- [ ] Confirm alert is sent to appropriate Slack channel

## Are there any deployment considerations?
N/A

## Does this work require review from our design team?
Yes
  • Loading branch information
SpennyNDaJets authored and lewisl9029 committed Nov 16, 2023
1 parent b8f2e35 commit 503a938
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 46 deletions.
1 change: 1 addition & 0 deletions backend/alerts/integrations/discord/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,7 @@ func (bot *Bot) SendLogAlert(channelId string, payload integrations.LogAlertPayl

embed := newMessageEmbed()
embed.Title = "Highlight Log Alert"
embed.Color = RED_ALERT
embed.Description = fmt.Sprintf("*%s* is currently %s the threshold.", payload.Name, aboveStr)
embed.Fields = fields

Expand Down
11 changes: 5 additions & 6 deletions backend/jobs/log-alerts/log-alerts.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,19 +152,18 @@ func processLogAlert(ctx context.Context, DB *gorm.DB, TDB timeseries.DB, MailCl
if alert.Query != "" {
queryStr = fmt.Sprintf(`for query *%s* `, alert.Query)
}
message := fmt.Sprintf(
"🚨 *%s* fired!\nLog count %swas %s the threshold.\n"+
body := fmt.Sprintf(
"Log count %swas %s the threshold.\n"+
"_Count_: %d | _Threshold_: %d",
alert.Name,
queryStr,
aboveStr,
count,
alert.CountThreshold,
)

log.WithContext(ctx).Info(message)
log.WithContext(ctx).WithField("alert_id", alert.ID).Info(fmt.Sprintf("Firing alert for %s", alert.Name))

if err := alert.SendSlackAlert(ctx, DB, &model.SendSlackAlertForLogAlertInput{Message: message, Workspace: &workspace, StartDate: start, EndDate: end}); err != nil {
if err := alert.SendSlackAlert(ctx, DB, &model.SendSlackAlertForLogAlertInput{Body: body, Workspace: &workspace, StartDate: start, EndDate: end}); err != nil {
log.WithContext(ctx).Error("error sending slack alert for metric monitor", err)
}

Expand All @@ -190,7 +189,7 @@ func processLogAlert(ctx context.Context, DB *gorm.DB, TDB timeseries.DB, MailCl
if alert.Query != "" {
queryStr = fmt.Sprintf(`for query <b>%s</b> `, alert.Query)
}
message = fmt.Sprintf(
message := fmt.Sprintf(
"<b>%s</b> fired! Log count %sis currently %s the threshold.<br>"+
"<em>Count</em>: %d | <em>Threshold</em>: %d"+
"<br><br>"+
Expand Down
40 changes: 35 additions & 5 deletions backend/model/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -2599,7 +2599,7 @@ func (obj *MetricMonitor) SendSlackAlert(ctx context.Context, input *SendSlackAl
}

type SendSlackAlertForLogAlertInput struct {
Message string
Body string
Workspace *Workspace
StartDate time.Time
EndDate time.Time
Expand Down Expand Up @@ -2637,12 +2637,42 @@ func (obj *LogAlert) SendSlackAlert(ctx context.Context, db *gorm.DB, input *Sen

alertUrl := GetLogAlertURL(obj.ProjectID, obj.Query, input.StartDate, input.EndDate)

previewText := fmt.Sprintf("%s fired!", obj.Name)

var headerBlockSet []slack.Block
headerBlock := slack.NewTextBlockObject(slack.MarkdownType, fmt.Sprintf("*%s* fired!", obj.Name), false, false)
headerBlockSet = append(headerBlockSet, slack.NewSectionBlock(headerBlock, nil, nil))

var bodyBlockSet []slack.Block
logBlock := slack.NewTextBlockObject(slack.MarkdownType, input.Body, false, false)

var actionBlocks []slack.BlockElement
button := slack.NewButtonBlockElement(
"",
"click",
slack.NewTextBlockObject(
slack.PlainTextType,
"View Logs",
false,
false,
),
)
button.URL = alertUrl
actionBlocks = append(actionBlocks, button)

bodyBlockSet = append(bodyBlockSet, slack.NewSectionBlock(logBlock, nil, nil))
bodyBlockSet = append(bodyBlockSet, slack.NewActionBlock("", actionBlocks...))

attachment := &slack.Attachment{
Color: RED_ALERT,
Blocks: slack.Blocks{BlockSet: bodyBlockSet},
}

log.WithContext(ctx).Info("Sending Slack Alert for Log Alert")

// send message
for _, channel := range channels {
if channel.WebhookChannel != nil {
message := fmt.Sprintf("%s\n<%s|View Logs>", input.Message, alertUrl)
slackChannelId := *channel.WebhookChannelID
slackChannelName := *channel.WebhookChannel

Expand All @@ -2655,12 +2685,12 @@ func (obj *LogAlert) SendSlackAlert(ctx context.Context, db *gorm.DB, input *Sen
log.WithContext(ctx).WithFields(log.Fields{"project_id": obj.ProjectID}).Error(e.Wrap(err, "failed to join slack channel while sending welcome message"))
}
}
_, _, err := slackClient.PostMessage(slackChannelId, slack.MsgOptionText(message, false),
_, _, err := slackClient.PostMessage(slackChannelId, slack.MsgOptionText(previewText, false), slack.MsgOptionBlocks(headerBlockSet...), slack.MsgOptionAttachments(*attachment),
slack.MsgOptionDisableLinkUnfurl(), /** Disables showing a preview of any links that are in the Slack message.*/
slack.MsgOptionDisableMediaUnfurl(), /** Disables showing a preview of any links that are in the Slack message.*/
)
if err != nil {
log.WithContext(ctx).WithFields(log.Fields{"workspace_id": input.Workspace.ID, "message": fmt.Sprintf("%+v", message)}).
log.WithContext(ctx).WithFields(log.Fields{"workspace_id": input.Workspace.ID, "message": previewText}).
Error(e.Wrap(err, "error sending slack msg via bot api for welcome message"))
}

Expand Down Expand Up @@ -2882,7 +2912,7 @@ func (obj *Alert) sendSlackAlert(ctx context.Context, db *gorm.DB, alertID int,
var headerBlock *slack.TextBlockObject
if input.FirstErrorAlert {
previewText = fmt.Sprintf("New Error Alert: %s", previewEvent)
headerBlock = slack.NewTextBlockObject(slack.MarkdownType, fmt.Sprintf("*❇️ New Error Alert: %d Recent Occurrences*", *input.ErrorsCount), false, false)
headerBlock = slack.NewTextBlockObject(slack.MarkdownType, fmt.Sprintf("*New Error Alert: %d Recent Occurrences ❇️*", *input.ErrorsCount), false, false)
attachmentColor = YELLOW_ALERT
} else {
previewText = fmt.Sprintf("Error Alert: %s", previewEvent)
Expand Down
72 changes: 37 additions & 35 deletions backend/private-graph/graph/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -931,13 +931,15 @@ func (r *Resolver) SendEmailAlert(
return nil
}

func (r *Resolver) CreateSlackBlocks(admin *model.Admin, viewLink, commentText, action string, subjectScope string, additionalContext *string) (blockSet slack.Blocks) {
func (r *Resolver) CreateSlackBlocks(admin *model.Admin, viewLink, commentText, action string, subjectScope string, additionalContext *string) ([]slack.Block, *slack.Attachment) {
determiner := "a"
if subjectScope == "error" {
determiner = "an"
}

// Header
var headerBlockSet []slack.Block

message := fmt.Sprintf("*You were %s in %s %s comment.*", action, determiner, subjectScope)
if admin.Email != nil && *admin.Email != "" {
message = fmt.Sprintf("*%s %s you in %s %s comment.*", *admin.Email, action, determiner, subjectScope)
Expand All @@ -946,38 +948,30 @@ func (r *Resolver) CreateSlackBlocks(admin *model.Admin, viewLink, commentText,
message = fmt.Sprintf("*%s %s you in %s %s comment.*", *admin.Name, action, determiner, subjectScope)
}

blockSet.BlockSet = append(blockSet.BlockSet,
slack.NewSectionBlock(
&slack.TextBlockObject{Type: slack.MarkdownType, Text: message},
nil, nil,
),
)
headerBlock := slack.NewTextBlockObject(slack.MarkdownType, message, false, false)
headerBlockSet = append(headerBlockSet, slack.NewSectionBlock(headerBlock, nil, nil))

// comment message
blockSet.BlockSet = append(blockSet.BlockSet,
slack.NewSectionBlock(
&slack.TextBlockObject{Type: slack.MarkdownType, Text: fmt.Sprintf("> %s", commentText)},
nil, nil,
),
)
var bodyBlockSet []slack.Block

commentBlock := slack.NewTextBlockObject(slack.MarkdownType, fmt.Sprintf("> %s", commentText), false, false)

detailsString := ""
// info on the session/error
if subjectScope == "error" {
blockSet.BlockSet = append(blockSet.BlockSet,
slack.NewSectionBlock(
&slack.TextBlockObject{Type: slack.MarkdownType, Text: fmt.Sprintf("*Error* %s\n %s", viewLink, *additionalContext)},
nil, nil,
),
)
detailsString = fmt.Sprintf("*Error* %s", viewLink)
} else if subjectScope == "session" {
blockSet.BlockSet = append(blockSet.BlockSet,
slack.NewSectionBlock(
&slack.TextBlockObject{Type: slack.MarkdownType, Text: fmt.Sprintf("*Session* %s\n%s", viewLink, *additionalContext)},
nil, nil,
),
)
detailsString = fmt.Sprintf("*Session* %s", viewLink)
}
if additionalContext != nil {
detailsString = fmt.Sprintf("%s\n%s", detailsString, *additionalContext)
}

detailsBlock := slack.NewTextBlockObject(slack.MarkdownType, detailsString, false, false)

// button
var actionBlocks []slack.BlockElement

button := slack.NewButtonBlockElement(
"",
"click",
Expand All @@ -988,29 +982,36 @@ func (r *Resolver) CreateSlackBlocks(admin *model.Admin, viewLink, commentText,
false,
),
)
button.WithStyle("primary")
button.URL = viewLink
blockSet.BlockSet = append(blockSet.BlockSet,
slack.NewActionBlock("action_block", button),
)

blockSet.BlockSet = append(blockSet.BlockSet, slack.NewDividerBlock())
return
actionBlocks = append(actionBlocks, button)

bodyBlockSet = append(bodyBlockSet, slack.NewSectionBlock(commentBlock, nil, nil))
bodyBlockSet = append(bodyBlockSet, slack.NewSectionBlock(detailsBlock, nil, nil))
bodyBlockSet = append(bodyBlockSet, slack.NewActionBlock("", actionBlocks...))

attachment := &slack.Attachment{
Color: "#6c37f4",
Blocks: slack.Blocks{BlockSet: bodyBlockSet},
}

return headerBlockSet, attachment
}

func (r *Resolver) SendSlackThreadReply(ctx context.Context, workspace *model.Workspace, admin *model.Admin, viewLink, commentText, action string, subjectScope string, threadIDs []int) error {
if workspace.SlackAccessToken == nil {
return nil
}
slackClient := slack.New(*workspace.SlackAccessToken)
blocks := r.CreateSlackBlocks(admin, viewLink, commentText, action, subjectScope, nil)
headerBlock, bodyAttachment := r.CreateSlackBlocks(admin, viewLink, commentText, action, subjectScope, nil)
for _, threadID := range threadIDs {
thread := &model.CommentSlackThread{}
if err := r.DB.Where(&model.CommentSlackThread{Model: model.Model{ID: threadID}}).Take(&thread).Error; err != nil {
return e.Wrap(err, "error querying slack thread")
}
opts := []slack.MsgOption{
slack.MsgOptionBlocks(blocks.BlockSet...),
slack.MsgOptionBlocks(headerBlock...),
slack.MsgOptionAttachments(*bodyAttachment),
slack.MsgOptionDisableLinkUnfurl(), /** Disables showing a preview of any links that are in the Slack message.*/
slack.MsgOptionDisableMediaUnfurl(), /** Disables showing a preview of any media that are in the Slack message.*/
slack.MsgOptionTS(thread.ThreadTS),
Expand All @@ -1031,7 +1032,7 @@ func (r *Resolver) SendSlackAlertToUser(ctx context.Context, workspace *model.Wo
}
slackClient := slack.New(*workspace.SlackAccessToken)

blocks := r.CreateSlackBlocks(admin, viewLink, commentText, action, subjectScope, additionalContext)
headerBlock, bodyAttachment := r.CreateSlackBlocks(admin, viewLink, commentText, action, subjectScope, additionalContext)

// Prepare to upload the screenshot to the user's Slack workspace.
// We do this instead of upload it to S3 or somewhere else to defer authorization checks to Slack.
Expand Down Expand Up @@ -1071,7 +1072,8 @@ func (r *Resolver) SendSlackAlertToUser(ctx context.Context, workspace *model.Wo
log.WithContext(ctx).Warn(e.Wrap(err, "failed to join slack channel"))
}
opts := []slack.MsgOption{
slack.MsgOptionBlocks(blocks.BlockSet...),
slack.MsgOptionBlocks(headerBlock...),
slack.MsgOptionAttachments(*bodyAttachment),
slack.MsgOptionDisableLinkUnfurl(), /** Disables showing a preview of any links that are in the Slack message.*/
slack.MsgOptionDisableMediaUnfurl(), /** Disables showing a preview of any media that are in the Slack message.*/
}
Expand Down

0 comments on commit 503a938

Please sign in to comment.