You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
scrutiny/webapp/backend/pkg/models/measurements/smart_ata_attribute.go

152 lines
5.0 KiB

package measurements
import (
"fmt"
"strconv"
"strings"
)
const SmartAttributeStatusPassed = "passed"
const SmartAttributeStatusFailed = "failed"
const SmartAttributeStatusWarning = "warn"
type SmartAtaAttribute struct {
AttributeId int `json:"attribute_id"`
Name string `json:"name"`
Value int64 `json:"value"`
Threshold int64 `json:"thresh"`
Worst int64 `json:"worst"`
RawValue int64 `json:"raw_value"`
RawString string `json:"raw_string"`
WhenFailed string `json:"when_failed"`
//Generated data
TransformedValue int64 `json:"transformed_value"`
Status string `json:"status,omitempty"`
StatusReason string `json:"status_reason,omitempty"`
FailureRate float64 `json:"failure_rate,omitempty"`
}
func (sa *SmartAtaAttribute) Flatten() map[string]interface{} {
idString := strconv.Itoa(sa.AttributeId)
return map[string]interface{}{
fmt.Sprintf("attr.%s.attribute_id", idString): idString,
fmt.Sprintf("attr.%s.name", idString): sa.Name,
fmt.Sprintf("attr.%s.value", idString): sa.Value,
fmt.Sprintf("attr.%s.worst", idString): sa.Worst,
fmt.Sprintf("attr.%s.thresh", idString): sa.Threshold,
fmt.Sprintf("attr.%s.raw_value", idString): sa.RawValue,
fmt.Sprintf("attr.%s.raw_string", idString): sa.RawString,
fmt.Sprintf("attr.%s.when_failed", idString): sa.WhenFailed,
}
}
func (sa *SmartAtaAttribute) Inflate(key string, val interface{}) {
if val == nil {
return
}
keyParts := strings.Split(key, ".")
switch keyParts[2] {
case "attribute_id":
attrId, err := strconv.Atoi(val.(string))
if err == nil {
sa.AttributeId = attrId
}
case "name":
sa.Name = val.(string)
case "value":
sa.Value = val.(int64)
case "worst":
sa.Worst = val.(int64)
case "thresh":
sa.Threshold = val.(int64)
case "raw_value":
sa.RawValue = val.(int64)
case "raw_string":
sa.RawString = val.(string)
case "when_failed":
sa.WhenFailed = val.(string)
}
}
//
////populate attribute status, using SMART Thresholds & Observed Metadata
//func (sa *SmartAtaAttribute) PopulateAttributeStatus() {
// if strings.ToUpper(sa.WhenFailed) == SmartWhenFailedFailingNow {
// //this attribute has previously failed
// sa.Status = SmartAttributeStatusFailed
// sa.StatusReason = "Attribute is failing manufacturer SMART threshold"
//
// } else if strings.ToUpper(sa.WhenFailed) == SmartWhenFailedInThePast {
// sa.Status = SmartAttributeStatusWarning
// sa.StatusReason = "Attribute has previously failed manufacturer SMART threshold"
// }
//
// if smartMetadata, ok := metadata.AtaMetadata[sa.AttributeId]; ok {
// sa.MetadataObservedThresholdStatus(smartMetadata)
// }
//
// //check if status is blank, set to "passed"
// if len(sa.Status) == 0 {
// sa.Status = SmartAttributeStatusPassed
// }
//}
//
//// compare the attribute (raw, normalized, transformed) value to observed thresholds, and update status if necessary
//func (sa *SmartAtaAttribute) MetadataObservedThresholdStatus(smartMetadata metadata.AtaAttributeMetadata) {
// //TODO: multiple rules
// // try to predict the failure rates for observed thresholds that have 0 failure rate and error bars.
// // - if the attribute is critical
// // - the failure rate is over 10 - set to failed
// // - the attribute does not match any threshold, set to warn
// // - if the attribute is not critical
// // - if failure rate is above 20 - set to failed
// // - if failure rate is above 10 but below 20 - set to warn
//
// //update the smart attribute status based on Observed thresholds.
// var value int64
// if smartMetadata.DisplayType == metadata.AtaSmartAttributeDisplayTypeNormalized {
// value = int64(sa.Value)
// } else if smartMetadata.DisplayType == metadata.AtaSmartAttributeDisplayTypeTransformed {
// value = sa.TransformedValue
// } else {
// value = sa.RawValue
// }
//
// for _, obsThresh := range smartMetadata.ObservedThresholds {
//
// //check if "value" is in this bucket
// if ((obsThresh.Low == obsThresh.High) && value == obsThresh.Low) ||
// (obsThresh.Low < value && value <= obsThresh.High) {
// sa.FailureRate = obsThresh.AnnualFailureRate
//
// if smartMetadata.Critical {
// if obsThresh.AnnualFailureRate >= 0.10 {
// sa.Status = SmartAttributeStatusFailed
// sa.StatusReason = "Observed Failure Rate for Critical Attribute is greater than 10%"
// }
// } else {
// if obsThresh.AnnualFailureRate >= 0.20 {
// sa.Status = SmartAttributeStatusFailed
// sa.StatusReason = "Observed Failure Rate for Attribute is greater than 20%"
// } else if obsThresh.AnnualFailureRate >= 0.10 {
// sa.Status = SmartAttributeStatusWarning
// sa.StatusReason = "Observed Failure Rate for Attribute is greater than 10%"
// }
// }
//
// //we've found the correct bucket, we can drop out of this loop
// return
// }
// }
// // no bucket found
// if smartMetadata.Critical {
// sa.Status = SmartAttributeStatusWarning
// sa.StatusReason = "Could not determine Observed Failure Rate for Critical Attribute"
// }
//
// return
//}