-
-
Notifications
You must be signed in to change notification settings - Fork 611
feat(alerting): Make email alert provider e-mail customizable #1119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
b19ec8e
324d2cd
2aa842b
19727cb
4447cb7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,6 +29,17 @@ type Config struct { | |
| Port int `yaml:"port"` | ||
| To string `yaml:"to"` | ||
|
|
||
| // Strings used in the email body and subject | ||
| // These fields are optional and will be replaced with default values if not set | ||
| TextEmailSubjectTriggered string `yaml:"text-email-subject-triggered,omitempty"` | ||
| TextEmailSubjectResolved string `yaml:"text-email-subject-resolved,omitempty"` | ||
| TextEmailBodyTriggered string `yaml:"text-email-body-triggered,omitempty"` | ||
| TextEmailBodyResolved string `yaml:"text-email-body-resolved,omitempty"` | ||
| TextEmailHeader string `yaml:"text-email-header,omitempty"` | ||
| TextEmailFooter string `yaml:"text-email-footer,omitempty"` | ||
| TextEmailDescription string `yaml:"text-email-description,omitempty"` | ||
| TextIncludeConditionResults *bool `yaml:"text-include-condition-results,omitempty"` | ||
|
|
||
| // ClientConfig is the configuration of the client used to communicate with the provider's target | ||
| ClientConfig *client.Config `yaml:"client,omitempty"` | ||
| } | ||
|
|
@@ -68,6 +79,30 @@ func (cfg *Config) Merge(override *Config) { | |
| if len(override.To) > 0 { | ||
| cfg.To = override.To | ||
| } | ||
| if len(override.TextEmailSubjectTriggered) > 0 { | ||
| cfg.TextEmailSubjectTriggered = override.TextEmailSubjectTriggered | ||
| } | ||
| if len(override.TextEmailSubjectResolved) > 0 { | ||
| cfg.TextEmailSubjectResolved = override.TextEmailSubjectResolved | ||
| } | ||
| if len(override.TextEmailBodyTriggered) > 0 { | ||
| cfg.TextEmailBodyTriggered = override.TextEmailBodyTriggered | ||
| } | ||
| if len(override.TextEmailBodyResolved) > 0 { | ||
| cfg.TextEmailBodyResolved = override.TextEmailBodyResolved | ||
| } | ||
| if len(override.TextEmailHeader) > 0 { | ||
| cfg.TextEmailHeader = override.TextEmailHeader | ||
| } | ||
| if len(override.TextEmailFooter) > 0 { | ||
| cfg.TextEmailFooter = override.TextEmailFooter | ||
| } | ||
| if len(override.TextEmailDescription) > 0 { | ||
| cfg.TextEmailDescription = override.TextEmailDescription | ||
| } | ||
| if override.TextIncludeConditionResults != nil { | ||
| cfg.TextIncludeConditionResults = override.TextIncludeConditionResults | ||
| } | ||
| } | ||
|
|
||
| // AlertProvider is the configuration necessary for sending an alert using SMTP | ||
|
|
@@ -113,7 +148,7 @@ func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, r | |
| } else { | ||
| username = cfg.From | ||
| } | ||
| subject, body := provider.buildMessageSubjectAndBody(ep, alert, result, resolved) | ||
| subject, body := provider.buildMessageSubjectAndBody(cfg, ep, alert, result, resolved) | ||
| m := gomail.NewMessage() | ||
| m.SetHeader("From", cfg.From) | ||
| m.SetHeader("To", strings.Split(cfg.To, ",")...) | ||
|
|
@@ -140,17 +175,40 @@ func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, r | |
| } | ||
|
|
||
| // buildMessageSubjectAndBody builds the message subject and body | ||
| func (provider *AlertProvider) buildMessageSubjectAndBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) (string, string) { | ||
| var subject, message string | ||
| func (provider *AlertProvider) buildMessageSubjectAndBody(cfg *Config, ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) (string, string) { | ||
| var header, footer, subject, message string | ||
| if len(cfg.TextEmailHeader) > 0 { | ||
| header = cfg.TextEmailHeader + "\n\n" | ||
| } | ||
| if len(cfg.TextEmailFooter) > 0 { | ||
| footer = "\n\n" + cfg.TextEmailFooter | ||
| } | ||
| if resolved { | ||
| subject = fmt.Sprintf("[%s] Alert resolved", ep.DisplayName()) | ||
| message = fmt.Sprintf("An alert for %s has been resolved after passing successfully %d time(s) in a row", ep.DisplayName(), alert.SuccessThreshold) | ||
| if len(cfg.TextEmailSubjectResolved) > 0 { | ||
| subject = strings.Replace(cfg.TextEmailSubjectResolved, "{endpoint}", ep.DisplayName(), 1) | ||
|
||
| } else { | ||
| subject = fmt.Sprintf("[%s] Alert resolved", ep.DisplayName()) | ||
| } | ||
| if len(cfg.TextEmailBodyResolved) > 0 { | ||
| message = strings.Replace(strings.Replace(cfg.TextEmailBodyResolved, "{endpoint}", ep.DisplayName(), 1), "{threshold}", string(rune(alert.SuccessThreshold)), 1) | ||
| } else { | ||
| message = fmt.Sprintf("An alert for %s has been resolved after passing successfully %d time(s) in a row", ep.DisplayName(), alert.SuccessThreshold) | ||
| } | ||
| } else { | ||
| subject = fmt.Sprintf("[%s] Alert triggered", ep.DisplayName()) | ||
| message = fmt.Sprintf("An alert for %s has been triggered due to having failed %d time(s) in a row", ep.DisplayName(), alert.FailureThreshold) | ||
| if len(cfg.TextEmailSubjectTriggered) > 0 { | ||
| subject = strings.Replace(cfg.TextEmailSubjectTriggered, "{endpoint}", ep.DisplayName(), 1) | ||
| } else { | ||
| subject = fmt.Sprintf("[%s] Alert triggered", ep.DisplayName()) | ||
| } | ||
| if len(cfg.TextEmailBodyTriggered) > 0 { | ||
| message = strings.Replace(strings.Replace(cfg.TextEmailBodyTriggered, "{endpoint}", ep.DisplayName(), 1), "{threshold}", string(rune(alert.FailureThreshold)), 1) | ||
| } else { | ||
| message = fmt.Sprintf("An alert for %s has been triggered due to having failed %d time(s) in a row", ep.DisplayName(), alert.FailureThreshold) | ||
| } | ||
| } | ||
| var formattedConditionResults string | ||
| if len(result.ConditionResults) > 0 { | ||
| if len(result.ConditionResults) > 0 && (cfg.TextIncludeConditionResults == nil || *cfg.TextIncludeConditionResults) { | ||
| // If the condition results are included, format them | ||
| formattedConditionResults = "\n\nCondition results:\n" | ||
| for _, conditionResult := range result.ConditionResults { | ||
| var prefix string | ||
|
|
@@ -164,9 +222,14 @@ func (provider *AlertProvider) buildMessageSubjectAndBody(ep *endpoint.Endpoint, | |
| } | ||
| var description string | ||
| if alertDescription := alert.GetDescription(); len(alertDescription) > 0 { | ||
| description = "\n\nAlert description: " + alertDescription | ||
| if len(cfg.TextEmailDescription) > 0 { | ||
| description = "\n\n" + strings.Replace(cfg.TextEmailDescription, "{description}", alertDescription, 1) | ||
| } else { | ||
| // If no description is provided, use the alert's description} | ||
| description = "\n\nAlert description: " + alertDescription | ||
| } | ||
| } | ||
| return subject, message + description + formattedConditionResults | ||
| return subject, header + message + description + formattedConditionResults + footer | ||
| } | ||
|
|
||
| // GetDefaultAlert returns the provider's default alert configuration | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm really not sure about this. I'd almost rather have just the subject and the body, and then have a placeholder for the condition results. This would remove the need for the header, the footer, the description and the bool to include/exclude the condition results.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello! I would like to be able to say hello and display information in the footer in the case of an email alert provider, all fields as optional parameter. And everything is backward compatible. Given that not everyone understands the technical details, I would like to optionally hide the condition results section.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I just understood exactly what you wanted. I'll edit it and report back with the changes.