github.com/cs3org/reva/v2@v2.27.7/pkg/siteacc/alerting/dispatcher.go (about) 1 // Copyright 2018-2020 CERN 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // In applying this license, CERN does not waive the privileges and immunities 16 // granted to it by virtue of its status as an Intergovernmental Organization 17 // or submit itself to any jurisdiction. 18 19 package alerting 20 21 import ( 22 "strings" 23 24 "github.com/cs3org/reva/v2/pkg/siteacc/config" 25 "github.com/cs3org/reva/v2/pkg/siteacc/data" 26 "github.com/cs3org/reva/v2/pkg/siteacc/email" 27 "github.com/cs3org/reva/v2/pkg/smtpclient" 28 "github.com/pkg/errors" 29 "github.com/prometheus/alertmanager/template" 30 "github.com/rs/zerolog" 31 ) 32 33 // Dispatcher is used to dispatch Prometheus alerts via email. 34 type Dispatcher struct { 35 conf *config.Configuration 36 log *zerolog.Logger 37 38 smtp *smtpclient.SMTPCredentials 39 } 40 41 func (dispatcher *Dispatcher) initialize(conf *config.Configuration, log *zerolog.Logger) error { 42 if conf == nil { 43 return errors.Errorf("no configuration provided") 44 } 45 dispatcher.conf = conf 46 47 if log == nil { 48 return errors.Errorf("no logger provided") 49 } 50 dispatcher.log = log 51 52 // Create the SMTP client 53 if conf.Email.SMTP != nil { 54 dispatcher.smtp = smtpclient.NewSMTPCredentials(conf.Email.SMTP) 55 } 56 57 return nil 58 } 59 60 // DispatchAlerts sends the provided alert(s) via email to the appropriate recipients. 61 func (dispatcher *Dispatcher) DispatchAlerts(alerts *template.Data, accounts data.Accounts) error { 62 for _, alert := range alerts.Alerts { 63 siteID, ok := alert.Labels["site_id"] 64 if !ok { 65 continue 66 } 67 68 // Dispatch the alert to all accounts configured to receive it 69 for _, account := range accounts { 70 if strings.EqualFold(account.Site, siteID) /* && account.Settings.ReceiveAlerts */ { // TODO: Uncomment if alert notifications aren't mandatory anymore 71 if err := dispatcher.dispatchAlert(alert, account); err != nil { 72 // Log errors only 73 dispatcher.log.Err(err).Str("id", alert.Fingerprint).Str("recipient", account.Email).Msg("unable to dispatch alert to user") 74 } 75 } 76 } 77 78 // Dispatch the alert to the global receiver (if set) 79 if dispatcher.conf.Email.NotificationsMail != "" { 80 globalAccount := data.Account{ // On-the-fly account representing the "global alerts receiver" 81 Email: dispatcher.conf.Email.NotificationsMail, 82 FirstName: "ScienceMesh", 83 LastName: "Global Alerts receiver", 84 Site: "Global", 85 Role: "Alerts receiver", 86 Settings: data.AccountSettings{ 87 ReceiveAlerts: true, 88 }, 89 } 90 if err := dispatcher.dispatchAlert(alert, &globalAccount); err != nil { 91 dispatcher.log.Err(err).Str("id", alert.Fingerprint).Str("recipient", globalAccount.Email).Msg("unable to dispatch alert to global alerts receiver") 92 } 93 } 94 } 95 return nil 96 } 97 98 func (dispatcher *Dispatcher) dispatchAlert(alert template.Alert, account *data.Account) error { 99 alertValues := map[string]string{ 100 "Status": alert.Status, 101 "StartDate": alert.StartsAt.String(), 102 "EndDate": alert.EndsAt.String(), 103 "Fingerprint": alert.Fingerprint, 104 105 "Name": alert.Labels["alertname"], 106 "Service": alert.Labels["service_type"], 107 "Instance": alert.Labels["instance"], 108 "Job": alert.Labels["job"], 109 "Severity": alert.Labels["severity"], 110 "Site": alert.Labels["site"], 111 "SiteID": alert.Labels["site_id"], 112 113 "Description": alert.Annotations["description"], 114 "Summary": alert.Annotations["summary"], 115 } 116 117 return email.SendAlertNotification(account, []string{account.Email}, alertValues, *dispatcher.conf) 118 } 119 120 // NewDispatcher creates a new dispatcher instance. 121 func NewDispatcher(conf *config.Configuration, log *zerolog.Logger) (*Dispatcher, error) { 122 dispatcher := &Dispatcher{} 123 if err := dispatcher.initialize(conf, log); err != nil { 124 return nil, errors.Wrap(err, "unable to initialize the alerts dispatcher") 125 } 126 return dispatcher, nil 127 }