working settings update.

Settings are loaded from the DB and added to the AppConfig during startup.
When updating settings, they are stored in AppConfig, and written do  the database.
pull/338/head
Jason Kulatunga 2 years ago
parent 99af2b8b16
commit 29bc79996b

@ -66,6 +66,10 @@ func (c *configuration) Init() error {
return c.ValidateConfig() return c.ValidateConfig()
} }
func (c *configuration) SubKeys(key string) []string {
return c.Sub(key).AllKeys()
}
func (c *configuration) ReadConfig(configFilePath string) error { func (c *configuration) ReadConfig(configFilePath string) error {
//make sure that we specify that this is the correct config path (for eventual WriteConfig() calls) //make sure that we specify that this is the correct config path (for eventual WriteConfig() calls)
c.SetConfigFile(configFilePath) c.SetConfigFile(configFilePath)

@ -12,12 +12,16 @@ type Interface interface {
WriteConfig() error WriteConfig() error
Set(key string, value interface{}) Set(key string, value interface{})
SetDefault(key string, value interface{}) SetDefault(key string, value interface{})
MergeConfigMap(cfg map[string]interface{}) error
AllSettings() map[string]interface{} AllSettings() map[string]interface{}
AllKeys() []string
SubKeys(key string) []string
IsSet(key string) bool IsSet(key string) bool
Get(key string) interface{} Get(key string) interface{}
GetBool(key string) bool GetBool(key string) bool
GetInt(key string) int GetInt(key string) int
GetInt64(key string) int64
GetString(key string) string GetString(key string) string
GetStringSlice(key string) []string GetStringSlice(key string) []string
UnmarshalKey(key string, rawVal interface{}, decoderOpts ...viper.DecoderConfigOption) error UnmarshalKey(key string, rawVal interface{}, decoderOpts ...viper.DecoderConfigOption) error

@ -67,14 +67,5 @@ const (
// Deprecated // Deprecated
const NotifyFilterAttributesAll = "all" const NotifyFilterAttributesAll = "all"
// Deprecated
const NotifyFilterAttributesCritical = "critical"
// Deprecated // Deprecated
const NotifyLevelFail = "fail" const NotifyLevelFail = "fail"
// Deprecated
const NotifyLevelFailScrutiny = "fail_scrutiny"
// Deprecated
const NotifyLevelFailSmart = "fail_smart"

@ -11,9 +11,6 @@ import (
type DeviceRepo interface { type DeviceRepo interface {
Close() error Close() error
//GetSettings()
//SaveSetting()
RegisterDevice(ctx context.Context, dev models.Device) error RegisterDevice(ctx context.Context, dev models.Device) error
GetDevices(ctx context.Context) ([]models.Device, error) GetDevices(ctx context.Context) ([]models.Device, error)
UpdateDevice(ctx context.Context, wwn string, collectorSmartData collector.SmartInfo) (models.Device, error) UpdateDevice(ctx context.Context, wwn string, collectorSmartData collector.SmartInfo) (models.Device, error)
@ -29,6 +26,6 @@ type DeviceRepo interface {
GetSummary(ctx context.Context) (map[string]*models.DeviceSummary, error) GetSummary(ctx context.Context) (map[string]*models.DeviceSummary, error)
GetSmartTemperatureHistory(ctx context.Context, durationKey string) (map[string][]measurements.SmartTemperature, error) GetSmartTemperatureHistory(ctx context.Context, durationKey string) (map[string][]measurements.SmartTemperature, error)
GetSettings(ctx context.Context) (*models.Settings, error) LoadSettings(ctx context.Context) (*models.Settings, error)
SaveSettings(ctx context.Context, settings models.Settings) error SaveSettings(ctx context.Context, settings models.Settings) error
} }

@ -304,7 +304,7 @@ func (sr *scrutinyRepository) Migrate(ctx context.Context) error {
{ {
SettingKeyName: "metrics.status.threshold", SettingKeyName: "metrics.status.threshold",
SettingKeyDescription: "Determines which threshold should impact device status", SettingKeyDescription: "Determines which threshold should impact device status",
SettingDataType: "string", SettingDataType: "numeric",
SettingValueNumeric: int64(pkg.MetricsStatusThresholdBoth), // options: 'scrutiny', 'smart', 'both' SettingValueNumeric: int64(pkg.MetricsStatusThresholdBoth), // options: 'scrutiny', 'smart', 'both'
}, },
} }

@ -4,30 +4,79 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/analogj/scrutiny/webapp/backend/pkg/models" "github.com/analogj/scrutiny/webapp/backend/pkg/models"
"github.com/mitchellh/mapstructure"
) )
func (sr *scrutinyRepository) GetSettings(ctx context.Context) (*models.Settings, error) { const DBSETTING_SUBKEY = "dbsetting"
// LoadSettings will retrieve settings from the database, store them in the AppConfig object, and return a Settings struct
func (sr *scrutinyRepository) LoadSettings(ctx context.Context) (*models.Settings, error) {
settingsEntries := []models.SettingEntry{} settingsEntries := []models.SettingEntry{}
if err := sr.gormClient.WithContext(ctx).Find(&settingsEntries).Error; err != nil { if err := sr.gormClient.WithContext(ctx).Find(&settingsEntries).Error; err != nil {
return nil, fmt.Errorf("Could not get settings from DB: %v", err) return nil, fmt.Errorf("Could not get settings from DB: %v", err)
} }
settings := models.Settings{} // store retrieved settings in the AppConfig obj
settings.PopulateFromSettingEntries(settingsEntries) for _, settingsEntry := range settingsEntries {
configKey := fmt.Sprintf("%s.%s", DBSETTING_SUBKEY, settingsEntry.SettingKeyName)
if settingsEntry.SettingDataType == "numeric" {
sr.appConfig.SetDefault(configKey, settingsEntry.SettingValueNumeric)
} else if settingsEntry.SettingDataType == "string" {
sr.appConfig.SetDefault(configKey, settingsEntry.SettingValueString)
}
}
// unmarshal the dbsetting object data to a settings object.
var settings models.Settings
err := sr.appConfig.UnmarshalKey(DBSETTING_SUBKEY, &settings)
if err != nil {
return nil, err
}
return &settings, nil return &settings, nil
} }
// testing
// curl -d '{"metrics": { "notify": { "level": 5 }, "status": { "filter_attributes": 5, "threshold": 5 } }}' -H "Content-Type: application/json" -X POST http://localhost:9090/api/settings
// SaveSettings will update settings in AppConfig object, then save the settings to the database.
func (sr *scrutinyRepository) SaveSettings(ctx context.Context, settings models.Settings) error { func (sr *scrutinyRepository) SaveSettings(ctx context.Context, settings models.Settings) error {
//get current settings //save the entries to the appconfig
settingsMap := &map[string]interface{}{}
err := mapstructure.Decode(settings, &settingsMap)
if err != nil {
return err
}
settingsWrapperMap := map[string]interface{}{}
settingsWrapperMap[DBSETTING_SUBKEY] = *settingsMap
err = sr.appConfig.MergeConfigMap(settingsWrapperMap)
if err != nil {
return err
}
//retrieve current settings from the database
settingsEntries := []models.SettingEntry{} settingsEntries := []models.SettingEntry{}
if err := sr.gormClient.WithContext(ctx).Find(&settingsEntries).Error; err != nil { if err := sr.gormClient.WithContext(ctx).Find(&settingsEntries).Error; err != nil {
return fmt.Errorf("Could not get settings from DB: %v", err) return fmt.Errorf("Could not get settings from DB: %v", err)
} }
// override with values from settings object //update settingsEntries
settingsEntries = settings.UpdateSettingEntries(settingsEntries) for ndx, settingsEntry := range settingsEntries {
configKey := fmt.Sprintf("%s.%s", DBSETTING_SUBKEY, settingsEntry.SettingKeyName)
if settingsEntry.SettingDataType == "numeric" {
settingsEntries[ndx].SettingValueNumeric = sr.appConfig.GetInt(configKey)
} else if settingsEntry.SettingDataType == "string" {
settingsEntries[ndx].SettingValueString = sr.appConfig.GetString(configKey)
}
// store in database. // store in database.
return sr.gormClient.Updates(&settingsEntries).Error //TODO: this should be `sr.gormClient.Updates(&settingsEntries).Error`
err := sr.gormClient.Model(&models.SettingEntry{}).Where([]uint{settingsEntry.ID}).Select("setting_value_numeric", "setting_value_string").Updates(settingsEntries[ndx]).Error
if err != nil {
return err
}
}
return nil
} }

@ -13,7 +13,7 @@ type SettingEntry struct {
SettingKeyDescription string `json:"setting_key_description"` SettingKeyDescription string `json:"setting_key_description"`
SettingDataType string `json:"setting_data_type"` SettingDataType string `json:"setting_data_type"`
SettingValueNumeric int64 `json:"setting_value_numeric"` SettingValueNumeric int `json:"setting_value_numeric"`
SettingValueString string `json:"setting_value_string"` SettingValueString string `json:"setting_value_string"`
} }

@ -1,35 +1,20 @@
package models package models
import "github.com/analogj/scrutiny/webapp/backend/pkg"
// Settings is made up of parsed SettingEntry objects retrieved from the database // Settings is made up of parsed SettingEntry objects retrieved from the database
type Settings struct { //type Settings struct {
MetricsNotifyLevel pkg.MetricsNotifyLevel `json:"metrics_notify_level"` // MetricsNotifyLevel pkg.MetricsNotifyLevel `json:"metrics.notify.level" mapstructure:"metrics.notify.level"`
MetricsStatusFilterAttributes pkg.MetricsStatusFilterAttributes `json:"metrics_status_filter_attributes"` // MetricsStatusFilterAttributes pkg.MetricsStatusFilterAttributes `json:"metrics.status.filter_attributes" mapstructure:"metrics.status.filter_attributes"`
MetricsStatusThreshold pkg.MetricsStatusThreshold `json:"metrics_status_threshold"` // MetricsStatusThreshold pkg.MetricsStatusThreshold `json:"metrics.status.threshold" mapstructure:"metrics.status.threshold"`
} //}
func (s *Settings) PopulateFromSettingEntries(entries []SettingEntry) { type Settings struct {
for _, entry := range entries { Metrics struct {
if entry.SettingKeyName == "metrics.notify.level" { Notify struct {
s.MetricsNotifyLevel = pkg.MetricsNotifyLevel(entry.SettingValueNumeric) Level int `json:"level" mapstructure:"level"`
} else if entry.SettingKeyName == "metrics.status.filter_attributes" { } `json:"notify" mapstructure:"notify"`
s.MetricsStatusFilterAttributes = pkg.MetricsStatusFilterAttributes(entry.SettingValueNumeric) Status struct {
} else if entry.SettingKeyName == "metrics.status.threshold" { FilterAttributes int `json:"filter_attributes" mapstructure:"filter_attributes"`
s.MetricsStatusThreshold = pkg.MetricsStatusThreshold(entry.SettingValueNumeric) Threshold int `json:"threshold" mapstructure:"threshold"`
} } `json:"status" mapstructure:"status"`
} } `json:"metrics" mapstructure:"metrics"`
}
func (s *Settings) UpdateSettingEntries(entries []SettingEntry) []SettingEntry {
for _, entry := range entries {
if entry.SettingKeyName == "metrics.notify.level" {
entry.SettingValueNumeric = int64(s.MetricsNotifyLevel)
} else if entry.SettingKeyName == "metrics.status.filter_attributes" {
entry.SettingValueNumeric = int64(s.MetricsStatusFilterAttributes)
} else if entry.SettingKeyName == "metrics.status.threshold" {
entry.SettingValueNumeric = int64(s.MetricsStatusThreshold)
}
}
return entries
} }

@ -29,20 +29,22 @@ const NotifyFailureTypeSmartFailure = "SmartFailure"
const NotifyFailureTypeScrutinyFailure = "ScrutinyFailure" const NotifyFailureTypeScrutinyFailure = "ScrutinyFailure"
// ShouldNotify check if the error Message should be filtered (level mismatch or filtered_attributes) // ShouldNotify check if the error Message should be filtered (level mismatch or filtered_attributes)
func ShouldNotify(device models.Device, smartAttrs measurements.Smart, notifyLevel string, notifyFilterAttributes string) bool { func ShouldNotify(device models.Device, smartAttrs measurements.Smart, statusThreshold pkg.MetricsStatusThreshold, statusFilterAttributes pkg.MetricsStatusFilterAttributes) bool {
// 1. check if the device is healthy // 1. check if the device is healthy
if device.DeviceStatus == pkg.DeviceStatusPassed { if device.DeviceStatus == pkg.DeviceStatusPassed {
return false return false
} }
//TODO: cannot check for warning notifyLevel yet.
// setup constants for comparison // setup constants for comparison
var requiredDeviceStatus pkg.DeviceStatus var requiredDeviceStatus pkg.DeviceStatus
var requiredAttrStatus pkg.AttributeStatus var requiredAttrStatus pkg.AttributeStatus
if notifyLevel == pkg.NotifyLevelFail { if statusThreshold == pkg.MetricsStatusThresholdBoth {
// either scrutiny or smart failures should trigger an email // either scrutiny or smart failures should trigger an email
requiredDeviceStatus = pkg.DeviceStatusSet(pkg.DeviceStatusFailedSmart, pkg.DeviceStatusFailedScrutiny) requiredDeviceStatus = pkg.DeviceStatusSet(pkg.DeviceStatusFailedSmart, pkg.DeviceStatusFailedScrutiny)
requiredAttrStatus = pkg.AttributeStatusSet(pkg.AttributeStatusFailedSmart, pkg.AttributeStatusFailedScrutiny) requiredAttrStatus = pkg.AttributeStatusSet(pkg.AttributeStatusFailedSmart, pkg.AttributeStatusFailedScrutiny)
} else if notifyLevel == pkg.NotifyLevelFailSmart { } else if statusThreshold == pkg.MetricsStatusThresholdSmart {
//only smart failures //only smart failures
requiredDeviceStatus = pkg.DeviceStatusFailedSmart requiredDeviceStatus = pkg.DeviceStatusFailedSmart
requiredAttrStatus = pkg.AttributeStatusFailedSmart requiredAttrStatus = pkg.AttributeStatusFailedSmart
@ -53,9 +55,9 @@ func ShouldNotify(device models.Device, smartAttrs measurements.Smart, notifyLev
// 2. check if the attributes that are failing should be filtered (non-critical) // 2. check if the attributes that are failing should be filtered (non-critical)
// 3. for any unfiltered attribute, store the failure reason (Smart or Scrutiny) // 3. for any unfiltered attribute, store the failure reason (Smart or Scrutiny)
if notifyFilterAttributes == pkg.NotifyFilterAttributesCritical { if statusFilterAttributes == pkg.MetricsStatusFilterAttributesCritical {
hasFailingCriticalAttr := false hasFailingCriticalAttr := false
var statusFailingCrtiticalAttr pkg.AttributeStatus var statusFailingCriticalAttr pkg.AttributeStatus
for attrId, attrData := range smartAttrs.Attributes { for attrId, attrData := range smartAttrs.Attributes {
//find failing attribute //find failing attribute
@ -64,7 +66,7 @@ func ShouldNotify(device models.Device, smartAttrs measurements.Smart, notifyLev
} }
// merge the status's of all critical attributes // merge the status's of all critical attributes
statusFailingCrtiticalAttr = pkg.AttributeStatusSet(statusFailingCrtiticalAttr, attrData.GetStatus()) statusFailingCriticalAttr = pkg.AttributeStatusSet(statusFailingCriticalAttr, attrData.GetStatus())
//found a failing attribute, see if its critical //found a failing attribute, see if its critical
if device.IsScsi() && thresholds.ScsiMetadata[attrId].Critical { if device.IsScsi() && thresholds.ScsiMetadata[attrId].Critical {
@ -89,7 +91,7 @@ func ShouldNotify(device models.Device, smartAttrs measurements.Smart, notifyLev
return false return false
} else { } else {
// check if any of the critical attributes have a status that we're looking for // check if any of the critical attributes have a status that we're looking for
return pkg.AttributeStatusHas(statusFailingCrtiticalAttr, requiredAttrStatus) return pkg.AttributeStatusHas(statusFailingCriticalAttr, requiredAttrStatus)
} }
} else { } else {

@ -15,56 +15,56 @@ func TestShouldNotify_MustSkipPassingDevices(t *testing.T) {
DeviceStatus: pkg.DeviceStatusPassed, DeviceStatus: pkg.DeviceStatusPassed,
} }
smartAttrs := measurements.Smart{} smartAttrs := measurements.Smart{}
notifyLevel := pkg.NotifyLevelFail statusThreshold := pkg.MetricsStatusThresholdBoth
notifyFilterAttributes := pkg.NotifyFilterAttributesAll notifyFilterAttributes := pkg.MetricsStatusFilterAttributesAll
//assert //assert
require.False(t, ShouldNotify(device, smartAttrs, notifyLevel, notifyFilterAttributes)) require.False(t, ShouldNotify(device, smartAttrs, statusThreshold, notifyFilterAttributes))
} }
func TestShouldNotify_NotifyLevelFail_FailingSmartDevice(t *testing.T) { func TestShouldNotify_MetricsStatusThresholdBoth_FailingSmartDevice(t *testing.T) {
t.Parallel() t.Parallel()
//setup //setup
device := models.Device{ device := models.Device{
DeviceStatus: pkg.DeviceStatusFailedSmart, DeviceStatus: pkg.DeviceStatusFailedSmart,
} }
smartAttrs := measurements.Smart{} smartAttrs := measurements.Smart{}
notifyLevel := pkg.NotifyLevelFail statusThreshold := pkg.MetricsStatusThresholdBoth
notifyFilterAttributes := pkg.NotifyFilterAttributesAll notifyFilterAttributes := pkg.MetricsStatusFilterAttributesAll
//assert //assert
require.True(t, ShouldNotify(device, smartAttrs, notifyLevel, notifyFilterAttributes)) require.True(t, ShouldNotify(device, smartAttrs, statusThreshold, notifyFilterAttributes))
} }
func TestShouldNotify_NotifyLevelFailSmart_FailingSmartDevice(t *testing.T) { func TestShouldNotify_MetricsStatusThresholdSmart_FailingSmartDevice(t *testing.T) {
t.Parallel() t.Parallel()
//setup //setup
device := models.Device{ device := models.Device{
DeviceStatus: pkg.DeviceStatusFailedSmart, DeviceStatus: pkg.DeviceStatusFailedSmart,
} }
smartAttrs := measurements.Smart{} smartAttrs := measurements.Smart{}
notifyLevel := pkg.NotifyLevelFailSmart statusThreshold := pkg.MetricsStatusThresholdSmart
notifyFilterAttributes := pkg.NotifyFilterAttributesAll notifyFilterAttributes := pkg.MetricsStatusFilterAttributesAll
//assert //assert
require.True(t, ShouldNotify(device, smartAttrs, notifyLevel, notifyFilterAttributes)) require.True(t, ShouldNotify(device, smartAttrs, statusThreshold, notifyFilterAttributes))
} }
func TestShouldNotify_NotifyLevelFailScrutiny_FailingSmartDevice(t *testing.T) { func TestShouldNotify_MetricsStatusThresholdScrutiny_FailingSmartDevice(t *testing.T) {
t.Parallel() t.Parallel()
//setup //setup
device := models.Device{ device := models.Device{
DeviceStatus: pkg.DeviceStatusFailedSmart, DeviceStatus: pkg.DeviceStatusFailedSmart,
} }
smartAttrs := measurements.Smart{} smartAttrs := measurements.Smart{}
notifyLevel := pkg.NotifyLevelFailScrutiny statusThreshold := pkg.MetricsStatusThresholdScrutiny
notifyFilterAttributes := pkg.NotifyFilterAttributesAll notifyFilterAttributes := pkg.MetricsStatusFilterAttributesAll
//assert //assert
require.False(t, ShouldNotify(device, smartAttrs, notifyLevel, notifyFilterAttributes)) require.False(t, ShouldNotify(device, smartAttrs, statusThreshold, notifyFilterAttributes))
} }
func TestShouldNotify_NotifyFilterAttributesCritical_WithCriticalAttrs(t *testing.T) { func TestShouldNotify_MetricsStatusFilterAttributesCritical_WithCriticalAttrs(t *testing.T) {
t.Parallel() t.Parallel()
//setup //setup
device := models.Device{ device := models.Device{
@ -75,14 +75,14 @@ func TestShouldNotify_NotifyFilterAttributesCritical_WithCriticalAttrs(t *testin
Status: pkg.AttributeStatusFailedSmart, Status: pkg.AttributeStatusFailedSmart,
}, },
}} }}
notifyLevel := pkg.NotifyLevelFail statusThreshold := pkg.MetricsStatusThresholdBoth
notifyFilterAttributes := pkg.NotifyFilterAttributesCritical notifyFilterAttributes := pkg.MetricsStatusFilterAttributesCritical
//assert //assert
require.True(t, ShouldNotify(device, smartAttrs, notifyLevel, notifyFilterAttributes)) require.True(t, ShouldNotify(device, smartAttrs, statusThreshold, notifyFilterAttributes))
} }
func TestShouldNotify_NotifyFilterAttributesCritical_WithMultipleCriticalAttrs(t *testing.T) { func TestShouldNotify_MetricsStatusFilterAttributesCritical_WithMultipleCriticalAttrs(t *testing.T) {
t.Parallel() t.Parallel()
//setup //setup
device := models.Device{ device := models.Device{
@ -96,14 +96,14 @@ func TestShouldNotify_NotifyFilterAttributesCritical_WithMultipleCriticalAttrs(t
Status: pkg.AttributeStatusFailedScrutiny, Status: pkg.AttributeStatusFailedScrutiny,
}, },
}} }}
notifyLevel := pkg.NotifyLevelFail statusThreshold := pkg.MetricsStatusThresholdBoth
notifyFilterAttributes := pkg.NotifyFilterAttributesCritical notifyFilterAttributes := pkg.MetricsStatusFilterAttributesCritical
//assert //assert
require.True(t, ShouldNotify(device, smartAttrs, notifyLevel, notifyFilterAttributes)) require.True(t, ShouldNotify(device, smartAttrs, statusThreshold, notifyFilterAttributes))
} }
func TestShouldNotify_NotifyFilterAttributesCritical_WithNoCriticalAttrs(t *testing.T) { func TestShouldNotify_MetricsStatusFilterAttributesCritical_WithNoCriticalAttrs(t *testing.T) {
t.Parallel() t.Parallel()
//setup //setup
device := models.Device{ device := models.Device{
@ -114,14 +114,14 @@ func TestShouldNotify_NotifyFilterAttributesCritical_WithNoCriticalAttrs(t *test
Status: pkg.AttributeStatusFailedSmart, Status: pkg.AttributeStatusFailedSmart,
}, },
}} }}
notifyLevel := pkg.NotifyLevelFail statusThreshold := pkg.MetricsStatusThresholdBoth
notifyFilterAttributes := pkg.NotifyFilterAttributesCritical notifyFilterAttributes := pkg.MetricsStatusFilterAttributesCritical
//assert //assert
require.False(t, ShouldNotify(device, smartAttrs, notifyLevel, notifyFilterAttributes)) require.False(t, ShouldNotify(device, smartAttrs, statusThreshold, notifyFilterAttributes))
} }
func TestShouldNotify_NotifyFilterAttributesCritical_WithNoFailingCriticalAttrs(t *testing.T) { func TestShouldNotify_MetricsStatusFilterAttributesCritical_WithNoFailingCriticalAttrs(t *testing.T) {
t.Parallel() t.Parallel()
//setup //setup
device := models.Device{ device := models.Device{
@ -132,14 +132,14 @@ func TestShouldNotify_NotifyFilterAttributesCritical_WithNoFailingCriticalAttrs(
Status: pkg.AttributeStatusPassed, Status: pkg.AttributeStatusPassed,
}, },
}} }}
notifyLevel := pkg.NotifyLevelFail statusThreshold := pkg.MetricsStatusThresholdBoth
notifyFilterAttributes := pkg.NotifyFilterAttributesCritical notifyFilterAttributes := pkg.MetricsStatusFilterAttributesCritical
//assert //assert
require.False(t, ShouldNotify(device, smartAttrs, notifyLevel, notifyFilterAttributes)) require.False(t, ShouldNotify(device, smartAttrs, statusThreshold, notifyFilterAttributes))
} }
func TestShouldNotify_NotifyFilterAttributesCritical_NotifyLevelFailSmart_WithCriticalAttrsFailingScrutiny(t *testing.T) { func TestShouldNotify_MetricsStatusFilterAttributesCritical_MetricsStatusThresholdSmart_WithCriticalAttrsFailingScrutiny(t *testing.T) {
t.Parallel() t.Parallel()
//setup //setup
device := models.Device{ device := models.Device{
@ -153,9 +153,9 @@ func TestShouldNotify_NotifyFilterAttributesCritical_NotifyLevelFailSmart_WithCr
Status: pkg.AttributeStatusFailedScrutiny, Status: pkg.AttributeStatusFailedScrutiny,
}, },
}} }}
notifyLevel := pkg.NotifyLevelFailSmart statusThreshold := pkg.MetricsStatusThresholdSmart
notifyFilterAttributes := pkg.NotifyFilterAttributesCritical notifyFilterAttributes := pkg.MetricsStatusFilterAttributesCritical
//assert //assert
require.False(t, ShouldNotify(device, smartAttrs, notifyLevel, notifyFilterAttributes)) require.False(t, ShouldNotify(device, smartAttrs, statusThreshold, notifyFilterAttributes))
} }

@ -11,7 +11,7 @@ func GetSettings(c *gin.Context) {
logger := c.MustGet("LOGGER").(logrus.FieldLogger) logger := c.MustGet("LOGGER").(logrus.FieldLogger)
deviceRepo := c.MustGet("DEVICE_REPOSITORY").(database.DeviceRepo) deviceRepo := c.MustGet("DEVICE_REPOSITORY").(database.DeviceRepo)
settings, err := deviceRepo.GetSettings(c) settings, err := deviceRepo.LoadSettings(c)
if err != nil { if err != nil {
logger.Errorln("An error occurred while retrieving settings", err) logger.Errorln("An error occurred while retrieving settings", err)
c.JSON(http.StatusInternalServerError, gin.H{"success": false}) c.JSON(http.StatusInternalServerError, gin.H{"success": false})

@ -67,7 +67,12 @@ func UploadDeviceMetrics(c *gin.Context) {
} }
//check for error //check for error
if notify.ShouldNotify(updatedDevice, smartData, appConfig.GetString("notify.level"), appConfig.GetString("notify.filter_attributes")) { if notify.ShouldNotify(
updatedDevice,
smartData,
pkg.MetricsStatusThreshold(appConfig.GetInt("dbsetting.metrics.status.threshold")),
pkg.MetricsStatusFilterAttributes(appConfig.GetInt("dbsetting.metrics.status.filter_attributes")),
) {
//send notifications //send notifications
liveNotify := notify.New( liveNotify := notify.New(

@ -32,7 +32,7 @@ func LoggerMiddleware(logger logrus.FieldLogger) gin.HandlerFunc {
hostname, err := os.Hostname() hostname, err := os.Hostname()
if err != nil { if err != nil {
hostname = "unknow" hostname = "unknown"
} }
return func(c *gin.Context) { return func(c *gin.Context) {

@ -1,6 +1,7 @@
package middleware package middleware
import ( import (
"context"
"github.com/analogj/scrutiny/webapp/backend/pkg/config" "github.com/analogj/scrutiny/webapp/backend/pkg/config"
"github.com/analogj/scrutiny/webapp/backend/pkg/database" "github.com/analogj/scrutiny/webapp/backend/pkg/database"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@ -14,6 +15,14 @@ func RepositoryMiddleware(appConfig config.Interface, globalLogger logrus.FieldL
panic(err) panic(err)
} }
// ensure the settings have been loaded into the app config during startup.
_, err = deviceRepo.LoadSettings(context.Background())
if err != nil {
panic(err)
}
//settings.UpdateSettingEntries()
//TODO: determine where we can call defer deviceRepo.Close() //TODO: determine where we can call defer deviceRepo.Close()
return func(c *gin.Context) { return func(c *gin.Context) {
c.Set("DEVICE_REPOSITORY", deviceRepo) c.Set("DEVICE_REPOSITORY", deviceRepo)

Loading…
Cancel
Save