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
1 change: 1 addition & 0 deletions docs/checks/commands/check_drivesize.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ these can be used in filters and thresholds (along with the default attributes):
| id | Drive or id of drive |
| drive_or_id | Drive letter if present if not use id |
| drive_or_name | Drive letter if present if not use name |
| drive_or_name_or_id | Drive letter if present, if not use drive name, if not use the given ID. Useful for volumes without assigned letters on Windows. |
| fstype | Filesystem type |
| mounted | Flag whether drive is mounter (0/1) |
| free | Free (human readable) bytes |
Expand Down
19 changes: 11 additions & 8 deletions pkg/snclient/check_drivesize.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ func (l *CheckDrivesize) Build() *CheckData {
{name: "id", description: "Drive or id of drive"},
{name: "drive_or_id", description: "Drive letter if present if not use id"},
{name: "drive_or_name", description: "Drive letter if present if not use name"},
{name: "drive_or_name_or_id", description: "Drive letter if present, if not use drive name, if not use the given ID. Useful for volumes without assigned letters on Windows."},
{name: "fstype", description: "Filesystem type"},
{name: "mounted", description: "Flag whether drive is mounter (0/1)", unit: UBool},

Expand Down Expand Up @@ -298,7 +299,7 @@ func (l *CheckDrivesize) isExcluded(drive map[string]string, excludes []string)
return false
}

func (l *CheckDrivesize) addMetrics(drive string, check *CheckData, usage *disk.UsageStat, magic float64) {
func (l *CheckDrivesize) addMetrics(metricPrefix string, check *CheckData, usage *disk.UsageStat, magic float64) {
total := usage.Total
if !l.freespaceIgnoreReserved {
total = usage.Used + usage.Free // use this total instead of usage.Total to account in the root reserved space
Expand All @@ -307,34 +308,34 @@ func (l *CheckDrivesize) addMetrics(drive string, check *CheckData, usage *disk.
if 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)
check.AddBytePercentMetrics("free", drive+" free", magic*float64(usage.Free), magic*float64(total))
check.AddBytePercentMetrics("free", metricPrefix+" free", magic*float64(usage.Free), magic*float64(total))
}

// convert '<drive> used_pct' keywords in conditions to '<drive> used %' as that matches the metric name
convertDriveUsagePctMetric1 := fmt.Sprintf("%s used_pct", drive)
convertDriveUsagePctMetric1 := fmt.Sprintf("%s used_pct", metricPrefix)
// metrics are normally added if the operand is simply 'used' , 'used_pct' , 'used_bytes' etc. and do not have a drive prefix
// detect conditions where the operand is named '<drive> used %', this is the default way snclient names percent usage metrics.
// if there is a condition using that as an operand, add usage metrics for that drive as well. during the metrics condition checking, they will take effect.
// this helps to check usage metrics specific to drives.
driveUsagePctMetric := fmt.Sprintf("%s used %%", drive)
driveUsagePctMetric := fmt.Sprintf("%s used %%", metricPrefix)

check.warnThreshold = check.TransformMultipleKeywords([]string{convertDriveUsagePctMetric1}, driveUsagePctMetric, check.warnThreshold)
check.critThreshold = check.TransformMultipleKeywords([]string{convertDriveUsagePctMetric1}, driveUsagePctMetric, check.critThreshold)

if check.HasThreshold(driveUsagePctMetric) || 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)
check.AddBytePercentMetrics("used", drive+" used", magic*float64(usage.Used), magic*float64(total))
check.AddBytePercentMetrics("used", metricPrefix+" used", magic*float64(usage.Used), magic*float64(total))
}
if check.HasThreshold("inodes") || check.HasThreshold("inodes_used") || check.HasThreshold("inodes_used_pct") {
check.warnThreshold = check.TransformMultipleKeywords([]string{"inodes_used_pct", "inodes_used"}, "inodes", check.warnThreshold)
check.critThreshold = check.TransformMultipleKeywords([]string{"inodes_used_pct", "inodes_used"}, "inodes", check.critThreshold)
check.AddPercentMetrics("inodes", drive+" inodes", float64(usage.InodesUsed), float64(usage.InodesTotal))
check.AddPercentMetrics("inodes", metricPrefix+" inodes", float64(usage.InodesUsed), float64(usage.InodesTotal))
}
if 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)
check.AddPercentMetrics("inodes_free", drive+" inodes free", float64(usage.InodesFree), float64(usage.InodesTotal))
check.AddPercentMetrics("inodes_free", metricPrefix+" inodes free", float64(usage.InodesFree), float64(usage.InodesTotal))
}
}

Expand Down Expand Up @@ -452,7 +453,9 @@ func (l *CheckDrivesize) addDriveSizeDetails(check *CheckData, drive map[string]
return
}

l.addMetrics(drive["drive"], check, usage, magic)
// volumes without an assigned drive letter have empty drive["drive"]
// use the volume name or id as fallback
l.addMetrics(drive["drive_or_name_or_id"], check, usage, magic)
}

func (l *CheckDrivesize) getFlagNames(drive map[string]string) []string {
Expand Down
1 change: 1 addition & 0 deletions pkg/snclient/check_drivesize_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ func (l *CheckDrivesize) setDisks(requiredDisks map[string]map[string]string) (e
entry["drive"] = drive
entry["drive_or_id"] = drive
entry["drive_or_name"] = drive
entry["drive_or_name_or_id"] = drive
entry["fstype"] = partition.Fstype
requiredDisks[drive] = entry
}
Expand Down
20 changes: 15 additions & 5 deletions pkg/snclient/check_drivesize_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,10 +325,24 @@ func (l *CheckDrivesize) setDeviceInfo(drive map[string]string) {
}

name := syscall.UTF16ToString(volumeName)
drive["name"] = name

driveOrName := drive["drive"]
if driveOrName == "" {
driveOrName = name
}
if drive["drive_or_name"] == "" {
drive["drive_or_name"] = driveOrName
}

driveOrNameOrID := driveOrName
if driveOrNameOrID == "" {
driveOrNameOrID = drive["drive_or_id"]
}
if drive["drive_or_name_or_id"] == "" {
drive["drive_or_name_or_id"] = driveOrNameOrID
}

drive["readable"] = "1"
if fileSystemFlags&volumeOptReadOnly == 0 {
drive["writable"] = "1"
Expand All @@ -339,15 +353,11 @@ func (l *CheckDrivesize) setDeviceInfo(drive map[string]string) {
if fileSystemFlags&volumeCompressed == 0 {
opts = append(opts, "compress")
}

drive["opts"] = strings.Join(opts, ",")
drive["name"] = name

if drive["fstype"] == "" {
drive["fstype"] = syscall.UTF16ToString(fileSystemName)
}
if drive["drive_or_name"] == "" {
drive["drive_or_name"] = driveOrName
}
}

// gopsutil disk.Partition had an issue with Bitlocker, but a fix was upstreamed
Expand Down
Loading