Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 26 additions & 29 deletions cmd/alert.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import (

"github.com/NETWAYS/check_prometheus/internal/alert"
"github.com/NETWAYS/go-check"
"github.com/NETWAYS/go-check/perfdata"
"github.com/NETWAYS/go-check/result"
goresult "github.com/NETWAYS/go-check/result"
"github.com/prometheus/common/model"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -88,7 +87,7 @@ inactive = 0`,
// If there are no rules we can exit early
if len(rules) == 0 {
// Just an empty PerfdataList to have consistent perfdata output
pdlist := perfdata.PerfdataList{
pdlist := check.PerfdataList{
{Label: "total", Value: 0},
{Label: "firing", Value: 0},
{Label: "pending", Value: 0},
Expand All @@ -98,10 +97,10 @@ inactive = 0`,
// Since the user is expecting the state of a certain alert and
// it that is not present it might be noteworthy.
if cliAlertConfig.AlertName != nil {
check.ExitRaw(check.Unknown, "No such alert defined", "|", pdlist.String())
check.ExitWithPerfdata(check.Unknown, pdlist, "No such alert defined")
}

check.ExitRaw(noAlertsState, "No alerts defined", "|", pdlist.String())
check.ExitWithPerfdata(noAlertsState, pdlist, "No alerts defined")
}

// Set initial capacity to reduce memory allocations
Expand All @@ -110,7 +109,7 @@ inactive = 0`,
l *= len(rl.AlertingRule.Alerts)
}

var overall result.Overall
var overall goresult.Overall

for _, rl := range rules {
// If it's not the Alert we're looking for, Skip!
Expand All @@ -128,7 +127,7 @@ inactive = 0`,
alertMatchedExclude, regexErr := matches(rl.AlertingRule.Name, cliAlertConfig.ExcludeAlerts)

if regexErr != nil {
check.ExitRaw(check.Unknown, "Invalid regular expression provided:", regexErr.Error())
check.Exit(check.Unknown, "Invalid regular expression provided:", regexErr.Error())
}

if alertMatchedExclude {
Expand All @@ -140,7 +139,7 @@ inactive = 0`,
labelsMatchedExclude, regexErr := matchesLabel(rl.AlertingRule.Labels, cliAlertConfig.ExcludeLabels)

if regexErr != nil {
check.ExitRaw(check.Unknown, "Invalid regular expression provided:", regexErr.Error())
check.Exit(check.Unknown, "Invalid regular expression provided:", regexErr.Error())
}

if len(cliAlertConfig.ExcludeLabels) > 0 && labelsMatchedExclude {
Expand All @@ -152,6 +151,7 @@ inactive = 0`,
if len(rl.AlertingRule.Alerts) == 0 {
// Counting states for perfdata. We don't use the state-label override here
// to have the acutal count from Prometheus
//nolint: exhaustive
switch rl.GetStatus("") {
case 0:
counterInactive++
Expand All @@ -161,16 +161,16 @@ inactive = 0`,
counterFiring++
}

sc := result.NewPartialResult()
sc := goresult.NewPartialResult()

rlStatus := rl.GetStatus(cliAlertConfig.StateLabelKey)
// If the negate flag is set we negate this state
if cliAlertConfig.FlipExitState {
rlStatus = negateStatus(rlStatus)
}

_ = sc.SetState(rlStatus)
sc.Output = rl.GetOutput()
sc.SetState(rlStatus)
sc.SetOutput(rl.GetOutput())
overall.AddSubcheck(sc)
}

Expand All @@ -180,6 +180,7 @@ inactive = 0`,
for _, alert := range rl.AlertingRule.Alerts {
// Counting states for perfdata. We don't use the state-label override here
// to have the acutal count from Prometheus
//nolint: exhaustive
switch rl.GetStatus("") {
case 0:
counterInactive++
Expand All @@ -192,7 +193,7 @@ inactive = 0`,
labelsMatchedInclude, regexErr := matchesLabel(alert.Labels, cliAlertConfig.IncludeLabels)

if regexErr != nil {
check.ExitRaw(check.Unknown, "Invalid regular expression provided:", regexErr.Error())
check.Exit(check.Unknown, "Invalid regular expression provided:", regexErr.Error())
}

if len(cliAlertConfig.IncludeLabels) > 0 && !labelsMatchedInclude {
Expand All @@ -203,59 +204,55 @@ inactive = 0`,
labelsMatchedExclude, regexErr := matchesLabel(alert.Labels, cliAlertConfig.ExcludeLabels)

if regexErr != nil {
check.ExitRaw(check.Unknown, "Invalid regular expression provided:", regexErr.Error())
check.Exit(check.Unknown, "Invalid regular expression provided:", regexErr.Error())
}

if len(cliAlertConfig.ExcludeLabels) > 0 && labelsMatchedExclude {
// If the alert labels matches here we can skip it.
continue
}

sc := result.NewPartialResult()
sc := goresult.NewPartialResult()

rlStatus := rl.GetStatus(cliAlertConfig.StateLabelKey)
// If the negate flag is set we negate this state
if cliAlertConfig.FlipExitState {
rlStatus = negateStatus(rlStatus)
}

_ = sc.SetState(rlStatus)
sc.SetState(rlStatus)
// Set the alert in the internal Type to generate the output
rl.Alert = alert
sc.Output = rl.GetOutput()
sc.SetOutput(rl.GetOutput())
overall.AddSubcheck(sc)
}
}
}

counterAlert := counterFiring + counterPending + counterInactive

perfList := perfdata.PerfdataList{
perfList := check.PerfdataList{
{Label: "total", Value: counterAlert},
{Label: "firing", Value: counterFiring},
{Label: "pending", Value: counterPending},
{Label: "inactive", Value: counterInactive},
}

// When there are no alerts we add an empty PartialResult just to have consistent output
if len(overall.PartialResults) == 0 {
sc := result.NewPartialResult()
// We already make sure it's valid
//nolint: errcheck
if l == 0 {
sc := goresult.NewPartialResult()
sc.SetDefaultState(noAlertsState)
sc.Output = "No alerts retrieved"
sc.SetOutput("No alerts retrieved")
overall.AddSubcheck(sc)
}

overall.PartialResults[0].Perfdata = append(overall.PartialResults[0].Perfdata, perfList...)

overall.Summary = fmt.Sprintf("%d Alerts: %d Firing - %d Pending - %d Inactive",
overall.SetOKSummary(fmt.Sprintf("%d Alerts: %d Firing - %d Pending - %d Inactive",
counterAlert,
counterFiring,
counterPending,
counterInactive)
counterInactive))

check.ExitRaw(overall.GetStatus(), overall.GetOutput())
check.ExitWithPerfdata(overall.GetStatus(), perfList, overall.GetOutput())
},
}

Expand Down Expand Up @@ -300,7 +297,7 @@ func init() {
}

// Function to convert state to integer.
func convertStateToInt(state string) (int, error) {
func convertStateToInt(state string) (check.Status, error) {
state = strings.ToUpper(state)
switch state {
case "OK", "0":
Expand Down Expand Up @@ -364,7 +361,7 @@ func matchesLabel(labels model.LabelSet, labelsToMatch []string) (bool, error) {
}

// negateStatus turns an OK state into critical and a warning/critical state into OK
func negateStatus(state int) int {
func negateStatus(state check.Status) check.Status {
switch state {
case check.OK:
return check.Critical
Expand Down
8 changes: 4 additions & 4 deletions cmd/alert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func TestAlertCmd(t *testing.T) {
w.Write([]byte(`{"status":"success","data":{"groups":[]}}`))
})),
args: []string{"run", "../main.go", "alert"},
expected: "[OK] - No alerts defined | total=0 firing=0 pending=0 inactive=0\n",
expected: "[OK] - No alerts defined|total=0 firing=0 pending=0 inactive=0\n",
},
{
name: "alert-none-with-problems",
Expand All @@ -58,7 +58,7 @@ func TestAlertCmd(t *testing.T) {
w.Write([]byte(`{"status":"success","data":{"groups":[]}}`))
})),
args: []string{"run", "../main.go", "alert", "--problems"},
expected: "[OK] - No alerts defined | total=0 firing=0 pending=0 inactive=0\n",
expected: "[OK] - No alerts defined|total=0 firing=0 pending=0 inactive=0\n",
},
{
name: "alert-none-with-no-state",
Expand All @@ -67,7 +67,7 @@ func TestAlertCmd(t *testing.T) {
w.Write([]byte(`{"status":"success","data":{"groups":[]}}`))
})),
args: []string{"run", "../main.go", "alert", "--no-alerts-state", "3"},
expected: "[UNKNOWN] - No alerts defined | total=0 firing=0 pending=0 inactive=0\nexit status 3\n",
expected: "[UNKNOWN] - No alerts defined|total=0 firing=0 pending=0 inactive=0\nexit status 3\n",
},
{
name: "alert-none-with-name",
Expand All @@ -76,7 +76,7 @@ func TestAlertCmd(t *testing.T) {
w.Write([]byte(`{"status":"success","data":{"groups":[]}}`))
})),
args: []string{"run", "../main.go", "alert", "--name", "MyPreciousAlert"},
expected: "[UNKNOWN] - No such alert defined | total=0 firing=0 pending=0 inactive=0\nexit status 3\n",
expected: "[UNKNOWN] - No such alert defined|total=0 firing=0 pending=0 inactive=0\nexit status 3\n",
},
{
name: "alert-default",
Expand Down
24 changes: 11 additions & 13 deletions cmd/health.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ Ready: Checks the readiness of an endpoint, which returns OK if the Prometheus s
$ check_prometheus --bearer secrettoken health --ready
OK - Prometheus Server is Ready. | statuscode=200`,
Run: func(_ *cobra.Command, _ []string) {
var (
rc int
)
var rc check.Status

overall := result.Overall{}

Expand All @@ -49,11 +47,11 @@ Ready: Checks the readiness of an endpoint, which returns OK if the Prometheus s

partialResult := result.NewPartialResult()

_ = partialResult.SetState(rc)
partialResult.Output = output
partialResult.SetState(rc)
partialResult.SetOutput(output)
overall.AddSubcheck(partialResult)

check.ExitRaw(overall.GetStatus(), overall.GetOutput())
check.Exit(overall.GetStatus(), overall.GetOutput())
}

if cliConfig.Info {
Expand All @@ -65,18 +63,18 @@ Ready: Checks the readiness of an endpoint, which returns OK if the Prometheus s

partialResult := result.NewPartialResult()

_ = partialResult.SetState(rc)
partialResult.SetState(rc)

partialResult.Output = "Prometheus Server information\n\n" +
partialResult.SetOutput("Prometheus Server information\n\n" +
"Version: " + info.Version + "\n" +
"Branch: " + info.Branch + "\n" +
"BuildDate: " + info.BuildDate + "\n" +
"BuildUser: " + info.BuildUser + "\n" +
"Revision: " + info.Revision
"Revision: " + info.Revision)

overall.AddSubcheck(partialResult)

check.ExitRaw(overall.GetStatus(), overall.GetOutput())
check.Exit(overall.GetStatus(), overall.GetOutput())
}

// Getting the health status is the default
Expand All @@ -87,11 +85,11 @@ Ready: Checks the readiness of an endpoint, which returns OK if the Prometheus s
}

partialResult := result.NewPartialResult()
_ = partialResult.SetState(rc)
partialResult.Output = output
partialResult.SetState(rc)
partialResult.SetOutput(output)
overall.AddSubcheck(partialResult)

check.ExitRaw(overall.GetStatus(), overall.GetOutput())
check.Exit(overall.GetStatus(), overall.GetOutput())
},
}

Expand Down
31 changes: 15 additions & 16 deletions cmd/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"time"

"github.com/NETWAYS/go-check"
"github.com/NETWAYS/go-check/perfdata"
goresult "github.com/NETWAYS/go-check/result"
"github.com/prometheus/common/model"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -41,9 +40,9 @@ type Number interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64
}

func generatePerfdata[T Number](metric string, value T, warning, critical *check.Threshold) perfdata.Perfdata {
func generatePerfdata[T Number](metric string, value T, warning, critical *check.Threshold) check.Perfdata {
// We trim the trailing "} from the string, so that the Perfdata won't have a trailing _
return perfdata.Perfdata{
return check.Perfdata{
Label: replacer.Replace(metric),
Value: value,
Warn: warning,
Expand Down Expand Up @@ -120,23 +119,23 @@ Note: Time range values e.G. 'go_memstats_alloc_bytes_total[0s]' only the latest
partial := goresult.NewPartialResult()

if crit.DoesViolate(numberValue) {
_ = partial.SetState(check.Critical)
partial.SetState(check.Critical)
} else if warn.DoesViolate(numberValue) {
_ = partial.SetState(check.Warning)
partial.SetState(check.Warning)
} else {
_ = partial.SetState(check.OK)
partial.SetState(check.OK)
}

// Format the metric and RC output for console output
partial.Output = generateMetricOutput(sample.Metric.String(), sample.Value.String())
partial.SetOutput(generateMetricOutput(sample.Metric.String(), sample.Value.String()))

// Generate Perfdata from API return
if math.IsInf(numberValue, 0) || math.IsNaN(numberValue) {
continue
}

perf := generatePerfdata(sample.Metric.String(), numberValue, warn, crit)
partial.Perfdata.Add(&perf)
partial.AddPerfdata(&perf)
overall.AddSubcheck(partial)
}

Expand All @@ -155,15 +154,15 @@ Note: Time range values e.G. 'go_memstats_alloc_bytes_total[0s]' only the latest
partial := goresult.NewPartialResult()

if crit.DoesViolate(numberValue) {
_ = partial.SetState(check.Critical)
partial.SetState(check.Critical)
} else if warn.DoesViolate(numberValue) {
_ = partial.SetState(check.Warning)
partial.SetState(check.Warning)
} else {
_ = partial.SetState(check.OK)
partial.SetState(check.OK)
}

// Format the metric and RC output for console output
partial.Output = generateMetricOutput(samplepair.String(), samplepair.Value.String())
partial.SetOutput(generateMetricOutput(samplepair.String(), samplepair.Value.String()))

valueString := samplepair.Value.String()

Expand All @@ -173,20 +172,20 @@ Note: Time range values e.G. 'go_memstats_alloc_bytes_total[0s]' only the latest

// Generate Perfdata from API return
if !math.IsInf(numberValue, 0) && !math.IsNaN(numberValue) {
partial.Perfdata.Add(&pd)
partial.AddPerfdata(&pd)
}
}

overall.AddSubcheck(partial)
}
}

var appendum string
if len(warnings) != 0 {
appendum := fmt.Sprintf("HTTP Warnings: %v", strings.Join(warnings, ", "))
overall.Summary = overall.GetOutput() + appendum
appendum = fmt.Sprintf("HTTP Warnings: %v", strings.Join(warnings, ", "))
}

check.ExitRaw(overall.GetStatus(), overall.GetOutput())
check.Exit(overall.GetStatus(), overall.GetOutput(), appendum)
},
}

Expand Down
Loading
Loading