Skip to content

Commit 35746fc

Browse files
committed
feat: Make handling of invalid devices configurable
Currently, whenever there are devices that are invalid, smartctl_exporter will log an error stating that the device can not be opened, refering to potential issues with missing IDENTIFY_DEVICE structures or low-power-mode-devices. There are, however, also situations where (virtual) devices disappear from the host and are not properly cleaned up. Here, `open()`ing the device in smartctl fails with ENXIO, resulting in the error message "No such device or address" being returned. In this case, the error just clutters the log output for no reason, as there is no reasonable action that can be taken. This MR makes the experienced behavior for such cases configurable. One can either specify the newly added flag `--smartctl.exclude-enxio` to ensure that devices with such problems are simply silently ignored, or decide to ignore the flag and continue experiencing the current behavior.
1 parent 0c86f73 commit 35746fc

File tree

2 files changed

+11
-1
lines changed

2 files changed

+11
-1
lines changed

main.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ var (
117117
"smartctl.scan-device-type",
118118
"Device type to use during automatic scan. Special by-id value forces predictable device names. (repeatable)",
119119
).Strings()
120+
smartctlExcludeENXIO = kingpin.Flag("smartctl.exclude-enxio",
121+
"Whether or not to exclude devices where open() returns with ENXIO",
122+
).Default("false").Bool()
120123
smartctlFakeData = kingpin.Flag("smartctl.fake-data",
121124
"The device to monitor (repeatable)",
122125
).Default("false").Hidden().Bool()
@@ -132,6 +135,13 @@ func scanDevices(logger *slog.Logger) []Device {
132135
for _, d := range scanDevices {
133136
deviceName := d.Get("name").String()
134137
deviceType := d.Get("type").String()
138+
deviceOpenError := d.Get("open_error").String()
139+
140+
if *smartctlExcludeENXIO && deviceOpenError == "No such device or address" {
141+
// Ignore devices that do not exist (anymore) or were not properly cleaned up
142+
// This effectively means open(device) returned ENXIO
143+
continue
144+
}
135145

136146
// SATA devices are reported as SCSI during scan - fallback to auto scraping
137147
if deviceType == "scsi" {

readjson.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func readSMARTctl(logger *slog.Logger, device Device) (gjson.Result, bool) {
8181

8282
func readSMARTctlDevices(logger *slog.Logger) gjson.Result {
8383
logger.Debug("Scanning for devices")
84-
var scanArgs []string = []string{"--json", "--scan"}
84+
var scanArgs []string = []string{"--json", "--scan-open"}
8585
for _, d := range *smartctlScanDeviceTypes {
8686
scanArgs = append(scanArgs, "--device", d)
8787
}

0 commit comments

Comments
 (0)