fix: OCP/SMART metric correctness, endurance from percent_used, GUID info metric - #16
Merged
Conversation
added 2 commits
June 4, 2026 11:29
- data_units_read/written help now states the values are in thousands of 512-byte units (bytes = value * 512000), per the NVMe spec. - physical_media_units_* help corrected from "1000h sector size" to bytes (128-bit byte counter split lo/hi), per the OCP spec. - bad_user/system_nand_blocks_normalized changed from counter to gauge: normalized 0-100 values decrease over time, so rate()/increase() on a counter would misread them as resets.
Document every magic constant and unit assumption (512000 = 1000*512 data-unit-to-byte factor, 1e12 decimal TB, 3000 P/E cycles, 365*5 warranty window, 273.15 Kelvin offset) and note which rules are stateful (rate/predict_linear) and must stay in Prometheus. Add device:DWPD_observed, the actual drive-writes-per-day computed from the host write rate, complementing the existing rated DWPD_calculated.
added 2 commits
June 4, 2026 11:51
The GUID is a 128-bit identifier; read via gjson .Float() it was always
0/garbage. Add a label-metric provider that emits a constant-1 gauge
nvme_log_page_guid_info{guid="..."} carrying the GUID as a label, the
standard Prometheus pattern for string identifiers.
Replace the hard-coded 3000 P/E-cycle guess with the device's own nvme_percent_used (the vendor wear estimate, which already accounts for real endurance and write amplification): - DRL_calculated is now clamp_min(100 - nvme_percent_used, 0) - TBW_calculated is derived from percent_used (guarded to >0) - removed TBW_numerator (the *3000 rule) Keep 365*5 (warranty window) as it is contractual, not telemetry; keep the spec unit constants (512000, 1e12, 273.15). Add device:DWPD_lifetime (total host writes / capacity / powered-on days), a constant-free, single-scrape DWPD.
added 2 commits
June 4, 2026 11:57
… projection Two distinct rules for two distinct questions: - device:DRL_calculated: accurate remaining-life % from the vendor's own percent_used (how much life is left now). - device:DRL_days_remaining: estimated days to end-of-life at the current write rate. The wear rate comes from the continuous data-units counter (smooth), the endurance size from percent_used. Replaces device:projected_DRL_4h, whose predict_linear over the coarse integer percent_used produced a flat/jumpy slope regardless of window.
- Add the missing root '{' — the JSON was invalid and could not be
imported into Grafana at all.
- Fix broken metric references:
- device:projected_DRL_8h (rule never existed) -> device:DRL_days_remaining,
retitled to estimated days-to-EOL with day units and proper thresholds.
- node_nvme_info (not exported) -> nvme_physical_size, with the Disk Info
table regrouped on the real info labels (model_number, serial_number,
firmware, generic_path) plus capacity.
- Remove a stray 'nvme_num' target.
- Add panels for the new recording rules: device:DWPD_observed and
device:DWPD_lifetime.
- Correct stale/copy-paste descriptions and titles (DRL gauge now reflects
percent_used basis, DWPD reflects telemetry-derived TBW, unsafe-shutdowns
description, truncated 'Host Read/Write Commands' titles, data-units-written
node scoping).
- Drop the hard-coded node IP from the OCP row title and the baked-in node
selection; clean dashboard title and null the id for clean import.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Correctness improvements to the OCP/SMART metrics and the recording rules that derive endurance values. Unit semantics verified against the NVMe Base Spec and OCP Datacenter NVMe SSD Spec.
Exporter (
cmd/collector.go,pkg/provider.go)nvme_data_units_read/writtenhelp: now states values are in thousands of 512-byte units (bytes = value × 512000).nvme_physical_media_units_*help: corrected from "1000h sector size" to bytes (128-bit counter split lo/hi), per OCP spec.nvme_bad_user/system_nand_blocks_normalizedchanged counter → gauge (normalized 0-100 values decrease; counters would misread that as resets).nvme_log_page_guid→nvme_log_page_guid_info: the GUID is a 128-bit identifier; read as a float it was always 0/garbage. Now emitted as a constant-1 info metricnvme_log_page_guid_info{guid="..."}via a new label-metric provider — the standard Prometheus pattern for string identifiers.Recording rules (
resources/prom/nvme_ocp.yml)3000P/E-cycle guess. Endurance now derives from the device's ownnvme_percent_used(vendor wear estimate, which already accounts for real endurance and write amplification):device:DRL_calculated=clamp_min(100 - nvme_percent_used, 0)device:TBW_calculatedderived frompercent_used, guarded to> 0device:TBW_numerator365*5(warranty window — contractual, not telemetry) and the spec unit constants (512000,1e12,273.15), all documented.device:DWPD_lifetime— total host writes ÷ capacity ÷ powered-on days; constant-free and single-scrape. Plusdevice:DWPD_observed(windowed rate) from the earlier commit.rate,predict_linear) and must stay in Prometheus.Behavioral notes
nvme_log_page_guidis renamed tonvme_log_page_guid_info(the old metric was always 0, so no real consumer).device:DRL_calculated/device:TBW_calculatedkeep their names but change basis (3000-model → vendorpercent_used); dashboards keep working, values become more accurate.device:projected_DRL_4hnow uses a[6h]lookback becausepercent_usedis coarse.Still not done (breaking — needs a decision)
_totalsuffix; fixing is breaking (renames metrics referenced by these rules + dashboards).Testing
go build ./...✅ ·go vet ./...✅ ·nvme_ocp.ymlparses as valid YAML (promtool unavailable locally).