Repository navigation
feat(scsi): record SAS background scan, lifetime temperatures and wear counters - #1045
Merged
Merged
Conversation
Starosdev
force-pushed
the
feat/1024-sas-phy-counters
branch
from
October 28, 2026 11:16
71a4427 to
dd0dfe9
Compare
Starosdev
force-pushed
the
feat/1024-scsi-lifetime-counters
branch
from
October 28, 2026 11:19
b9ea63a to
f82b327
Compare
Starosdev
force-pushed
the
feat/1024-sas-phy-counters
branch
from
October 28, 2026 13:14
dd0dfe9 to
5b0e033
Compare
Starosdev
force-pushed
the
feat/1024-scsi-lifetime-counters
branch
from
October 28, 2026 13:15
f82b327 to
6de95da
Compare
Starosdev
force-pushed
the
feat/1024-sas-phy-counters
branch
from
October 28, 2026 15:00
5b0e033 to
8199ac1
Compare
…r counters (#1024) Three more SCSI log pages reach the attribute table and its history. Background Medium Scan (log page 0x15) was already decoded but had no consumer at all. The drive runs this scan on its own schedule, independently of Scrutiny's self-tests, so the scan counts are how a user sees whether it is still checking its own media; a count that stops rising means scanning is disabled or never completing. The status code and the progress percentage are recorded alongside it, and none of the four is treated as a verdict, because the errors a scan finds are counted by the verify error counters instead. The page's human-readable status string cannot be an attribute value, which is an int64, so it rides in the status reason of the status attribute: that field is already persisted, is carried through downsampling by fn: last, and reaches the API response. The web UI surfaces it as the tooltip on the attribute's status rather than as a column of its own, and a user override on that attribute replaces the reason with the override's own. Both are the cost of borrowing an existing field rather than adding one, and the alternative was not recording the drive's own wording at all. Environmental Reports lifetime temperature extremes were likewise decoded and only the current temperature was used. The drive tracks its own lifetime and since-power-on maxima and minima, so they cover the whole life of the drive rather than the window Scrutiny has been watching, and they survive any gap in collection. One attribute set per reported sensor, keyed by the sensor key smartctl used, and every row names its sensor, because a drive can report more than one and an unnamed row would read as a drive-wide figure. Humidity sensors of the same log page are left alone by an allow-list on the sensor key. Start-Stop Cycle Counter (log page 0x0e) is new. It reports each accumulated mechanical wear counter together with the count the manufacturer rates the drive for, so the rated count becomes the attribute's threshold and the UI reads as "44 of 50000 start/stop cycles". Passing the rating is not reported as a failure: drives routinely outlive their rated cycle count, and the ATA equivalents of these counters (attributes 4, 193 and 225) are not failed either. A user who wants to be told can set a fail_above override. Every field of that page is decoded as a pointer, because smartctl emits each parameter only when the drive reports it: a drive can report start/stop cycles and omit load/unload entirely, and a value type would turn that absence into a permanently-zero attribute. A counter reported without its rated limit gets no threshold rather than a zero one it would always exceed. The lifetime temperature IDs are per sensor, so like the SAS PHY counters they are resolved through ScsiMetadataFor rather than listed in the static metadata map. Nothing here is delta-evaluated: these are state and wear figures, not error counters, so a static value carries no false alarm to suppress. A fully-featured SAS HDD now reports 42 attributes where it reported 16, which is 298 InfluxDB fields per measurement point rather than 116. Downsampling aggregates every SMART field with fn: last, so the added state and wear figures keep their last observed value rather than being averaged. Known wart, recorded rather than fixed here: the two wear counters put a rated specification into the attribute threshold, a field whose only other meaning on SCSI is a failure boundary. The web UI's default attribute filter admits any attribute whose value is below its threshold, so a healthy wear counter shows there. The same clause admits any attribute with a negative value, because "no threshold" is -1, so a drive stored below freezing also shows its lifetime temperature minimum there. The rows are correct and raise nothing; separating "rated limit" from "fail boundary" is the real fix. One group of the issue remains unimplemented: the General Statistics and Performance log page. Several of its counters read zero on the reporting user's own drives, and its logical-block counts duplicate the workload signal the read/write gigabytes-processed attributes already provide. Also drops the temperature parameter of ProcessScsiSmartInfo. It was never read, and the migration path it serves reconstructs attributes from pre-InfluxDB records that carry the grown defect count and the read/write error counters only, so every later SCSI log page is absent there by definition. Documents the verify, background scan and start-stop fields in the OpenAPI collector schema, which had not been updated for any of the three slices.
Starosdev
force-pushed
the
feat/1024-scsi-lifetime-counters
branch
from
October 28, 2026 15:22
6de95da to
9ab98be
Compare
This was referenced Oct 30, 2026
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
Three more SCSI log pages reach the attribute table and its history: Background Medium Scan status (0x15), the Environmental Reports lifetime temperature extremes, and the Start-Stop Cycle Counter (0x0e). Two of the three were already decoded and had no consumer at all.
This is the third of three stacked PRs for #1024.
Base is
feat/1024-sas-phy-counters, notdevelop. Review only the top commit.Type of Change
Related Issues
Related to #1024, delivering groups 2 and 3. Still no closing keyword, because group 5 is not implemented; see below.
Changes Made
temperatureparameter ofProcessScsiSmartInfo. It was never read, and the migration path it serves reconstructs attributes from pre-InfluxDB records that carry the grown defect count and the read/write error counters only.Design decisions worth a reviewer's attention
fail_aboveoverride. An earlier revision made these critical and failable, which turned an old-but-working drive red and sent a notification under the default notify filter.int64and cannot hold it, butStatusReasonis already persisted, is carried throughfn: lastdownsampling, and reaches the API response. Being precise about the UI, since an earlier draft of this body overstated it: the web UI surfaces that field as the tooltip on the attribute's status, not as a column of its own, and it is not graphable. A user override on this attribute also replaces the reason with the override's own. So group 2's four fields are all delivered; the string is the least prominent of them. The alternative was not recording the drive's own wording at all.Not implemented
Issue group 5, the General Statistics and Performance log page, is deliberately absent. Several of its counters read zero on the reporting user's own drives, and its logical-block counts duplicate the workload signal the read/write gigabytes-processed attributes already provide. The reporter says the same in the issue. Worth its own change if wanted.
Testing
The Go test suite was not run locally, by operator policy on this machine; CI is its first run. Checked locally:
go build ./webapp/...andgo vet ./webapp/backend/pkg/...: clean.golangci-lintv2.14.0, the version CI pins:--new-from-revagainst this branch's own base from the real worktree path, plus a full-module run cross-checked against the diff's line ranges. Zero findings on changed lines.smart-scsi-sas-full.json: the PHY fixture plus the three new pages, values taken from thesmartctl-ultrastar-sas-samples.jsonattachment on the issue.TESTING.md's fixture inventory gains rows for all three new fixtures across the stack.Cost of the full stack
A fully-featured SAS HDD now reports 42 attributes where it reported 16, which is 298 InfluxDB fields per measurement point rather than 116. Downsampling aggregates every SMART field with
fn: last, so the added state and wear figures keep their last observed value rather than being averaged. Nothing in the repo caps or chokes on that; the growth is linear in attributes and bounded by device count.Checklist
Known wart, recorded rather than fixed
The two wear counters put a rated specification into the attribute threshold, a field whose only other meaning on SCSI is a failure boundary. The web UI's default attribute filter admits any attribute whose value is below its threshold (
detail.component.ts), so a healthy wear counter appears in the default view. The same clause admits any attribute with a negative value, since "no threshold" is-1, so a drive stored below freezing also shows its lifetime temperature minimum there. The rows are correct and raise nothing, but separating "rated limit" from "fail boundary" is the real fix and belongs in its own change. The test comment now says this rather than claiming the opposite.Additional Notes
Review: required (merging to
developpublishes the testing image throughdeploy-testing.yml, with no separate deploy step).Merge last of the three.