From 297f0a51c50b86177445640cb018e02e7d1afcbb Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Sat, 19 Sep 2020 18:51:35 -0600 Subject: [PATCH] adding ability to write a log file with all output from collector. Executing commands will now log be logged (and when debug is enabled, their output's are also logged). --- .../cmd/collector-metrics/collector-metrics.go | 17 +++++++++++++++++ .../collector-selftest/collector-selftest.go | 17 +++++++++++++++++ collector/pkg/collector/metrics.go | 2 +- collector/pkg/common/exec.go | 8 +++++--- collector/pkg/common/exec_test.go | 7 ++++--- collector/pkg/detect/detect.go | 5 +++-- collector/pkg/detect/devices_darwin.go | 2 ++ collector/pkg/detect/devices_linux.go | 2 ++ 8 files changed, 51 insertions(+), 9 deletions(-) diff --git a/collector/cmd/collector-metrics/collector-metrics.go b/collector/cmd/collector-metrics/collector-metrics.go index c7f76ac..dcaed1f 100644 --- a/collector/cmd/collector-metrics/collector-metrics.go +++ b/collector/cmd/collector-metrics/collector-metrics.go @@ -5,6 +5,7 @@ import ( "github.com/analogj/scrutiny/collector/pkg/collector" "github.com/analogj/scrutiny/webapp/backend/pkg/version" "github.com/sirupsen/logrus" + "io" "log" "os" "time" @@ -85,6 +86,16 @@ OPTIONS: logrus.SetLevel(logrus.InfoLevel) } + if c.IsSet("log-file") { + logFile, err := os.OpenFile(c.String("log-file"), os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + logrus.Errorf("Failed to open log file %s for output: %s", c.String("log-file"), err) + return err + } + defer logFile.Close() + logrus.SetOutput(io.MultiWriter(os.Stderr, logFile)) + } + metricCollector, err := collector.CreateMetricsCollector( collectorLogger, c.String("api-endpoint"), @@ -105,6 +116,12 @@ OPTIONS: EnvVars: []string{"SCRUTINY_API_ENDPOINT"}, }, + &cli.StringFlag{ + Name: "log-file", + Usage: "Path to file for logging. Leave empty to use STDOUT", + Value: "", + }, + &cli.BoolFlag{ Name: "debug", Usage: "Enable debug logging", diff --git a/collector/cmd/collector-selftest/collector-selftest.go b/collector/cmd/collector-selftest/collector-selftest.go index 3800a5f..aa01826 100644 --- a/collector/cmd/collector-selftest/collector-selftest.go +++ b/collector/cmd/collector-selftest/collector-selftest.go @@ -5,6 +5,7 @@ import ( "github.com/analogj/scrutiny/collector/pkg/collector" "github.com/analogj/scrutiny/webapp/backend/pkg/version" "github.com/sirupsen/logrus" + "io" "log" "os" "time" @@ -85,6 +86,16 @@ OPTIONS: logrus.SetLevel(logrus.InfoLevel) } + if c.IsSet("log-file") { + logFile, err := os.OpenFile(c.String("log-file"), os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + logrus.Errorf("Failed to open log file %s for output: %s", c.String("log-file"), err) + return err + } + defer logFile.Close() + logrus.SetOutput(io.MultiWriter(os.Stderr, logFile)) + } + stCollector, err := collector.CreateSelfTestCollector( collectorLogger, c.String("api-endpoint"), @@ -105,6 +116,12 @@ OPTIONS: EnvVars: []string{"SCRUTINY_API_ENDPOINT"}, }, + &cli.StringFlag{ + Name: "log-file", + Usage: "Path to file for logging. Leave empty to use STDOUT", + Value: "", + }, + &cli.BoolFlag{ Name: "debug", Usage: "Enable debug logging", diff --git a/collector/pkg/collector/metrics.go b/collector/pkg/collector/metrics.go index 8643a23..722ebb1 100644 --- a/collector/pkg/collector/metrics.go +++ b/collector/pkg/collector/metrics.go @@ -109,7 +109,7 @@ func (mc *MetricsCollector) Collect(wg *sync.WaitGroup, deviceWWN string, device } args = append(args, fmt.Sprintf("%s%s", detect.DevicePrefix(), deviceName)) - result, err := common.ExecCmd("smartctl", args, "", os.Environ()) + result, err := common.ExecCmd(mc.logger, "smartctl", args, "", os.Environ()) resultBytes := []byte(result) if err != nil { if exitError, ok := err.(*exec.ExitError); ok { diff --git a/collector/pkg/common/exec.go b/collector/pkg/common/exec.go index 97a28c1..b17ea22 100644 --- a/collector/pkg/common/exec.go +++ b/collector/pkg/common/exec.go @@ -3,17 +3,19 @@ package common import ( "bytes" "errors" + "github.com/sirupsen/logrus" "io" - "os" "os/exec" "path" + "strings" ) -func ExecCmd(cmdName string, cmdArgs []string, workingDir string, environ []string) (string, error) { +func ExecCmd(logger *logrus.Entry, cmdName string, cmdArgs []string, workingDir string, environ []string) (string, error) { + logger.Infof("Executing command: %s %s", cmdName, strings.Join(cmdArgs, " ")) cmd := exec.Command(cmdName, cmdArgs...) var stdBuffer bytes.Buffer - mw := io.MultiWriter(os.Stdout, &stdBuffer) + mw := io.MultiWriter(logger.Logger.Out, &stdBuffer) cmd.Stdout = mw cmd.Stderr = mw diff --git a/collector/pkg/common/exec_test.go b/collector/pkg/common/exec_test.go index ef75a3e..846417c 100644 --- a/collector/pkg/common/exec_test.go +++ b/collector/pkg/common/exec_test.go @@ -2,6 +2,7 @@ package common_test import ( "github.com/analogj/scrutiny/collector/pkg/common" + "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" "os/exec" "testing" @@ -13,7 +14,7 @@ func TestExecCmd(t *testing.T) { //setup //test - result, err := common.ExecCmd("echo", []string{"hello world"}, "", nil) + result, err := common.ExecCmd(logrus.WithField("exec", "test"), "echo", []string{"hello world"}, "", nil) //assert require.NoError(t, err) @@ -26,7 +27,7 @@ func TestExecCmd_Date(t *testing.T) { //setup //test - _, err := common.ExecCmd("date", []string{}, "", nil) + _, err := common.ExecCmd(logrus.WithField("exec", "test"), "date", []string{}, "", nil) //assert require.NoError(t, err) @@ -56,7 +57,7 @@ func TestExecCmd_InvalidCommand(t *testing.T) { //setup //test - _, err := common.ExecCmd("invalid_binary", []string{}, "", nil) + _, err := common.ExecCmd(logrus.WithField("exec", "test"), "invalid_binary", []string{}, "", nil) //assert _, castOk := err.(*exec.ExitError) diff --git a/collector/pkg/detect/detect.go b/collector/pkg/detect/detect.go index 5899adb..7eb830a 100644 --- a/collector/pkg/detect/detect.go +++ b/collector/pkg/detect/detect.go @@ -26,7 +26,7 @@ type Detect struct { // models.Device returned from this function only contain the minimum data for smartctl to execute: device type and device name (device file). func (d *Detect) smartctlScan() ([]models.Device, error) { //we use smartctl to detect all the drives available. - detectedDeviceConnJson, err := common.ExecCmd("smartctl", []string{"--scan", "-j"}, "", os.Environ()) + detectedDeviceConnJson, err := common.ExecCmd(d.Logger, "smartctl", []string{"--scan", "-j"}, "", os.Environ()) if err != nil { d.Logger.Errorf("Error scanning for devices: %v", err) return nil, err @@ -64,7 +64,7 @@ func (d *Detect) smartCtlInfo(device *models.Device) error { } args = append(args, fmt.Sprintf("%s%s", DevicePrefix(), device.DeviceName)) - availableDeviceInfoJson, err := common.ExecCmd("smartctl", args, "", os.Environ()) + availableDeviceInfoJson, err := common.ExecCmd(d.Logger, "smartctl", args, "", os.Environ()) if err != nil { d.Logger.Errorf("Could not retrieve device information for %s: %v", device.DeviceName, err) return err @@ -101,6 +101,7 @@ func (d *Detect) smartCtlInfo(device *models.Device) error { Id: availableDeviceInfo.Wwn.ID, } device.WWN = wwn.ToString() + d.Logger.Debugf("NAA: %d OUI: %d Id: %d => WWN: %s", wwn.Naa, wwn.Oui, wwn.Id, device.WWN) } else { d.Logger.Info("Using WWN Fallback") d.wwnFallback(device) diff --git a/collector/pkg/detect/devices_darwin.go b/collector/pkg/detect/devices_darwin.go index 4e55693..b2a2ffd 100644 --- a/collector/pkg/detect/devices_darwin.go +++ b/collector/pkg/detect/devices_darwin.go @@ -93,6 +93,7 @@ func (d *Detect) wwnFallback(detectedDevice *models.Device) { if err == nil { for _, disk := range block.Disks { if disk.Name == detectedDevice.DeviceName { + d.Logger.Debugf("Found matching block device. WWN: %s", disk.WWN) detectedDevice.WWN = disk.WWN break } @@ -101,6 +102,7 @@ func (d *Detect) wwnFallback(detectedDevice *models.Device) { //no WWN found, or could not open Block devices. Either way, fallback to serial number if len(detectedDevice.WWN) == 0 { + d.Logger.Debugf("WWN is empty, falling back to serial number: %s", detectedDevice.SerialNumber) detectedDevice.WWN = detectedDevice.SerialNumber } } diff --git a/collector/pkg/detect/devices_linux.go b/collector/pkg/detect/devices_linux.go index 6a97623..3b12406 100644 --- a/collector/pkg/detect/devices_linux.go +++ b/collector/pkg/detect/devices_linux.go @@ -30,6 +30,7 @@ func (d *Detect) wwnFallback(detectedDevice *models.Device) { if err == nil { for _, disk := range block.Disks { if disk.Name == detectedDevice.DeviceName { + d.Logger.Debugf("Found matching block device. WWN: %s", disk.WWN) detectedDevice.WWN = disk.WWN break } @@ -38,6 +39,7 @@ func (d *Detect) wwnFallback(detectedDevice *models.Device) { //no WWN found, or could not open Block devices. Either way, fallback to serial number if len(detectedDevice.WWN) == 0 { + d.Logger.Debugf("WWN is empty, falling back to serial number: %s", detectedDevice.SerialNumber) detectedDevice.WWN = detectedDevice.SerialNumber } }