From 35746fc3876e5e56c674dfbf4acdb1f6f7d296bb Mon Sep 17 00:00:00 2001 From: Markus Kostrzewski Date: Wed, 29 Jan 2025 16:56:11 +0100 Subject: [PATCH] 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. --- main.go | 10 ++++++++++ readjson.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index 3d8ff86..387d80e 100644 --- a/main.go +++ b/main.go @@ -117,6 +117,9 @@ var ( "smartctl.scan-device-type", "Device type to use during automatic scan. Special by-id value forces predictable device names. (repeatable)", ).Strings() + smartctlExcludeENXIO = kingpin.Flag("smartctl.exclude-enxio", + "Whether or not to exclude devices where open() returns with ENXIO", + ).Default("false").Bool() smartctlFakeData = kingpin.Flag("smartctl.fake-data", "The device to monitor (repeatable)", ).Default("false").Hidden().Bool() @@ -132,6 +135,13 @@ func scanDevices(logger *slog.Logger) []Device { for _, d := range scanDevices { deviceName := d.Get("name").String() deviceType := d.Get("type").String() + deviceOpenError := d.Get("open_error").String() + + if *smartctlExcludeENXIO && deviceOpenError == "No such device or address" { + // Ignore devices that do not exist (anymore) or were not properly cleaned up + // This effectively means open(device) returned ENXIO + continue + } // SATA devices are reported as SCSI during scan - fallback to auto scraping if deviceType == "scsi" { diff --git a/readjson.go b/readjson.go index 81f7b12..bcc7a32 100644 --- a/readjson.go +++ b/readjson.go @@ -81,7 +81,7 @@ func readSMARTctl(logger *slog.Logger, device Device) (gjson.Result, bool) { func readSMARTctlDevices(logger *slog.Logger) gjson.Result { logger.Debug("Scanning for devices") - var scanArgs []string = []string{"--json", "--scan"} + var scanArgs []string = []string{"--json", "--scan-open"} for _, d := range *smartctlScanDeviceTypes { scanArgs = append(scanArgs, "--device", d) }