Skip to content

feat: Add SMART attribute override functionality#835

Open
AIndoria wants to merge 2 commits into
AnalogJ:masterfrom
AIndoria:master
Open

feat: Add SMART attribute override functionality#835
AIndoria wants to merge 2 commits into
AnalogJ:masterfrom
AIndoria:master

Conversation

@AIndoria

@AIndoria AIndoria commented Dec 7, 2025

Copy link
Copy Markdown

This PR introduces a new 'attribute_overrides' section to scrutiny.yaml. It allows users to:

  • Ignore specific SMART attributes (preventing false/old but irrelevant positives).
  • Force status (pass/warn/fail) for specific attributes.
  • Set custom thresholds (warn_above/fail_above) for attribute values.

This addresses issues like #522, #332, and #369 where vendor-specific attributes or specific scenarios cause incorrect failure reports or prevent custom thresholding. Partially I was tired of an error from early age of a disk showing the entire disk as FAILED despite perfect repeated badblocks testing. Note, I did code portions of this and used help from an LLM for other portions. I did also test this fairly significantly - but would appreciate testing from other users if possible.

This also includes unit tests for the new logic.

This feature allows users to override SMART attribute behavior at the host
level. Users can now:

- Ignore specific attributes entirely.
- Force a specific status (passed, warn, failed) for an attribute.
- Set custom thresholds (warn_above, fail_above) for attribute values.

This is configured via a new  section in the
scrutiny.yaml file.
Copilot AI review requested due to automatic review settings December 7, 2025 19:15

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces SMART attribute override functionality to allow users to customize how specific SMART attributes are evaluated. The feature enables ignoring problematic attributes, forcing specific statuses, and setting custom thresholds to address false positives from vendor-specific attributes.

Key changes:

  • New AttributeOverride model with support for ignore, force_status, and threshold-based overrides
  • Integration of override logic into the SMART data processing pipeline with device status recalculation
  • Comprehensive unit test coverage for override scenarios

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
webapp/backend/pkg/models/attribute_override.go Introduces the AttributeOverride model defining the structure for user-configured attribute overrides
webapp/backend/pkg/database/scrutiny_repository_device_smart_attributes.go Implements core override logic including loading, matching, and applying overrides to SMART attributes
webapp/backend/pkg/database/scrutiny_repository_device_smart_attributes_test.go Adds comprehensive unit tests covering various override scenarios (ignore, force_status, thresholds, mismatches)
webapp/backend/pkg/database/scrutiny_repository_device.go Updates device status persistence to always overwrite (not merge) to properly clear old failure flags
webapp/backend/pkg/web/handler/upload_device_metrics.go Changes status update logic to always persist evaluated status, ensuring old failures are cleared when resolved
webapp/backend/pkg/config/config.go Adds default configuration for smart.attribute_overrides
webapp/backend/pkg/web/server_test.go Adds mock expectations for new InfluxDB initialization config keys to fix test failures
example.scrutiny.yaml Adds documentation and examples for the new attribute override configuration

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
func (sr *scrutinyRepository) SaveSmartAttributes(ctx context.Context, wwn string, collectorSmartData collector.SmartInfo) (measurements.Smart, error) {
sr.logger.Infof("SaveSmartAttributes called for wwn=%s", wwn)

Copilot AI Dec 7, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The Infof log at this line will log on every SMART attribute save operation, which could be quite frequent in production. Consider using Debugf instead for this type of operational logging to avoid log verbosity.

Suggested change
sr.logger.Infof("SaveSmartAttributes called for wwn=%s", wwn)
sr.logger.Debugf("SaveSmartAttributes called for wwn=%s", wwn)

Copilot uses AI. Check for mistakes.
overrides = append(overrides, ao)
}

sr.logger.Infof("Loaded %d attribute overrides from config", len(overrides))

Copilot AI Dec 7, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] This Infof log is called on every SMART data upload and will execute the loop iteration even when there are no overrides configured (most common case). The logging should be moved inside the if len(overrides) == 0 check or reduced to Debugf level to avoid excessive logging in production.

Suggested change
sr.logger.Infof("Loaded %d attribute overrides from config", len(overrides))
sr.logger.Debugf("Loaded %d attribute overrides from config", len(overrides))

Copilot uses AI. Check for mistakes.
for attrKey, attrData := range smart.Attributes {
override := sr.matchingOverride(smart.DeviceProtocol, wwn, attrKey, overrides)
if override != nil {
sr.logger.Infof("Applying override to attribute %s: action=%s", attrKey, override.Action)

Copilot AI Dec 7, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] This Infof log is inside a loop over all attributes and will generate a log entry for every matched override on every SMART upload. Consider using Debugf instead to reduce log verbosity in production.

Suggested change
sr.logger.Infof("Applying override to attribute %s: action=%s", attrKey, override.Action)
sr.logger.Debugf("Applying override to attribute %s: action=%s", attrKey, override.Action)

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +33
// apply host-level attribute overrides before persisting or notifying
attributeOverrides := sr.loadAttributeOverrides()
sr.applyAttributeOverrides(&deviceSmartData, wwn, attributeOverrides)

Copilot AI Dec 7, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The loadAttributeOverrides() function is called on every SMART data save operation, causing repeated configuration parsing and map allocation. Consider caching the parsed overrides (e.g., loading once during repository initialization or using a cached value with a reload mechanism) to improve performance, especially for systems with many devices reporting frequently.

Copilot uses AI. Check for mistakes.
}

sr.logger.Debugf(" MATCH!")
return &o

Copilot AI Dec 7, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returning a pointer to the loop variable o can lead to unexpected behavior. The loop variable is reused in each iteration, so all returned pointers could point to the same memory location with the last iteration's value. Copy the value or return by index: return &overrides[ndx] instead of return &o.

Suggested change
return &o
return &overrides[ndx]

Copilot uses AI. Check for mistakes.
Comment on lines +314 to +315
case "ignore":
return setAttributeStatus(attr, pkg.AttributeStatusPassed, "Ignored by attribute override")

Copilot AI Dec 7, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "ignore" action is handled twice: once at the beginning (lines 305-307) and again in the switch statement (lines 314-315). The first check makes the switch case unreachable. Remove the duplicate case from the switch statement.

Suggested change
case "ignore":
return setAttributeStatus(attr, pkg.AttributeStatusPassed, "Ignored by attribute override")

Copilot uses AI. Check for mistakes.
@kaysond

kaysond commented Feb 2, 2026

Copy link
Copy Markdown
Collaborator

@AIndoria - can you rebase this?

@AIndoria

AIndoria commented Feb 3, 2026

Copy link
Copy Markdown
Author

@AIndoria - can you rebase this?

No problems. I haven't taken a look at this lately since I first touched it, I'll fix the dumb mistakes I made that Copilot pointed out and then cherry pick.

@kaysond

kaysond commented Feb 5, 2026

Copy link
Copy Markdown
Collaborator

@AIndoria - can you rebase this?

No problems. I haven't taken a look at this lately since I first touched it, I'll fix the dumb mistakes I made that Copilot pointed out and then cherry pick.

Would you mind also taking a look at this - #375 and #374 ? I believe your config updates would take care of this too right?

@AIndoria

AIndoria commented Feb 6, 2026

Copy link
Copy Markdown
Author

@AIndoria - can you rebase this?

No problems. I haven't taken a look at this lately since I first touched it, I'll fix the dumb mistakes I made that Copilot pointed out and then cherry pick.

Would you mind also taking a look at this - #375 and #374 ? I believe your config updates would take care of this too right?

Ironically, it does seem like Starosdev#118 did the ugly-work for most of us. Fixed the blunders I made and integrated it. Opinions on proceeding forward?

@kaysond

kaysond commented Feb 13, 2026

Copy link
Copy Markdown
Collaborator

Ironically, it does seem like Starosdev#118 did the ugly-work for most of us. Fixed the blunders I made and integrated it. Opinions on proceeding forward?

@AIndoria - I have some concerns with how that config is set up. Setting up discussion here: #922

@Abraxos

Abraxos commented Jun 3, 2026

Copy link
Copy Markdown

Is there anything I can do to help this get merged? The fact that I cannot ignore a specific code (188) is becoming a serious problem for me. I don't have any opinions on #922 , I just want to help get this done.

EDIT: I guess I have a slight preference for the config file?

@kaysond

kaysond commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

Is there anything I can do to help this get merged? The fact that I cannot ignore a specific code (188) is becoming a serious problem for me. I don't have any opinions on #922 , I just want to help get this done.

EDIT: I guess I have a slight preference for the config file?

If you're interested in contributing this I can spec out updates to the config file and how to implement support for the attribute overrides. It might make the most sense to just create a new PR.

@Abraxos

Abraxos commented Jun 3, 2026

Copy link
Copy Markdown

Yes, I am interested in contributing to this. The only caveat to be aware of is that golang isn't my best language, so I will almost certainly be using Claude to help (though of course I will thoroughly test and review everything before submitting it for review here). As long as that's OK, yeah, I am happy to write a PR

@kaysond

kaysond commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

Yes, I am interested in contributing to this. The only caveat to be aware of is that golang isn't my best language, so I will almost certainly be using Claude to help (though of course I will thoroughly test and review everything before submitting it for review here). As long as that's OK, yeah, I am happy to write a PR

That's fine. I'll review and if so just need a lot of testing. I'll probably leave it in nightly for a bit too. I'll try to spec out the change in the next couple of days and will tag you when it's ready.

@Abraxos

Abraxos commented Jun 4, 2026

Copy link
Copy Markdown

Yes, I am interested in contributing to this. The only caveat to be aware of is that golang isn't my best language, so I will almost certainly be using Claude to help (though of course I will thoroughly test and review everything before submitting it for review here). As long as that's OK, yeah, I am happy to write a PR

That's fine. I'll review and if so just need a lot of testing. I'll probably leave it in nightly for a bit too. I'll try to spec out the change in the next couple of days and will tag you when it's ready.

Sweet, I am looking forward to it!

@AIndoria

AIndoria commented Jun 5, 2026

Copy link
Copy Markdown
Author

I'll start re-looking into this as well. So far I've not because last few months have been exceptionally busy but I should have some time for next few weeks. @Abraxos ping me if you find a different/better way of doing this and maybe we can rebase it as @kaysond mentioned earlier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Add SMART attribute override functionality

4 participants