Skip to content

Commit

Permalink
Rework logic when there are no alerts defined
Browse files Browse the repository at this point in the history
Changes default to OK, instead of UNKNOWN.

Added a check to see if the API response contains
alert rules. If not, we exit early.

To add extra flexibility this also adds a --no-alerts-state
flag that can be used to set the desired exit state when no
alerts are found.
  • Loading branch information
martialblog committed Dec 18, 2024
1 parent e562d29 commit c4706c1
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 18 deletions.
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,12 @@ Examples:
| total=2 firing=1 pending=0 inactive=1
Flags:
-h, --help help for alert
-n, --name strings The name of one or more specific alerts to check.
This parameter can be repeated e.G.: '--name alert1 --name alert2'
If no name is given, all alerts will be evaluated
-P, --problems Display only alerts which status is not inactive/OK
-h, --help help for alert
-n, --name strings The name of one or more specific alerts to check.
This parameter can be repeated e.G.: '--name alert1 --name alert2'
If no name is given, all alerts will be evaluated
-T, --no-alerts-state string State to assign when no alerts are found (0, 1, 2, 3, OK, WARNING, CRITICAL, UNKNOWN). If not set this defaults to OK (default "OK")
-P, --problems Display only alerts which status is not inactive/OK. Note that in combination with the --name flag this might result in no alerts being displayed
```
#### Checking all defined alerts
Expand Down
52 changes: 51 additions & 1 deletion cmd/alert.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package cmd

import (
"errors"
"fmt"
"strings"

"github.com/NETWAYS/check_prometheus/internal/alert"
"github.com/NETWAYS/go-check"
Expand All @@ -10,6 +12,15 @@ import (
"github.com/spf13/cobra"
)

type AlertConfig struct {
AlertName []string
Group []string
ProblemsOnly bool
NoAlertsState string
}

var cliAlertConfig AlertConfig

func contains(s string, list []string) bool {
// Tiny helper to see if a string is in a list of strings
for _, elem := range list {
Expand Down Expand Up @@ -40,14 +51,21 @@ inactive = 0`,
\_[CRITICAL] [PrometheusAlertmanagerJobMissing] - Job: [alertmanager] is firing - value: 1.00
| total=2 firing=1 pending=0 inactive=1`,
Run: func(_ *cobra.Command, _ []string) {
// Convert --no-alerts-state to integer and validate input
noAlertsState, err := convertStateToInt(cliAlertConfig.NoAlertsState)
if err != nil {
check.ExitError(fmt.Errorf("invalid value for --no-alerts-state: %s", cliAlertConfig.NoAlertsState))
}

var (
counterFiring int
counterPending int
counterInactive int
)

c := cliConfig.NewClient()
err := c.Connect()
err = c.Connect()

if err != nil {
check.ExitError(err)
}
Expand All @@ -65,6 +83,16 @@ inactive = 0`,
// Get all rules from all groups into a single list
rules := alert.FlattenRules(alerts.Groups)

// If there are no rules we can exit early
if len(rules) == 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")
}
check.ExitRaw(noAlertsState, "No alerts defined")
}

// Set initial capacity to reduce memory allocations
var l int
for _, rl := range rules {
Expand Down Expand Up @@ -164,11 +192,33 @@ inactive = 0`,

func init() {
rootCmd.AddCommand(alertCmd)

fs := alertCmd.Flags()

fs.StringVarP(&cliAlertConfig.NoAlertsState, "no-alerts-state", "T", "OK", "State to assign when no alerts are found (0, 1, 2, 3, OK, WARNING, CRITICAL, UNKNOWN). If not set this defaults to OK")

fs.StringSliceVarP(&cliAlertConfig.AlertName, "name", "n", nil,
"The name of one or more specific alerts to check."+
"\nThis parameter can be repeated e.G.: '--name alert1 --name alert2'"+
"\nIf no name is given, all alerts will be evaluated")

fs.BoolVarP(&cliAlertConfig.ProblemsOnly, "problems", "P", false,
"Display only alerts which status is not inactive/OK. Note that in combination with the --name flag this might result in no alerts being displayed")
}

// Function to convert state to integer.
func convertStateToInt(state string) (int, error) {
state = strings.ToUpper(state)
switch state {
case "OK", "0":
return check.OK, nil
case "WARNING", "1":
return check.Warning, nil
case "CRITICAL", "2":
return check.Critical, nil
case "UNKNOWN", "3":
return check.Unknown, nil
default:
return check.Unknown, errors.New("invalid state")
}
}
22 changes: 20 additions & 2 deletions cmd/alert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func TestAlertCmd(t *testing.T) {
w.Write([]byte(`{"status":"success","data":{"groups":[]}}`))
})),
args: []string{"run", "../main.go", "alert"},
expected: "[UNKNOWN] - 0 Alerts: 0 Firing - 0 Pending - 0 Inactive\n\nexit status 3\n",
expected: "[OK] - No alerts defined\n",
},
{
name: "alert-none-with-problems",
Expand All @@ -47,7 +47,25 @@ func TestAlertCmd(t *testing.T) {
w.Write([]byte(`{"status":"success","data":{"groups":[]}}`))
})),
args: []string{"run", "../main.go", "alert", "--problems"},
expected: "[UNKNOWN] - 0 Alerts: 0 Firing - 0 Pending - 0 Inactive\n\nexit status 3\n",
expected: "[OK] - No alerts defined\n",
},
{
name: "alert-none-with-no-state",
server: httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"status":"success","data":{"groups":[]}}`))
})),
args: []string{"run", "../main.go", "alert", "--no-alerts-state", "3"},
expected: "[UNKNOWN] - No alerts defined\nexit status 3\n",
},
{
name: "alert-none-with-name",
server: httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"status":"success","data":{"groups":[]}}`))
})),
args: []string{"run", "../main.go", "alert", "--name", "MyPreciousAlert"},
expected: "[UNKNOWN] - No such alert defined\nexit status 3\n",
},
{
name: "alert-default",
Expand Down
11 changes: 1 addition & 10 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ import (
"github.com/prometheus/common/config"
)

type AlertConfig struct {
AlertName []string
Group []string
ProblemsOnly bool
}

type Config struct {
BasicAuth string `env:"CHECK_PROMETHEUS_BASICAUTH"`
Bearer string `env:"CHECK_PROMETHEUS_BEARER"`
Expand Down Expand Up @@ -57,10 +51,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
`

var (
cliConfig Config
cliAlertConfig AlertConfig
)
var cliConfig Config

func (c *Config) NewClient() *client.Client {
u := url.URL{
Expand Down

0 comments on commit c4706c1

Please sign in to comment.