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.
152 lines
5.0 KiB
152 lines
5.0 KiB
4 years ago
|
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
|
||
|
//}
|