aboutsummaryrefslogtreecommitdiffstats
path: root/modules/collectors.nix
diff options
context:
space:
mode:
authorTim Keller <tjk@tjkeller.xyz>2026-09-02 21:01:46 -0500
committerTim Keller <tjk@tjkeller.xyz>2026-09-02 21:01:46 -0500
commite88a880435ebdda6e50bf16a493abb85b4e80d15 (patch)
treecc59b2810868bcc90bb2772380945fc024f7f5ee /modules/collectors.nix
parenta74c2877571afbfd04584b8821c754e9050b9e72 (diff)
downloadtelemetry-flake-e88a880435ebdda6e50bf16a493abb85b4e80d15.tar.xz
telemetry-flake-e88a880435ebdda6e50bf16a493abb85b4e80d15.zip
add NVMe support, and give the self-test collector the device listHEADmasterflake-modules
Two configurations the modules claimed to support and did not. NVMe drives had no per-drive section. smartctl:bus routes a drive by metric presence -- ATA attribute table, or SCSI grown defect list -- and NVMe emits neither, confirmed against a live smartctl_exporter 0.14.0 on real hardware. With no bus label the smartctl:row join dropped them, so they appeared in Fleet Overview and All Drives but could not be opened. Adds an nvme arm keyed on smartctl_device_percentage_used, verdict rules over the SMART/Health Information log, and a third repeating section. The verdict is BAD on a critical warning, media errors, or available spare below the drive's own threshold, and CAUTION at 90% of rated endurance. num_err_log_entries is deliberately not in it: the NVMe drive in this machine is healthy and sits at 2200, because it counts every command that ever returned an error. smart.devices reached the exporter but not the self-test collector, which always ran its own `smartctl --scan` -- exactly what cannot see drives behind a RAID controller, which is the only reason to set the option. The collector now takes the same PATH[;TYPE] syntax and passes -d through. That means it also has to reproduce the exporter's device label, which is not the basename: /dev/bus/0 as megaraid,1 is bus_0_megaraid_1. Ported buildDeviceLabel with its /dev/disk/by-{id,path}/ prefix stripping and the comma rule, and the scan-time scsi -> auto fallback. Getting this wrong fails silently -- every join in rules/smartctl.yml simply misses. Verified: promtool; a Prometheus fixture covering all three transports plus a megaraid-labelled device, asserting bus and verdict per drive and resolving $ata_device/$sas_device/$nvme_device the way Grafana does; the grid layout; the ExecStart with and without smart.devices; and the collector against this machine's NVMe drive. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JKczN1f66kmLxNBLX37voQ
Diffstat (limited to 'modules/collectors.nix')
-rw-r--r--modules/collectors.nix23
1 files changed, 18 insertions, 5 deletions
diff --git a/modules/collectors.nix b/modules/collectors.nix
index 6f328ee..879516b 100644
--- a/modules/collectors.nix
+++ b/modules/collectors.nix
@@ -148,11 +148,16 @@ in
devices = mkOption {
type = types.listOf types.str;
default = [ ];
- example = [ "/dev/sda" "/dev/nvme0" ];
+ example = [ "/dev/sda" "/dev/nvme0" "/dev/bus/0;megaraid,1" ];
description = ''
- Devices to poll. Empty means auto-discovery via `smartctl --scan`, which is
- correct for direct-attached AHCI/HBA disks. Behind a RAID controller you
- generally have to list devices explicitly with their `-d` type.
+ Devices to poll, shared by the smartctl exporter and the self-test collector.
+ Empty means auto-discovery via `smartctl --scan`, which is correct for
+ direct-attached AHCI/HBA disks. Behind a RAID controller `--scan` returns
+ nothing useful and you have to list the drives explicitly, giving each one its
+ `-d` type after a semicolon: `"/dev/bus/0;megaraid,1"`.
+
+ Note that setting this also turns off the exporter's periodic rescan, so
+ hot-swapped drives will not be picked up until it restarts.
'';
};
@@ -268,7 +273,15 @@ in
systemd.services.smart-selftest-collector = mkIf cfg.smart.enable (mkCollectorService {
description = "Collect SMART self-test history and drive identity";
- execStart = "${lib.getExe collectorPkgs.smart-selftest} --output ${cfg.textfileDir}/smart-selftest.prom";
+ # The same device list the exporter gets. Without this the collector would fall
+ # back to its own `smartctl --scan`, which is exactly what cannot see the drives
+ # in the one configuration the option exists for -- so every row title would read
+ # "identity pending" and self-test history would be empty.
+ execStart = lib.escapeShellArgs ([
+ (lib.getExe collectorPkgs.smart-selftest)
+ "--output"
+ "${cfg.textfileDir}/smart-selftest.prom"
+ ] ++ concatMap (device: [ "--device" device ]) cfg.smart.devices);
# Same shape as the smartctl exporter's own hardening: raw device access to talk
# to the disks, and nothing else.
extraServiceConfig = {