Skip to content

Commit

Permalink
Make alerters honour context.
Browse files Browse the repository at this point in the history
- All alerters now return from loop when context is cancelled
- Each individual alert context is now given an explicit timeout
  in the case when there's no deadline set for parent context
- Mail alerter now honours context

Fixes #62

Signed-off-by: Vaibhav <[email protected]>
  • Loading branch information
vrongmeal authored and murex971 committed Oct 27, 2020
1 parent 2ad10b3 commit 3589c84
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 11 deletions.
20 changes: 19 additions & 1 deletion pkg/alerter/discord/alerter.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ import (
// serviceName is the name of the service used to send the alert.
const serviceName = "discord"

// defaultTimeout is the time after which the notification is canceled.
const defaultTimeout = time.Minute

func init() {
alerter.Register(serviceName, func() alerter.Alerter { return new(Alerter) })
}
Expand All @@ -45,6 +48,12 @@ func (a *Alerter) Provision(ctx *appcontext.Context, _ alerter.Provider) error {
// Alert sends the notification on discord.
func (a *Alerter) Alert(ctx context.Context, metrics []checker.Metric, amap map[string]alerter.Alert) error {
for i := range metrics {
select {
case <-ctx.Done():
return ctx.Err()
default:
}

metric := metrics[i]
alt, ok := amap[metric.GetCheckID()]
if !ok {
Expand All @@ -62,6 +71,15 @@ func (a *Alerter) Alert(ctx context.Context, metrics []checker.Metric, amap map[

// alert sends an individual notification.
func (a *Alerter) alert(ctx context.Context, metric checker.Metric, alt alerter.Alert) error {
var (
thisCtx = ctx
cancel func()
)
if _, ok := thisCtx.Deadline(); !ok {
thisCtx, cancel = context.WithTimeout(ctx, defaultTimeout)
defer cancel()
}

var msg string
if metric.IsSuccessful() {
msg = fmt.Sprintf("%s is back up", metric.GetCheckName())
Expand All @@ -78,7 +96,7 @@ func (a *Alerter) alert(ctx context.Context, metric checker.Metric, alt alerter.
}

req, err := http.NewRequestWithContext(
ctx,
thisCtx,
http.MethodPost,
alt.GetTarget(),
bytes.NewBuffer(body),
Expand Down
41 changes: 32 additions & 9 deletions pkg/alerter/mail/alerter.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package mail
import (
"context"
"fmt"
"time"

gomail "gopkg.in/mail.v2"

Expand All @@ -20,6 +21,9 @@ import (
// serviceName is the name of the service used to send the alert.
const serviceName = "mail"

// defaultTimeout is the time after which a mail being sent is considered failed.
const defaultTimeout = time.Minute

func init() {
alerter.Register(serviceName, func() alerter.Alerter { return new(Alerter) })
}
Expand All @@ -45,9 +49,15 @@ func (a *Alerter) Provision(ctx *appcontext.Context, prov alerter.Provider) erro
return nil
}

// Alert sends the notification on slack.
// Alert sends the notification on mail.
func (a *Alerter) Alert(ctx context.Context, metrics []checker.Metric, amap map[string]alerter.Alert) error {
for i := range metrics {
select {
case <-ctx.Done():
return ctx.Err()
default:
}

metric := metrics[i]
alt, ok := amap[metric.GetCheckID()]
if !ok {
Expand All @@ -65,6 +75,15 @@ func (a *Alerter) Alert(ctx context.Context, metrics []checker.Metric, amap map[

// alert sends an individual notification.
func (a *Alerter) alert(ctx context.Context, metric checker.Metric, alt alerter.Alert) error {
var (
thisCtx = ctx
cancel func()
)
if _, ok := thisCtx.Deadline(); !ok {
thisCtx, cancel = context.WithTimeout(ctx, defaultTimeout)
defer cancel()
}

var msg string
if metric.IsSuccessful() {
msg = fmt.Sprintf("%s is back up", metric.GetCheckName())
Expand All @@ -75,25 +94,29 @@ func (a *Alerter) alert(ctx context.Context, metric checker.Metric, alt alerter.
}
}

// Receiver's data
to := alt.GetTarget()

// Set E-mail
m := gomail.NewMessage()
m.SetHeader("From", a.sender.User)
m.SetHeader("To", to)
m.SetHeader("Subject", "Pinger Alert: "+msg)
m.SetBody("text/plain", msg)

// Settings for SMTP server
d := gomail.NewDialer(a.sender.Host, int(a.sender.Port), a.sender.User, a.sender.Secret)

// Sending E-Mail
if err := d.DialAndSend(m); err != nil {
return fmt.Errorf("could not send request: %v", err)
}
errChan := make(chan error)
go func(dialer *gomail.Dialer, message *gomail.Message, stream chan<- error) {
if err := d.DialAndSend(m); err != nil {
stream <- fmt.Errorf("could not send request: %v", err)
}
}(d, m, errChan)

return nil
select {
case <-thisCtx.Done():
return thisCtx.Err()
case err := <-errChan:
return err
}
}

// Interface guard.
Expand Down
20 changes: 19 additions & 1 deletion pkg/alerter/slack/alerter.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ import (
// serviceName is the name of the service used to send the alert.
const serviceName = "slack"

// defaultTimeout is the time after which the notification is canceled.
const defaultTimeout = time.Minute

func init() {
alerter.Register(serviceName, func() alerter.Alerter { return new(Alerter) })
}
Expand All @@ -45,6 +48,12 @@ func (a *Alerter) Provision(ctx *appcontext.Context, _ alerter.Provider) error {
// Alert sends the notification on slack.
func (a *Alerter) Alert(ctx context.Context, metrics []checker.Metric, amap map[string]alerter.Alert) error {
for i := range metrics {
select {
case <-ctx.Done():
return ctx.Err()
default:
}

metric := metrics[i]
alt, ok := amap[metric.GetCheckID()]
if !ok {
Expand All @@ -62,6 +71,15 @@ func (a *Alerter) Alert(ctx context.Context, metrics []checker.Metric, amap map[

// alert sends an individual notification.
func (a *Alerter) alert(ctx context.Context, metric checker.Metric, alt alerter.Alert) error {
var (
thisCtx = ctx
cancel func()
)
if _, ok := thisCtx.Deadline(); !ok {
thisCtx, cancel = context.WithTimeout(ctx, defaultTimeout)
defer cancel()
}

var msg string
if metric.IsSuccessful() {
msg = fmt.Sprintf("%s is back up", metric.GetCheckName())
Expand All @@ -78,7 +96,7 @@ func (a *Alerter) alert(ctx context.Context, metric checker.Metric, alt alerter.
}

req, err := http.NewRequestWithContext(
ctx,
thisCtx,
http.MethodPost,
alt.GetTarget(),
bytes.NewBuffer(body),
Expand Down
File renamed without changes.
File renamed without changes.

0 comments on commit 3589c84

Please sign in to comment.