From f77a65ff662d3f1a938c55a4e21e4c6d385d135f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20=C3=85hall?= Date: Mon, 27 May 2024 20:03:25 +0200 Subject: [PATCH 1/2] Added problem state in notification --- main.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/main.go b/main.go index 883457f..ab88c7c 100644 --- a/main.go +++ b/main.go @@ -203,7 +203,7 @@ func entryDatapoint(w http.ResponseWriter, r *http.Request, sess *session.T) { / logger.Error("entry", "error", err) } - // Multiple triggers can use the same datapoint. + // Multiple triggers can use the same datapoint. for _, trigger := range triggers { var out any out, err = trigger.Run() @@ -215,25 +215,25 @@ func entryDatapoint(w http.ResponseWriter, r *http.Request, sess *session.T) { / logger.Debug("entry", "datapoint", dpoint, "value", value, "trigger", trigger, "result", out) var problemID int + var problemState string switch v := out.(type) { case bool: // Trigger returning true - a problem occurred if v { problemID, err = ProblemStart(trigger) - logger.Info("FOO", "problemID", problemID, "err==nil", err == nil) if err != nil { err = werr.Wrap(err).Log() logger.Error("entry", "error", err) } - + problemState = "PROBLEM" } else { // A problem didn't occur. problemID, err = ProblemClose(trigger) - logger.Info("FOO", "problemID", problemID, "err==nil", err == nil) if err != nil { err = werr.Wrap(err).Log() logger.Error("entry", "error", err) } + problemState = "OK" } // Has a change in problem state happened? @@ -244,7 +244,7 @@ func entryDatapoint(w http.ResponseWriter, r *http.Request, sess *session.T) { / logger.Debug("notification", "trigger", trigger.ID, "state", "change") } - err = notificationManager.Send(problemID, []byte(trigger.Name), func(notificationService *notification.Service, err error) { + err = notificationManager.Send(problemID, []byte(problemState+": "+trigger.Name), func(notificationService *notification.Service, err error) { logger.Info( "notification", "service", (*notificationService).GetType(), @@ -611,12 +611,12 @@ func pageDatapointValues(w http.ResponseWriter, r *http.Request, _ *session.T) { PAGE: "datapoint_values", MENU: "datapoints", Icon: "datapoints", - Label: "Values for "+datapoint.Name, + Label: "Values for " + datapoint.Name, } page.Data = map[string]any{ "Datapoint": datapoint, - "Values": values, + "Values": values, } page.Render(w) return From 3af2cd4d17d252b0ed7b8c565f0fb9ad62810db6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20=C3=85hall?= Date: Mon, 27 May 2024 23:01:34 +0200 Subject: [PATCH 2/2] Added nodata notification --- nodata.go | 78 ++++++++++++++++++++++++++++++++++++++++++++------- sql/00015.sql | 3 ++ 2 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 sql/00015.sql 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;