198 lines
4.1 KiB
Go
198 lines
4.1 KiB
Go
package main
|
|
|
|
import (
|
|
// External
|
|
werr "git.gibonuddevalla.se/go/wrappederror"
|
|
|
|
// Standard
|
|
"database/sql"
|
|
"encoding/json"
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type Problem struct { // {{{
|
|
ID int
|
|
Start time.Time
|
|
End time.Time
|
|
Acknowledged bool
|
|
Datapoints map[string]any
|
|
DatapointValues map[string]any `json:"datapoints"`
|
|
TriggerID int `json:"trigger_id"`
|
|
TriggerName string `json:"trigger_name"`
|
|
AreaName string `json:"area_name"`
|
|
SectionName string `json:"section_name"`
|
|
} // }}}
|
|
|
|
func ProblemsRetrieve(showCurrent bool, from, to time.Time) (problems []Problem, err error) { // {{{
|
|
problems = []Problem{}
|
|
row := service.Db.Conn.QueryRow(`
|
|
SELECT
|
|
jsonb_agg(problems.*)
|
|
FROM (
|
|
(SELECT
|
|
p.id,
|
|
p.start,
|
|
TO_CHAR(p.end, 'YYYY-MM-DD"T"HH24:MI:SSTZH:TZM') AS end,
|
|
p.acknowledged,
|
|
p.datapoints,
|
|
t.id AS trigger_id,
|
|
p.trigger_name AS trigger_name,
|
|
a.name AS area_name,
|
|
s.name AS section_name
|
|
FROM problem p
|
|
LEFT JOIN "trigger" t ON p.trigger_id = t.id
|
|
LEFT JOIN section s ON t.section_id = s.id
|
|
LEFT JOIN area a ON s.area_id = a.id
|
|
WHERE
|
|
CASE
|
|
WHEN NOT $1 THEN p.end IS NULL
|
|
WHEN $1 THEN
|
|
p.start >= $2 AND
|
|
(
|
|
p.end IS NULL OR
|
|
p.end <= $3
|
|
)
|
|
END
|
|
|
|
ORDER BY
|
|
p.start DESC)
|
|
|
|
UNION ALL
|
|
|
|
(SELECT
|
|
-1 AS id,
|
|
dp.last_value,
|
|
null,
|
|
false,
|
|
'{}',
|
|
-1 AS trigger_id,
|
|
CONCAT(
|
|
'NODATA: ',
|
|
dp.name
|
|
) AS trigger_name,
|
|
'[NODATA]' AS area_name,
|
|
'[NODATA]' AS section_name
|
|
FROM datapoint dp
|
|
WHERE
|
|
dp.nodata_is_problem
|
|
ORDER BY
|
|
dp.name ASC)
|
|
) AS problems`,
|
|
showCurrent,
|
|
from,
|
|
to,
|
|
)
|
|
|
|
var jsonBody []byte
|
|
err = row.Scan(&jsonBody)
|
|
if err != nil {
|
|
err = werr.Wrap(err)
|
|
return
|
|
}
|
|
|
|
if jsonBody == nil {
|
|
return
|
|
}
|
|
|
|
err = json.Unmarshal(jsonBody, &problems)
|
|
if err != nil {
|
|
err = werr.Wrap(err)
|
|
}
|
|
return
|
|
} // }}}
|
|
func ProblemStart(trigger Trigger) (problemID int, err error) { // {{{
|
|
row := service.Db.Conn.QueryRow(`
|
|
SELECT COUNT(id)
|
|
FROM problem
|
|
WHERE
|
|
trigger_id = $1 AND
|
|
"end" IS NULL
|
|
GROUP BY trigger_id
|
|
`,
|
|
trigger.ID,
|
|
)
|
|
var openProblems int
|
|
err = row.Scan(&openProblems)
|
|
if err != nil && err != sql.ErrNoRows {
|
|
err = werr.Wrap(err).WithData(trigger.ID)
|
|
return
|
|
}
|
|
|
|
// Open up a new problem if no open exists.
|
|
if openProblems == 0 {
|
|
datapointValuesJson, _ := json.Marshal(trigger.DatapointValues)
|
|
row = service.Db.Conn.QueryRow(
|
|
`INSERT INTO problem(trigger_id, trigger_name, datapoints, trigger_expression) VALUES($1, $2, $3, $4) RETURNING id`,
|
|
trigger.ID,
|
|
trigger.Name,
|
|
datapointValuesJson,
|
|
trigger.Expression,
|
|
)
|
|
err = row.Scan(&problemID)
|
|
if err != nil {
|
|
err = werr.Wrap(err).WithData(trigger)
|
|
}
|
|
}
|
|
return
|
|
} // }}}
|
|
func ProblemClose(trigger Trigger) (problemID int, err error) { // {{{
|
|
row := service.Db.Conn.QueryRow(`UPDATE problem SET "end"=NOW() WHERE trigger_id=$1 AND "end" IS NULL RETURNING id`, trigger.ID)
|
|
err = row.Scan(&problemID)
|
|
|
|
if err == sql.ErrNoRows {
|
|
err = nil
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
err = werr.Wrap(err).WithData(trigger)
|
|
return
|
|
}
|
|
return
|
|
} // }}}
|
|
func ProblemAcknowledge(id int, state bool) (err error) { // {{{
|
|
_, err = service.Db.Conn.Exec(`UPDATE problem SET "acknowledged"=$2 WHERE id=$1`, id, state)
|
|
if err != nil {
|
|
err = werr.Wrap(err).WithData(id)
|
|
return
|
|
}
|
|
return
|
|
} // }}}
|
|
|
|
func (p Problem) FormattedValues() string { // {{{
|
|
out := []string{}
|
|
for key, val := range p.DatapointValues {
|
|
var keyval string
|
|
|
|
switch val.(type) {
|
|
case int:
|
|
keyval = fmt.Sprintf("%s: %d", key, val)
|
|
|
|
case string:
|
|
if str, ok := val.(string); ok {
|
|
timeVal, err := time.Parse(time.RFC3339, str)
|
|
if err == nil {
|
|
formattedTime := timeVal.Format("2006-01-02 15:04:05")
|
|
keyval = fmt.Sprintf("%s: %s", key, formattedTime)
|
|
} else {
|
|
keyval = fmt.Sprintf("%s: %s", key, val)
|
|
}
|
|
}
|
|
|
|
default:
|
|
keyval = fmt.Sprintf("%s: %v", key, val)
|
|
}
|
|
|
|
out = append(out, keyval)
|
|
|
|
}
|
|
sort.Strings(out)
|
|
|
|
return strings.Join(out, "\n")
|
|
} // }}}
|
|
func (p Problem) IsArchived() bool { // {{{
|
|
return !p.End.IsZero()
|
|
} // }}}
|