smon/nodata.go

134 lines
2.6 KiB
Go
Raw Normal View History

2024-05-25 09:40:40 +02:00
package main
import (
// External
werr "git.gibonuddevalla.se/go/wrappederror"
2024-05-27 23:01:34 +02:00
// Internal
"smon/notification"
2024-05-25 09:40:40 +02:00
// Standard
"database/sql"
2024-05-27 23:01:34 +02:00
"encoding/json"
2024-05-25 09:40:40 +02:00
"time"
)
2024-05-27 23:01:34 +02:00
var (
nodataAreaID int
nodataSectionID int
)
2024-05-25 09:40:40 +02:00
// 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() {
2024-05-27 23:01:34 +02:00
var datapoints []Datapoint
2024-05-25 09:40:40 +02:00
var err error
2024-06-27 09:09:47 +02:00
ticker := time.NewTicker(time.Second * time.Duration(fileConf.NodataInterval))
2024-05-25 09:40:40 +02:00
for {
<-ticker.C
2024-05-27 23:01:34 +02:00
datapoints, err = nodataDatapoints()
2024-05-25 09:40:40 +02:00
if err != nil {
err = werr.Wrap(err).Log()
logger.Error("nodata", "error", err)
continue
}
2024-05-27 23:01:34 +02:00
if len(datapoints) == 0 {
2024-05-25 09:40:40 +02:00
continue
}
2024-05-27 23:01:34 +02:00
for _, datapoint := range datapoints {
nodataNotify(datapoint, "[NODATA] problem")
}
logger.Info("nodata", "problem_ids", datapoints)
}
}
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)
2024-05-25 09:40:40 +02:00
}
2024-05-27 23:01:34 +02:00
return
2024-05-25 09:40:40 +02:00
}
2024-05-27 23:01:34 +02:00
func nodataDatapoints() (datapoints []Datapoint, err error) {
datapoints = []Datapoint{}
2024-05-25 09:40:40 +02:00
var rows *sql.Rows
rows, err = service.Db.Conn.Query(`
UPDATE datapoint
SET
nodata_is_problem = true
FROM (
SELECT
id
FROM
datapoint
WHERE
nodata_problem_seconds > 0 AND
2024-05-25 09:40:40 +02:00
NOT nodata_is_problem AND
extract(EPOCH from (NOW() - last_value))::int > nodata_problem_seconds
) AS subquery
WHERE
datapoint.id = subquery.id
RETURNING
2024-05-27 23:01:34 +02:00
datapoint.id,
datapoint.name
2024-05-25 09:40:40 +02:00
`)
if err != nil {
err = werr.Wrap(err)
return
}
defer rows.Close()
2024-05-27 23:01:34 +02:00
var dp Datapoint
2024-05-25 09:40:40 +02:00
for rows.Next() {
2024-05-27 23:01:34 +02:00
if err = rows.Scan(&dp.ID, &dp.Name); err != nil {
2024-05-25 09:40:40 +02:00
err = werr.Wrap(err)
return
}
2024-05-27 23:01:34 +02:00
datapoints = append(datapoints, dp)
2024-05-25 09:40:40 +02:00
}
return
}