From 3133d9f1d0507ade338b0e61ec5426f31183a113 Mon Sep 17 00:00:00 2001 From: Markus Opolka Date: Thu, 12 Nov 2026 13:47:56 +0100 Subject: [PATCH 1/2] Fix alert state when no alerts are included --- cmd/alert.go | 8 +++++++- cmd/alert_test.go | 13 +++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/cmd/alert.go b/cmd/alert.go index 72255bc..81cb7ca 100644 --- a/cmd/alert.go +++ b/cmd/alert.go @@ -110,6 +110,8 @@ inactive = 0`, } var overall goresult.Overall + // We need to count how many times we added an alert for the no-alerts-state + var counterPartialResult int for _, rl := range rules { // If it's not the Alert we're looking for, Skip! @@ -172,6 +174,8 @@ inactive = 0`, sc.SetState(rlStatus) sc.SetOutput(rl.GetOutput()) overall.AddSubcheck(sc) + + counterPartialResult++ } // Handle active alerts @@ -225,6 +229,8 @@ inactive = 0`, rl.Alert = alert sc.SetOutput(rl.GetOutput()) overall.AddSubcheck(sc) + + counterPartialResult++ } } } @@ -239,7 +245,7 @@ inactive = 0`, } // When there are no alerts we add an empty PartialResult just to have consistent output - if counterAlert == 0 { + if counterPartialResult == 0 { sc := goresult.NewPartialResult() sc.SetDefaultState(noAlertsState) sc.SetOutput("No alerts retrieved") diff --git a/cmd/alert_test.go b/cmd/alert_test.go index 604752f..5b08a2b 100644 --- a/cmd/alert_test.go +++ b/cmd/alert_test.go @@ -248,6 +248,19 @@ exit status 2 \_ [CRITICAL] [BlackboxTLS] - Job: [blackbox] on Instance: [https://localhost:443] is firing - value: -6065338.00 - {"alertname":"TLS","icinga":"ok","instance":"https://localhost:443","job":"blackbox","severity":"critical","team":"network"} |total=3 firing=1 pending=1 inactive=1 exit status 2 +`, + }, + { + name: "alert-include-label-no-alerts-state", + server: httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + w.Write(loadTestdata(alertTestDataSet1)) + })), + args: []string{"run", "../main.go", "alert", "--include-label", "foo=bar", "--no-alerts-state", "1", "-P", "true"}, + expected: `[WARNING] - No alerts retrieved +\_ [WARNING] No alerts retrieved +|total=2 firing=1 pending=1 inactive=0 +exit status 1 `, }, { From 8e73f619a2e990a5c182e9177a1d02dddd547aef Mon Sep 17 00:00:00 2001 From: Markus Opolka Date: Thu, 12 Nov 2026 14:12:24 +0100 Subject: [PATCH 2/2] Change perfdata output for alert subcheck to be alert name and status --- README.md | 11 +++-------- cmd/alert.go | 27 +++++++-------------------- 2 files changed, 10 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index fc5219b..9dd2bd3 100644 --- a/README.md +++ b/README.md @@ -156,13 +156,13 @@ Examples: $ check_prometheus alert --name "PrometheusAlertmanagerJobMissing" [CRITICAL] [PrometheusAlertmanagerJobMissing] - Job: [alertmanager] is firing - value: 1.00 \_[CRITICAL] [PrometheusAlertmanagerJobMissing] - Job: [alertmanager] is firing - value: 1.00 - | firing=1 pending=0 inactive=0 + | PrometheusAlertmanagerJobMissing=2 $ check_prometheus a alert --name "PrometheusAlertmanagerJobMissing" --name "PrometheusTargetMissing" [CRITICAL] [PrometheusAlertmanagerJobMissing] - Job: [alertmanager] is firing - value: 1.00 \_[OK] [PrometheusTargetMissing] is inactive \_[CRITICAL] [PrometheusAlertmanagerJobMissing] - Job: [alertmanager] is firing - value: 1.00 - | total=2 firing=1 pending=0 inactive=1 + | PrometheusAlertmanagerJobMissing=2 PrometheusTargetMissing=0 Flags: -S, --label-key-state string Use the given AlertRule label to override the exit state for firing alerts. @@ -201,8 +201,6 @@ $ check_prometheus alert \_[OK] [HostHighCpuLoad] - Job: [alertmanager] \_[CRITICAL] [HighResultLatency] - Job: [prometheus] on Instance: [localhost:9090] is firing - value: 11.00 \_[CRITICAL] [HighResultLatency] - Job: [node-exporter] on Instance: [node-exporter:9100] is firing - value: 10.00 - | total=6 firing=3 pending=0 inactive=3 - ``` #### Checking multiple alerts @@ -213,12 +211,11 @@ $ check_prometheus alert --name "HostHighCpuLoad" --name "HighResultLatency" \_[OK] [HostHighCpuLoad] is inactive \_[CRITICAL] [HighResultLatency] - Job: [prometheus] on Instance: [localhost:9090] is firing - value: 11.00 \_[CRITICAL] [HighResultLatency] - Job: [node-exporter] on Instance: [node-exporter:9100] is firing - value: 10.00 - | total=3 firing=2 pending=0 inactive=1 ``` ```bash $ check_prometheus alert --name "HostHighCpuLoad" --name "PrometheusTargetMissing" -OK - Alerts inactive | total=2 firing=0 pending=0 inactive=2 +OK - Alerts inactive ``` #### Checking alerts via their labels @@ -248,14 +245,12 @@ In Prometheus a "watchdog" or "dead man's switch" is an alert that is always fir $ check_prometheus alert --name Watchdog -W --no-alerts-state 2 [OK] - 1 Alerts: 1 Firing - 0 Pending - 0 Inactive \_ [OK] [Watchdog] is firing - value: 1.00 - {"alertname":"Watchdog","severity":"none"} -|total=1 firing=1 pending=0 inactive=0 ``` ```bash $ check_prometheus alert --name Watchdog -W --no-alerts-state 2 [CRITICAL] No alerts retrieved \_ [CRITICAL] No alerts retrieved -|total=0 firing=0 pending=0 inactive=0 ``` ## License diff --git a/cmd/alert.go b/cmd/alert.go index 81cb7ca..960ddfa 100644 --- a/cmd/alert.go +++ b/cmd/alert.go @@ -39,13 +39,13 @@ inactive = 0`, $ check_prometheus alert --name "PrometheusAlertmanagerJobMissing" [CRITICAL] - [PrometheusAlertmanagerJobMissing] - Job: [alertmanager] is firing - value: 1.00 \_[CRITICAL] [PrometheusAlertmanagerJobMissing] - Job: [alertmanager] is firing - value: 1.00 - | firing=1 pending=0 inactive=0 + | PrometheusAlertmanagerJobMissing=2 $ check_prometheus alert --name "PrometheusAlertmanagerJobMissing" --name "PrometheusTargetMissing" [CRITICAL] [PrometheusAlertmanagerJobMissing] - Job: [alertmanager] is firing - value: 1.00 \_[OK] [PrometheusTargetMissing] is inactive \_[CRITICAL] [PrometheusAlertmanagerJobMissing] - Job: [alertmanager] is firing - value: 1.00 - | total=2 firing=1 pending=0 inactive=1`, + | PrometheusAlertmanagerJobMissing=2 PrometheusTargetMissing=0`, Run: func(_ *cobra.Command, _ []string) { // Convert --no-alerts-state to integer and validate input noAlertsState, err := convertStateToInt(cliAlertConfig.NoAlertsState) @@ -86,21 +86,13 @@ 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 := check.PerfdataList{ - {Label: "total", Value: 0}, - {Label: "firing", Value: 0}, - {Label: "pending", Value: 0}, - {Label: "inactive", Value: 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.ExitWithPerfdata(check.Unknown, pdlist, "No such alert defined") + check.Exit(check.Unknown, "No such alert defined") } - check.ExitWithPerfdata(noAlertsState, pdlist, "No alerts defined") + check.Exit(noAlertsState, "No alerts defined") } // Set initial capacity to reduce memory allocations @@ -172,6 +164,7 @@ inactive = 0`, } sc.SetState(rlStatus) + sc.AddPerfdata(&check.Perfdata{Label: rl.AlertingRule.Name, Value: int(rlStatus)}) sc.SetOutput(rl.GetOutput()) overall.AddSubcheck(sc) @@ -228,6 +221,7 @@ inactive = 0`, // Set the alert in the internal Type to generate the output rl.Alert = alert sc.SetOutput(rl.GetOutput()) + sc.AddPerfdata(&check.Perfdata{Label: rl.AlertingRule.Name, Value: int(rlStatus)}) overall.AddSubcheck(sc) counterPartialResult++ @@ -237,13 +231,6 @@ inactive = 0`, counterAlert := counterFiring + counterPending + counterInactive - 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 counterPartialResult == 0 { sc := goresult.NewPartialResult() @@ -258,7 +245,7 @@ inactive = 0`, counterPending, counterInactive)) - check.ExitWithPerfdata(overall.GetStatus(), perfList, overall.GetOutput()) + check.Exit(overall.GetStatus(), overall.GetOutput()) }, }