package main 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 datapoints []Datapoint var err error ticker := time.NewTicker(time.Second * time.Duration(fileConf.NodataInterval)) for { <-ticker.C datapoints, err = nodataDatapoints() if err != nil { err = werr.Wrap(err).Log() logger.Error("nodata", "error", err) continue } if len(datapoints) == 0 { continue } 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) } return } func nodataDatapoints() (datapoints []Datapoint, err error) { datapoints = []Datapoint{} 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 NOT nodata_is_problem AND extract(EPOCH from (NOW() - last_value))::int > nodata_problem_seconds ) AS subquery WHERE datapoint.id = subquery.id RETURNING datapoint.id, datapoint.name `) if err != nil { err = werr.Wrap(err) return } defer rows.Close() var dp Datapoint for rows.Next() { if err = rows.Scan(&dp.ID, &dp.Name); err != nil { err = werr.Wrap(err) return } datapoints = append(datapoints, dp) } return }