diff --git a/nodata.go b/nodata.go index b30a239..ba1e625 100644 --- a/nodata.go +++ b/nodata.go @@ -4,38 +4,95 @@ import ( // External werr "git.gibonuddevalla.se/go/wrappederror" + // Internal + "smon/notification" + // Standard "database/sql" + "encoding/json" "time" ) +var ( + nodataAreaID int + nodataSectionID int +) + // nodataLoop checks if datapoint last_value is larger than the nodata_problem_seconds period and // marks them as problems. They are then notified. func nodataLoop() { - var ids []int + var datapoints []Datapoint var err error // TODO - should be configurable ticker := time.NewTicker(time.Second * 5) for { <-ticker.C - ids, err = nodataDatapointIDs() + datapoints, err = nodataDatapoints() if err != nil { err = werr.Wrap(err).Log() logger.Error("nodata", "error", err) continue } - if len(ids) == 0 { + if len(datapoints) == 0 { continue } - logger.Info("nodata", "problem_ids", ids) + for _, datapoint := range datapoints { + nodataNotify(datapoint, "[NODATA] problem") + } + + logger.Info("nodata", "problem_ids", datapoints) } } -func nodataDatapointIDs() (ids []int, err error) { - ids = []int{} +func nodataNotify(datapoint Datapoint, state string) (err error) { + err = notificationManager.Send(-1, []byte(state+": "+datapoint.Name), func(notificationService *notification.Service, err error) { + logger.Info( + "notification", + "service", (*notificationService).GetType(), + "datapointID", datapoint.ID, + "prio", (*notificationService).GetPrio(), + "ok", true, + ) + + var errBody any + if err != nil { + errBody, _ = json.Marshal(err) + } else { + errBody = nil + } + _, err = service.Db.Conn.Exec( + ` + INSERT INTO notification_send(notification_id, datapoint_nodata_id, uuid, ok, error) + SELECT + id, $3, '', $4, $5 + FROM notification + WHERE + service=$1 AND + prio=$2 + `, + (*notificationService).GetType(), + (*notificationService).GetPrio(), + datapoint.ID, + err == nil, + errBody, + ) + if err != nil { + err = werr.Wrap(err).Log() + logger.Error("entry", "error", err) + } + }) + if err != nil { + err = werr.Wrap(err).Log() + logger.Error("notification", "error", err) + } + return +} + +func nodataDatapoints() (datapoints []Datapoint, err error) { + datapoints = []Datapoint{} var rows *sql.Rows rows, err = service.Db.Conn.Query(` @@ -54,7 +111,8 @@ func nodataDatapointIDs() (ids []int, err error) { WHERE datapoint.id = subquery.id RETURNING - datapoint.id + datapoint.id, + datapoint.name `) if err != nil { @@ -63,13 +121,13 @@ func nodataDatapointIDs() (ids []int, err error) { } defer rows.Close() - var id int + var dp Datapoint for rows.Next() { - if err = rows.Scan(&id); err != nil { + if err = rows.Scan(&dp.ID, &dp.Name); err != nil { err = werr.Wrap(err) return } - ids = append(ids, id) + datapoints = append(datapoints, dp) } return } diff --git a/sql/00015.sql b/sql/00015.sql new file mode 100644 index 0000000..0787d66 --- /dev/null +++ b/sql/00015.sql @@ -0,0 +1,3 @@ +ALTER TABLE public.notification_send ALTER COLUMN problem_id DROP NOT NULL; +ALTER TABLE public.notification_send ADD datapoint_nodata_id int4 NULL; +ALTER TABLE public.notification_send ADD CONSTRAINT notification_send_datapoint_fk FOREIGN KEY (datapoint_nodata_id) REFERENCES public.datapoint(id) ON DELETE CASCADE ON UPDATE CASCADE;