aboutsummaryrefslogtreecommitdiffstats
path: root/rules/smartctl.yml
diff options
context:
space:
mode:
Diffstat (limited to 'rules/smartctl.yml')
-rw-r--r--rules/smartctl.yml40
1 files changed, 39 insertions, 1 deletions
diff --git a/rules/smartctl.yml b/rules/smartctl.yml
index 3982e06..60a2caa 100644
--- a/rules/smartctl.yml
+++ b/rules/smartctl.yml
@@ -59,6 +59,36 @@ groups:
+ sum by (host, device) (smartctl_write_total_uncorrected_errors)
or (count by (host, device) (smartctl_device_smart_status) * 0)
+ # --- NVMe -----------------------------------------------------------------
+ # NVMe has neither an ATA attribute table nor SCSI error counters. Its health is
+ # in the SMART/Health Information log, which smartctl_exporter emits only when the
+ # interface is nvme.
+ #
+ # Each arm is reduced to {host, device} *before* the `or`, so the union
+ # deduplicates per drive rather than emitting one series per metric name -- the
+ # count is then "did anything fire", which is all smartctl:health_code asks.
+ - record: smartctl:nvme_failing:count
+ expr: |
+ (
+ count by (host, device) (smartctl_device_critical_warning > 0)
+ or
+ count by (host, device) (smartctl_device_media_errors > 0)
+ or
+ count by (host, device) (
+ smartctl_device_available_spare
+ < on(host, device) smartctl_device_available_spare_threshold
+ )
+ )
+ or (count by (host, device) (smartctl_device_smart_status) * 0)
+
+ # percentage_used is the controller's own estimate of consumed write endurance,
+ # where 100 means the drive has reached its rated lifetime. Drives routinely run
+ # well past it, so this is a warning and not a failure.
+ - record: smartctl:nvme_caution:count
+ expr: |
+ count by (host, device) (smartctl_device_percentage_used >= 90)
+ or (count by (host, device) (smartctl_device_smart_status) * 0)
+
# --- Verdict --------------------------------------------------------------
# 0 good, 1 caution, 2 bad. The inner clamp_max on each group keeps two
# simultaneous caution signals from adding up to a false "bad".
@@ -69,22 +99,30 @@ groups:
(max by (host, device) (smartctl_device_smart_status) == bool 0)
+ (smartctl:attr_failing:count > bool 0)
+ (smartctl:scsi_uncorrected:count > bool 0)
+ + (smartctl:nvme_failing:count > bool 0)
, 1)
+ clamp_max(
(smartctl:attr_caution:count > bool 0)
+ (smartctl:scsi_defects:count > bool 0)
+ + (smartctl:nvme_caution:count > bool 0)
, 1)
, 2)
# --- Row labels -----------------------------------------------------------
# Which section of the SMART dashboard a drive belongs in. Keyed on metric
# presence rather than the `protocol` label: only ATA drives report an attribute
- # table, and only SCSI drives report a grown defect list.
+ # table, only SCSI drives report a grown defect list, and smartctl_exporter emits
+ # percentage_used only for nvme. The three are disjoint by construction, so the
+ # order of the `or` arms does not matter -- but a drive matching none of them gets
+ # no bus, drops out of the smartctl:row join, and silently loses its dashboard
+ # section, which is what NVMe used to do.
- record: smartctl:bus
expr: |
label_replace(count by (host, device) (smartctl_device_attribute), "bus", "ata", "", "")
or
label_replace(count by (host, device) (smartctl_scsi_grown_defect_list), "bus", "sas", "", "")
+ or
+ label_replace(count by (host, device) (smartctl_device_percentage_used), "bus", "nvme", "", "")
# The identity string from collectors/smart-selftest.py, made total so a drive
# still gets a row if that collector has not written its file yet. `unless` (not