Skip to content
Closed
25 changes: 13 additions & 12 deletions pkg/snclient/check_drivesize.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,36 +356,37 @@ func (l *CheckDrivesize) addMetrics(metricPrefix string, drive map[string]string
}

driveFreeMetricLabel := fmt.Sprintf("%s free %%", metricPrefix)
if check.HasThreshold(driveFreeMetricLabel) || check.HasThreshold("free") || check.HasThreshold("free_pct") || check.HasThreshold("free_bytes") {
check.warnThreshold = check.TransformMultipleKeywords([]string{"free_pct", "free_bytes"}, "free", check.warnThreshold)
check.critThreshold = check.TransformMultipleKeywords([]string{"free_pct", "free_bytes"}, "free", check.critThreshold)
if check.HasThreshold(driveFreeMetricLabel) || check.HasThreshold("free") || check.HasThreshold("free_pct") || check.HasThreshold("free_bytes") || check.HasThreshold("free %") {
check.warnThreshold = check.TransformMultipleKeywords([]string{"free_pct", "free_bytes", "free %"}, "free", check.warnThreshold)
check.critThreshold = check.TransformMultipleKeywords([]string{"free_pct", "free_bytes", "free %"}, "free", check.critThreshold)
perfLabel := fmt.Sprintf("%s free", metricPrefix)
check.AddBytePercentMetrics("free", perfLabel, magic*float64(usage.Free), magic*float64(total), drive)
check.processMetricsWithSpecializedKeyword("drive", perfLabel, drive)
}

driveUsagePctMetricLabel := fmt.Sprintf("%s used %%", metricPrefix)
if check.HasThreshold(driveUsagePctMetricLabel) || check.HasThreshold("used") || check.HasThreshold("used_pct") || check.HasThreshold("used_bytes") {
check.warnThreshold = check.TransformMultipleKeywords([]string{"used_pct", "used_bytes"}, "used", check.warnThreshold)
check.critThreshold = check.TransformMultipleKeywords([]string{"used_pct", "used_bytes"}, "used", check.critThreshold)
if check.HasThreshold(driveUsagePctMetricLabel) || check.HasThreshold("used") || check.HasThreshold("used_pct") || check.HasThreshold("used_bytes") || check.HasThreshold("used %") {
check.warnThreshold = check.TransformMultipleKeywords([]string{"used_pct", "used_bytes", "used %"}, "used", check.warnThreshold)
check.critThreshold = check.TransformMultipleKeywords([]string{"used_pct", "used_bytes", "used %"}, "used", check.critThreshold)
perfLabel := fmt.Sprintf("%s used", metricPrefix)
check.AddBytePercentMetrics("used", perfLabel, magic*float64(usage.Used), magic*float64(total), drive)
check.processMetricsWithSpecializedKeyword("drive", perfLabel, drive)
}

driveInodesUsedPctMetricLabel := fmt.Sprintf("%s inodes_used %%", metricPrefix)
if check.HasThreshold(driveInodesUsedPctMetricLabel) || check.HasThreshold("inodes") || check.HasThreshold("inodes_used") || check.HasThreshold("inodes_used_pct") {
check.warnThreshold = check.TransformMultipleKeywords([]string{"inodes_used_pct"}, "inodes_used", check.warnThreshold)
check.critThreshold = check.TransformMultipleKeywords([]string{"inodes_used_pct"}, "inodes_used", check.critThreshold)
if check.HasThreshold(driveInodesUsedPctMetricLabel) || check.HasThreshold("inodes") || check.HasThreshold("inodes_used") || check.HasThreshold("inodes_used_pct") ||
check.HasThreshold("inodes_used %") {
check.warnThreshold = check.TransformMultipleKeywords([]string{"inodes_used_pct", "inodes_used %"}, "inodes_used", check.warnThreshold)
check.critThreshold = check.TransformMultipleKeywords([]string{"inodes_used_pct", "inodes_used %"}, "inodes_used", check.critThreshold)
perfLabel := fmt.Sprintf("%s inodes_used", metricPrefix)
check.AddPercentMetrics("inodes_used", perfLabel, float64(usage.InodesUsed), float64(usage.InodesTotal), drive)
check.processMetricsWithSpecializedKeyword("drive", perfLabel, drive)
}

driveInodesFreePctMetricLabel := fmt.Sprintf("%s inodes_free %%", metricPrefix)
if check.HasThreshold(driveInodesFreePctMetricLabel) || check.HasThreshold("inodes_free") || check.HasThreshold("inodes_free_pct") {
check.warnThreshold = check.TransformMultipleKeywords([]string{"inodes_free_pct"}, "inodes_free", check.warnThreshold)
check.critThreshold = check.TransformMultipleKeywords([]string{"inodes_free_pct"}, "inodes_free", check.critThreshold)
if check.HasThreshold(driveInodesFreePctMetricLabel) || check.HasThreshold("inodes_free") || check.HasThreshold("inodes_free_pct") || check.HasThreshold("inodes_free %") {
check.warnThreshold = check.TransformMultipleKeywords([]string{"inodes_free_pct", "inodes_free %"}, "inodes_free", check.warnThreshold)
check.critThreshold = check.TransformMultipleKeywords([]string{"inodes_free_pct", "inodes_free %"}, "inodes_free", check.critThreshold)
perfLabel := fmt.Sprintf("%s inodes_free", metricPrefix)
check.AddPercentMetrics("inodes_free", perfLabel, float64(usage.InodesFree), float64(usage.InodesTotal), drive)
check.processMetricsWithSpecializedKeyword("drive", perfLabel, drive)
Expand Down
66 changes: 66 additions & 0 deletions pkg/snclient/check_drivesize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,69 @@ func TestNonexistingDrive(t *testing.T) {

StopTestAgent(t, snc)
}

func TestRootDriveThresholdsDrivePercentSign(t *testing.T) {
snc := StartTestAgent(t, "")

// This tests the conditions using '[drive] used %' keyword
res := snc.RunCheck("check_drivesize", []string{"drive=/", "warn='/ used %' >= 0", "crit=none"})
assert.Equalf(t, CheckExitWarning, res.State, "state should be WARNING")

res = snc.RunCheck("check_drivesize", []string{"drive=/", "crit='/ used %' >= 0"})
assert.Equalf(t, CheckExitCritical, res.State, "state should be CRITICAL")

res = snc.RunCheck("check_drivesize", []string{"drive=/", "warn='/ used %' >= 0", "crit='/ used %' >= 0"})
assert.Equalf(t, CheckExitCritical, res.State, "state should be CRITICAL")

res = snc.RunCheck("check_drivesize", []string{"drive=/", "warn='/ used %' >= 0", "crit='/ used %' >= 0", "ok='/ used %' >= 0"})
assert.Equalf(t, CheckExitOK, res.State, "state should be CRITICAL")

StopTestAgent(t, snc)
}

func TestRootDriveThresholdsUsedPct(t *testing.T) {
snc := StartTestAgent(t, "")

// This tests the conditions using '[drive] used_pct' keyword
res := snc.RunCheck("check_drivesize", []string{"drive=/", "warn='/ used_pct' >= 0", "crit=none"})
assert.Equalf(t, CheckExitWarning, res.State, "state should be WARNING")

res = snc.RunCheck("check_drivesize", []string{"drive=/", "crit='/ used_pct' >= 0"})
assert.Equalf(t, CheckExitCritical, res.State, "state should be CRITICAL")

res = snc.RunCheck("check_drivesize", []string{"drive=/", "warn='/ used_pct' >= 0", "crit='/ used_pct' >= 0"})
assert.Equalf(t, CheckExitCritical, res.State, "state should be CRITICAL")

res = snc.RunCheck("check_drivesize", []string{"drive=/", "warn='/ used_pct' >= 0", "crit='/ used_pct' >= 0", "ok='/ used_pct' >= 0"})
assert.Equalf(t, CheckExitOK, res.State, "state should be CRITICAL")

StopTestAgent(t, snc)
}

func TestRootDriveThresholdsUsedPercentSign(t *testing.T) {
snc := StartTestAgent(t, "")

// Generic 'used %' keyword, should trigger
res := snc.RunCheck("check_drivesize", []string{"drive=/", "warning='used %' gt 0", "critical=none"})
assert.Equalf(t, CheckExitWarning, res.State, "state should be WARNING")

res = snc.RunCheck("check_drivesize", []string{"drive=/", "critical='used %' gt 0"})
assert.Equalf(t, CheckExitCritical, res.State, "state should be CRITICAL")

StopTestAgent(t, snc)
}

func TestRootDriveSpecializedDriveConditions(t *testing.T) {
snc := StartTestAgent(t, "")

// In critical conditions, the second one is filtered as it contains the drive="/" keyword.
// Since such a condition is present, other critical conditions are filtered out for that entry
res := snc.RunCheck("check_drivesize", []string{"drive=/", "critical='used %' gt 0", "critical=drive eq '/' and 'used_pct' gt 100"})
assert.Equalf(t, CheckExitOK, res.State, "state should be OK")

// Filtering does not work here, since the specialized condition is in the warning threshold, not critical threshold
res = snc.RunCheck("check_drivesize", []string{"drive=/", "critical='used %' gt 0", "warning=drive eq '/' and 'used_pct' gt 0"})
assert.Equalf(t, CheckExitCritical, res.State, "state should be WARNING")

StopTestAgent(t, snc)
}
9 changes: 7 additions & 2 deletions pkg/snclient/check_temperature.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,19 @@ func (l *CheckTemperature) addSensor(check *CheckData, sensor *temperatureStat,

minVal := utils.ToPrecision(sensor.Min, 3)
maxVal := utils.ToPrecision(sensor.High, 3)
var warning, critical ConditionList
if sensor.Min != 0 || sensor.Critical != 0 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how is the expansion of temp and temperature related to Min/Critical? I don't understand why this is necessary.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expansion has nothing to do with it, I am only adding the modified warning/critical thresholds if sensor.Min != 0 or sensor.Critical != 0

Some sensors report min==0 and then get added, only to fail directly in the check_temperature_test

Of course that problem only started happening after the CheckMetric.CheckForThresholds was fixed in the pr.

warning = check.ExpandMetricMacros(check.TransformMultipleKeywords([]string{"temp", "temperature"}, sensorKey, check.warnThreshold), entry)
critical = check.ExpandMetricMacros(check.TransformMultipleKeywords([]string{"temp", "temperature"}, sensorKey, check.critThreshold), entry)
}
check.result.Metrics = append(check.result.Metrics, &CheckMetric{
ThresholdName: sensorKey,
Name: sensorKey,
Value: utils.ToPrecision(sensor.Temperature, 3),
Min: &minVal,
Max: &maxVal,
Warning: check.ExpandMetricMacros(check.TransformMultipleKeywords([]string{"temp", "temperature"}, sensorKey, check.warnThreshold), entry),
Critical: check.ExpandMetricMacros(check.TransformMultipleKeywords([]string{"temp", "temperature"}, sensorKey, check.critThreshold), entry),
Warning: warning,
Critical: critical,
})

check.listData = append(check.listData, entry)
Expand Down
9 changes: 5 additions & 4 deletions pkg/snclient/checkdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,8 @@ func (cd *CheckData) finalizeOutput() (*CheckResult, error) {
cd.setStateFromMaps(finalMacros)
// Metrics are checked last, which also sets the final state
log.Tracef("checking warning, critical, and ok thresholds on check metrics")
cd.CheckMetrics(cd.warnThreshold, cd.critThreshold, cd.okThreshold)
// metrics save their own warning and critical thresholds, but ok thresholds come from check itself
cd.CheckMetrics(cd.okThreshold)

switch {
case cd.result.Output != "":
Expand Down Expand Up @@ -483,16 +484,16 @@ func (cd *CheckData) Check(data map[string]string, warnCond, critCond, okCond Co
}

// CheckMetrics tries warn/crit/ok conditions against given metrics and sets final state accordingly
func (cd *CheckData) CheckMetrics(warnCond, critCond, okCond ConditionList) {
func (cd *CheckData) CheckMetrics(okCond ConditionList) {
// each metric is ran through conditions individually
for _, metric := range cd.result.Metrics {
state := CheckExitOK

if metric.CheckForThresholds(&warnCond) {
if metric.CheckForThresholds(&metric.Warning) {
state = CheckExitWarning
}

if metric.CheckForThresholds(&critCond) {
if metric.CheckForThresholds(&metric.Critical) {
state = CheckExitCritical
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/snclient/checkmetric.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,13 +191,13 @@ func (m *CheckMetric) BuildCheckData() (data map[string]string) {
return data
}

// Metrics have a defined way for specifying key / values
// Returns if at least one condition in the conditionList is found to be correct
//
//nolint:dogsled // only need corrects list here
func (m *CheckMetric) CheckForThresholds(conditionList *ConditionList) (result bool) {
data := m.BuildCheckData()

corrects, _, _, _ := conditionList.performMatches(data, true)

return len(corrects) > 1
return len(corrects) > 0
}