Skip to content

Commit cf18a6b

Browse files
authored
Merge pull request #51 from Starosdev/develop
Release: Bug fixes and feature updates
2 parents 4aee8e8 + 1db337d commit cf18a6b

File tree

18 files changed

+262
-72
lines changed

18 files changed

+262
-72
lines changed

collector/cmd/collector-metrics/collector-metrics.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@ package main
33
import (
44
"encoding/json"
55
"fmt"
6-
"github.com/analogj/scrutiny/collector/pkg/collector"
7-
"github.com/analogj/scrutiny/collector/pkg/config"
8-
"github.com/analogj/scrutiny/collector/pkg/errors"
9-
"github.com/analogj/scrutiny/webapp/backend/pkg/version"
10-
"github.com/sirupsen/logrus"
116
"io"
127
"log"
138
"os"
149
"strings"
1510
"time"
1611

1712
utils "github.com/analogj/go-util/utils"
13+
"github.com/analogj/scrutiny/collector/pkg/collector"
14+
"github.com/analogj/scrutiny/collector/pkg/config"
15+
"github.com/analogj/scrutiny/collector/pkg/errors"
16+
"github.com/analogj/scrutiny/webapp/backend/pkg/version"
1817
"github.com/fatih/color"
18+
"github.com/sirupsen/logrus"
1919
"github.com/urfave/cli/v2"
2020
)
2121

@@ -36,9 +36,13 @@ func main() {
3636
configFilePath = configFilePathAlternative
3737
}
3838

39+
// Create a bootstrap logger for config loading (before config-based logger is available)
40+
bootstrapLogger := logrus.WithFields(logrus.Fields{"type": "metrics"})
41+
bootstrapLogger.Logger.SetLevel(logrus.InfoLevel)
42+
3943
//we're going to load the config file manually, since we need to validate it.
40-
err = config.ReadConfig(configFilePath) // Find and read the config file
41-
if _, ok := err.(errors.ConfigFileMissingError); ok { // Handle errors reading the config file
44+
err = config.ReadConfig(configFilePath, bootstrapLogger) // Find and read the config file
45+
if _, ok := err.(errors.ConfigFileMissingError); ok { // Handle errors reading the config file
4246
//ignore "could not find config file"
4347
} else if err != nil {
4448
os.Exit(1)
@@ -100,8 +104,8 @@ OPTIONS:
100104
Usage: "Run the scrutiny smartctl metrics collector",
101105
Action: func(c *cli.Context) error {
102106
if c.IsSet("config") {
103-
err = config.ReadConfig(c.String("config")) // Find and read the config file
104-
if err != nil { // Handle errors reading the config file
107+
err = config.ReadConfig(c.String("config"), bootstrapLogger) // Find and read the config file
108+
if err != nil { // Handle errors reading the config file
105109
//ignore "could not find config file"
106110
fmt.Printf("Could not find config file at specified path: %s", c.String("config"))
107111
return err

collector/pkg/config/config.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@ package config
22

33
import (
44
"fmt"
5+
"os"
6+
"sort"
7+
"strings"
8+
59
"github.com/analogj/go-util/utils"
610
"github.com/analogj/scrutiny/collector/pkg/errors"
711
"github.com/analogj/scrutiny/collector/pkg/models"
812
"github.com/mitchellh/mapstructure"
13+
"github.com/sirupsen/logrus"
914
"github.com/spf13/viper"
10-
"log"
11-
"os"
12-
"sort"
13-
"strings"
1415
)
1516

1617
// When initializing this class the following methods must be called:
@@ -67,29 +68,29 @@ func (c *configuration) Init() error {
6768
return nil
6869
}
6970

70-
func (c *configuration) ReadConfig(configFilePath string) error {
71+
func (c *configuration) ReadConfig(configFilePath string, logger *logrus.Entry) error {
7172
configFilePath, err := utils.ExpandPath(configFilePath)
7273
if err != nil {
7374
return err
7475
}
7576

7677
if !utils.FileExists(configFilePath) {
77-
log.Printf("No configuration file found at %v. Using Defaults.", configFilePath)
78+
logger.Infof("No configuration file found at %v. Using Defaults.", configFilePath)
7879
return errors.ConfigFileMissingError("The configuration file could not be found.")
7980
}
8081

8182
//validate config file contents
8283
//err = c.ValidateConfigFile(configFilePath)
8384
//if err != nil {
84-
// log.Printf("Config file at `%v` is invalid: %s", configFilePath, err)
85+
// logger.Errorf("Config file at `%v` is invalid: %s", configFilePath, err)
8586
// return err
8687
//}
8788

88-
log.Printf("Loading configuration file: %s", configFilePath)
89+
logger.Infof("Loading configuration file: %s", configFilePath)
8990

9091
config_data, err := os.Open(configFilePath)
9192
if err != nil {
92-
log.Printf("Error reading configuration file: %s", err)
93+
logger.Errorf("Error reading configuration file: %s", err)
9394
return err
9495
}
9596

collector/pkg/config/config_test.go

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
11
package config_test
22

33
import (
4+
"path"
5+
"testing"
6+
47
"github.com/analogj/scrutiny/collector/pkg/config"
58
"github.com/analogj/scrutiny/collector/pkg/models"
9+
"github.com/sirupsen/logrus"
610
"github.com/stretchr/testify/require"
7-
"path"
8-
"testing"
911
)
1012

13+
func testLogger() *logrus.Entry {
14+
return logrus.WithFields(logrus.Fields{"type": "test"})
15+
}
16+
1117
func TestConfiguration_InvalidConfigPath(t *testing.T) {
1218
t.Parallel()
1319

1420
//setup
1521
testConfig, _ := config.Create()
1622

1723
//test
18-
err := testConfig.ReadConfig("does_not_exist.yaml")
24+
err := testConfig.ReadConfig("does_not_exist.yaml", testLogger())
1925

2026
//assert
2127
require.Error(t, err, "should return an error")
@@ -28,7 +34,7 @@ func TestConfiguration_GetScanOverrides_Simple(t *testing.T) {
2834
testConfig, _ := config.Create()
2935

3036
//test
31-
err := testConfig.ReadConfig(path.Join("testdata", "simple_device.yaml"))
37+
err := testConfig.ReadConfig(path.Join("testdata", "simple_device.yaml"), testLogger())
3238
require.NoError(t, err, "should correctly load simple device config")
3339
scanOverrides := testConfig.GetDeviceOverrides()
3440

@@ -44,7 +50,7 @@ func TestConfiguration_GetScanOverrides_DeviceTypeComma(t *testing.T) {
4450
testConfig, _ := config.Create()
4551

4652
//test
47-
err := testConfig.ReadConfig(path.Join("testdata", "device_type_comma.yaml"))
53+
err := testConfig.ReadConfig(path.Join("testdata", "device_type_comma.yaml"), testLogger())
4854
require.NoError(t, err, "should correctly load simple device config")
4955
scanOverrides := testConfig.GetDeviceOverrides()
5056

@@ -62,7 +68,7 @@ func TestConfiguration_GetScanOverrides_Ignore(t *testing.T) {
6268
testConfig, _ := config.Create()
6369

6470
//test
65-
err := testConfig.ReadConfig(path.Join("testdata", "ignore_device.yaml"))
71+
err := testConfig.ReadConfig(path.Join("testdata", "ignore_device.yaml"), testLogger())
6672
require.NoError(t, err, "should correctly load ignore device config")
6773
scanOverrides := testConfig.GetDeviceOverrides()
6874

@@ -77,7 +83,7 @@ func TestConfiguration_GetScanOverrides_Raid(t *testing.T) {
7783
testConfig, _ := config.Create()
7884

7985
//test
80-
err := testConfig.ReadConfig(path.Join("testdata", "raid_device.yaml"))
86+
err := testConfig.ReadConfig(path.Join("testdata", "raid_device.yaml"), testLogger())
8187
require.NoError(t, err, "should correctly load ignore device config")
8288
scanOverrides := testConfig.GetDeviceOverrides()
8389

@@ -102,7 +108,7 @@ func TestConfiguration_InvalidCommands_MissingJson(t *testing.T) {
102108
testConfig, _ := config.Create()
103109

104110
//test
105-
err := testConfig.ReadConfig(path.Join("testdata", "invalid_commands_missing_json.yaml"))
111+
err := testConfig.ReadConfig(path.Join("testdata", "invalid_commands_missing_json.yaml"), testLogger())
106112
require.EqualError(t, err, `ConfigValidationError: "configuration key 'commands.metrics_scan_args' is missing '--json' flag"`, "should throw an error because json flag is missing")
107113
}
108114

@@ -113,7 +119,7 @@ func TestConfiguration_InvalidCommands_IncludesDevice(t *testing.T) {
113119
testConfig, _ := config.Create()
114120

115121
//test
116-
err := testConfig.ReadConfig(path.Join("testdata", "invalid_commands_includes_device.yaml"))
122+
err := testConfig.ReadConfig(path.Join("testdata", "invalid_commands_includes_device.yaml"), testLogger())
117123
require.EqualError(t, err, `ConfigValidationError: "configuration key 'commands.metrics_info_args' must not contain '--device' or '-d' flag, configuration key 'commands.metrics_smart_args' must not contain '--device' or '-d' flag"`, "should throw an error because device flags detected")
118124
}
119125

@@ -124,7 +130,7 @@ func TestConfiguration_OverrideCommands(t *testing.T) {
124130
testConfig, _ := config.Create()
125131

126132
//test
127-
err := testConfig.ReadConfig(path.Join("testdata", "override_commands.yaml"))
133+
err := testConfig.ReadConfig(path.Join("testdata", "override_commands.yaml"), testLogger())
128134
require.NoError(t, err, "should not throw an error")
129135
require.Equal(t, "--xall --json -T permissive", testConfig.GetString("commands.metrics_smart_args"))
130136
}
@@ -136,7 +142,7 @@ func TestConfiguration_OverrideDeviceCommands_MetricsInfoArgs(t *testing.T) {
136142
testConfig, _ := config.Create()
137143

138144
//test
139-
err := testConfig.ReadConfig(path.Join("testdata", "override_device_commands.yaml"))
145+
err := testConfig.ReadConfig(path.Join("testdata", "override_device_commands.yaml"), testLogger())
140146
require.NoError(t, err, "should correctly override device command")
141147

142148
//assert
@@ -152,7 +158,7 @@ func TestConfiguration_DeviceAllowList(t *testing.T) {
152158
testConfig, err := config.Create()
153159
require.NoError(t, err)
154160

155-
require.NoError(t, testConfig.ReadConfig(path.Join("testdata", "allow_listed_devices_present.yaml")))
161+
require.NoError(t, testConfig.ReadConfig(path.Join("testdata", "allow_listed_devices_present.yaml"), testLogger()))
156162

157163
require.True(t, testConfig.IsAllowlistedDevice("/dev/sda"), "/dev/sda should be allow listed")
158164
require.False(t, testConfig.IsAllowlistedDevice("/dev/sdc"), "/dev/sda should not be allow listed")
@@ -163,7 +169,7 @@ func TestConfiguration_DeviceAllowList(t *testing.T) {
163169
require.NoError(t, err)
164170

165171
// Really just any other config where the key is full missing
166-
require.NoError(t, testConfig.ReadConfig(path.Join("testdata", "override_device_commands.yaml")))
172+
require.NoError(t, testConfig.ReadConfig(path.Join("testdata", "override_device_commands.yaml"), testLogger()))
167173

168174
// Anything should be allow listed if the key isnt there
169175
require.True(t, testConfig.IsAllowlistedDevice("/dev/sda"), "/dev/sda should be allow listed")

collector/pkg/config/interface.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ package config
22

33
import (
44
"github.com/analogj/scrutiny/collector/pkg/models"
5+
"github.com/sirupsen/logrus"
56
"github.com/spf13/viper"
67
)
78

89
// Create mock using:
910
// mockgen -source=collector/pkg/config/interface.go -destination=collector/pkg/config/mock/mock_config.go
1011
type Interface interface {
1112
Init() error
12-
ReadConfig(configFilePath string) error
13+
ReadConfig(configFilePath string, logger *logrus.Entry) error
1314
Set(key string, value interface{})
1415
SetDefault(key string, value interface{})
1516

collector/pkg/config/mock/mock_config.go

Lines changed: 5 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

collector/pkg/detect/detect.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package detect
22

33
import (
44
"encoding/json"
5+
"errors"
56
"fmt"
67
"os"
8+
"os/exec"
79
"strings"
810

911
"github.com/analogj/scrutiny/collector/pkg/common/shell"
@@ -62,6 +64,17 @@ func (d *Detect) SmartCtlInfo(device *models.Device) error {
6264
args = append(args, fullDeviceName)
6365

6466
availableDeviceInfoJson, err := d.Shell.Command(d.Logger, d.Config.GetString("commands.metrics_smartctl_bin"), args, "", os.Environ())
67+
var exitErr *exec.ExitError
68+
if errors.As(err, &exitErr) {
69+
exitCode := exitErr.ExitCode()
70+
if exitCode&0xBF == 0 {
71+
d.Logger.Warnf("Successfully retrieved device information for %s, but received exit code %d, which is a non-fatal exit code. Continuing.", device.DeviceName, exitCode)
72+
} else {
73+
d.Logger.Errorf("Could not retrieve device information for %s: %v", device.DeviceName, err)
74+
return err
75+
}
76+
}
77+
6578
if err != nil {
6679
d.Logger.Errorf("Could not retrieve device information for %s: %v", device.DeviceName, err)
6780
return err
@@ -84,7 +97,6 @@ func (d *Detect) SmartCtlInfo(device *models.Device) error {
8497
device.RotationSpeed = availableDeviceInfo.RotationRate
8598
device.Capacity = availableDeviceInfo.Capacity()
8699
device.FormFactor = availableDeviceInfo.FormFactor.Name
87-
device.DeviceType = availableDeviceInfo.Device.Type
88100
device.DeviceProtocol = availableDeviceInfo.Device.Protocol
89101
if len(availableDeviceInfo.Vendor) > 0 {
90102
device.Manufacturer = availableDeviceInfo.Vendor

example.scrutiny.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ web:
3030
database:
3131
# can also set absolute path here
3232
location: /opt/scrutiny/config/scrutiny.db
33+
# SQLite journal mode: WAL (default), DELETE, TRUNCATE, PERSIST, MEMORY, OFF
34+
# WAL mode is recommended for Docker containers with restricted capabilities (cap_drop: [ALL])
35+
# If you experience database issues with WAL mode on network filesystems (NFS), try DELETE mode
36+
# journal_mode: WAL
3337
src:
3438
# the location on the filesystem where scrutiny javascript + css is located
3539
frontend:

webapp/backend/cmd/scrutiny/scrutiny.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ package main
33
import (
44
"encoding/json"
55
"fmt"
6-
"github.com/analogj/scrutiny/webapp/backend/pkg/config"
7-
"github.com/analogj/scrutiny/webapp/backend/pkg/errors"
8-
"github.com/analogj/scrutiny/webapp/backend/pkg/version"
9-
"github.com/analogj/scrutiny/webapp/backend/pkg/web"
10-
"github.com/sirupsen/logrus"
116
"io"
127
"log"
138
"os"
149
"time"
1510

1611
utils "github.com/analogj/go-util/utils"
12+
"github.com/analogj/scrutiny/webapp/backend/pkg/config"
13+
"github.com/analogj/scrutiny/webapp/backend/pkg/errors"
14+
"github.com/analogj/scrutiny/webapp/backend/pkg/version"
15+
"github.com/analogj/scrutiny/webapp/backend/pkg/web"
1716
"github.com/fatih/color"
17+
"github.com/sirupsen/logrus"
1818
"github.com/urfave/cli/v2"
1919
)
2020

@@ -35,9 +35,13 @@ func main() {
3535
configFilePath = configFilePathAlternative
3636
}
3737

38+
// Create a bootstrap logger for config loading (before config-based logger is available)
39+
bootstrapLogger := logrus.WithFields(logrus.Fields{"type": "web"})
40+
bootstrapLogger.Logger.SetLevel(logrus.InfoLevel)
41+
3842
//we're going to load the config file manually, since we need to validate it.
39-
err = config.ReadConfig(configFilePath) // Find and read the config file
40-
if _, ok := err.(errors.ConfigFileMissingError); ok { // Handle errors reading the config file
43+
err = config.ReadConfig(configFilePath, bootstrapLogger) // Find and read the config file
44+
if _, ok := err.(errors.ConfigFileMissingError); ok { // Handle errors reading the config file
4145
//ignore "could not find config file"
4246
} else if err != nil {
4347
log.Print(color.HiRedString("CONFIG ERROR: %v", err))
@@ -101,8 +105,8 @@ OPTIONS:
101105
Action: func(c *cli.Context) error {
102106
fmt.Fprintln(c.App.Writer, c.Command.Usage)
103107
if c.IsSet("config") {
104-
err = config.ReadConfig(c.String("config")) // Find and read the config file
105-
if err != nil { // Handle errors reading the config file
108+
err = config.ReadConfig(c.String("config"), bootstrapLogger) // Find and read the config file
109+
if err != nil { // Handle errors reading the config file
106110
//ignore "could not find config file"
107111
fmt.Printf("Could not find config file at specified path: %s", c.String("config"))
108112
return err

0 commit comments

Comments
 (0)