diff --git a/pkg/alerter/discord/alerter.go b/pkg/alerter/discord/alerter.go index 6ab27ad..77bbfc6 100644 --- a/pkg/alerter/discord/alerter.go +++ b/pkg/alerter/discord/alerter.go @@ -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) }) } @@ -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 { @@ -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()) @@ -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), diff --git a/pkg/alerter/mail/alerter.go b/pkg/alerter/mail/alerter.go index bdfc9d1..ea5d3ef 100644 --- a/pkg/alerter/mail/alerter.go +++ b/pkg/alerter/mail/alerter.go @@ -7,6 +7,7 @@ package mail import ( "context" "fmt" + "time" gomail "gopkg.in/mail.v2" @@ -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) }) } @@ -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 { @@ -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()) @@ -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. diff --git a/pkg/alerter/slack/alerter.go b/pkg/alerter/slack/alerter.go index 3b1f0ca..f2cd13c 100644 --- a/pkg/alerter/slack/alerter.go +++ b/pkg/alerter/slack/alerter.go @@ -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) }) } @@ -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 { @@ -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()) @@ -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), diff --git a/pkg/components/agent/alerter.go b/pkg/components/agent/alerters.go similarity index 100% rename from pkg/components/agent/alerter.go rename to pkg/components/agent/alerters.go diff --git a/pkg/components/agent/exporter.go b/pkg/components/agent/exporters.go similarity index 100% rename from pkg/components/agent/exporter.go rename to pkg/components/agent/exporters.go