diff --git a/docs/checks/commands/check_drivesize.md b/docs/checks/commands/check_drivesize.md index 4bf3dabb..6148a89e 100644 --- a/docs/checks/commands/check_drivesize.md +++ b/docs/checks/commands/check_drivesize.md @@ -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 | diff --git a/pkg/snclient/check_drivesize.go b/pkg/snclient/check_drivesize.go index 146fc3df..713ccfe4 100644 --- a/pkg/snclient/check_drivesize.go +++ b/pkg/snclient/check_drivesize.go @@ -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}, @@ -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 @@ -307,16 +308,16 @@ 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 ' used_pct' keywords in conditions to ' 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 ' 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) @@ -324,17 +325,17 @@ func (l *CheckDrivesize) addMetrics(drive string, check *CheckData, usage *disk. 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)) } } @@ -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 { diff --git a/pkg/snclient/check_drivesize_other.go b/pkg/snclient/check_drivesize_other.go index e6c789c8..02288aad 100644 --- a/pkg/snclient/check_drivesize_other.go +++ b/pkg/snclient/check_drivesize_other.go @@ -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 } diff --git a/pkg/snclient/check_drivesize_windows.go b/pkg/snclient/check_drivesize_windows.go index c8e82e6a..724b8182 100644 --- a/pkg/snclient/check_drivesize_windows.go +++ b/pkg/snclient/check_drivesize_windows.go @@ -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" @@ -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