Modify the function CollectUSEMetrics

Modify the function CollectUSEMetrics so that it takes
in a component instead of being implemented by every
component. This removes repetition that was originally
present

Change-Id: I3d5a6def8102609924a63b4a6d68c6d3807b5cfd
Reviewed-on: https://cos-review.googlesource.com/c/cos/tools/+/20670
Cloud-Build: GCB Service account <228075978874@cloudbuild.gserviceaccount.com>
Reviewed-by: Dexter Rivera <riverade@google.com>
Tested-by: Dexter Rivera <riverade@google.com>
diff --git a/src/pkg/nodeprofiler/cloudlogger/cloudlogger_test.go b/src/pkg/nodeprofiler/cloudlogger/cloudlogger_test.go
index 3aac11a..856d9ea 100644
--- a/src/pkg/nodeprofiler/cloudlogger/cloudlogger_test.go
+++ b/src/pkg/nodeprofiler/cloudlogger/cloudlogger_test.go
@@ -1,7 +1,6 @@
 package cloudlogger
 
 import (
-	"fmt"
 	"io/ioutil"
 	"testing"
 	"time"
@@ -9,8 +8,8 @@
 	"cloud.google.com/go/logging"
 	"cos.googlesource.com/cos/tools.git/src/pkg/nodeprofiler/profiler"
 	"cos.googlesource.com/cos/tools.git/src/pkg/nodeprofiler/utils"
-
 	"github.com/google/go-cmp/cmp"
+	"github.com/google/go-cmp/cmp/cmpopts"
 )
 
 // fakeCPU is a struct that implements the Component interface.
@@ -36,24 +35,6 @@
 	return nil
 }
 
-// Collect USEMetrics behavior with regards to type fakeCPU.
-func (f *fakeCPU) CollectUSEMetrics(outputs map[string]utils.ParsedOutput) error {
-	metrics := f.Metrics
-	metrics.Timestamp = time.Date(2021, time.July, 21, 9, 59, 30, 0, time.UTC)
-	// setting an arbitrary start time.
-	start := metrics.Timestamp
-	if err := f.CollectUtilization(outputs); err != nil {
-		return fmt.Errorf("failed to collect utilization for CPU: %v", err)
-	}
-	if err := f.CollectSaturation(outputs); err != nil {
-		return fmt.Errorf("failed to collect saturation for CPU: %v", err)
-	}
-	// setting an arbitrary end time.
-	end := time.Date(2021, time.July, 21, 10, 3, 0, 0, time.UTC)
-	metrics.Interval = end.Sub(start)
-	return nil
-}
-
 // USEMetrics behavior with regards to type fakeCPU.
 func (f *fakeCPU) USEMetrics() *profiler.USEMetrics {
 	return f.Metrics
@@ -87,24 +68,6 @@
 	return nil
 }
 
-// Collect USEMetrics behavior with regards to type fakeMemCap.
-func (f *fakeMemCap) CollectUSEMetrics(outputs map[string]utils.ParsedOutput) error {
-	metrics := f.Metrics
-	metrics.Timestamp = time.Date(2021, time.July, 21, 9, 59, 30, 0, time.UTC)
-	// setting an arbitrary start time.
-	start := metrics.Timestamp
-	if err := f.CollectUtilization(outputs); err != nil {
-		return fmt.Errorf("failed to collect utilization for CPU: %v", err)
-	}
-	if err := f.CollectSaturation(outputs); err != nil {
-		return fmt.Errorf("failed to collect saturation for CPU: %v", err)
-	}
-	// setting an arbitrary end time.
-	end := time.Date(2021, time.July, 21, 10, 3, 0, 0, time.UTC)
-	metrics.Interval = end.Sub(start)
-	return nil
-}
-
 // USEMetrics behavior with regards to type fakeMemCap.
 func (f *fakeMemCap) USEMetrics() *profiler.USEMetrics {
 	return f.Metrics
@@ -138,24 +101,6 @@
 	return nil
 }
 
-// Collect USEMetrics behavior with regards to type fakeStorageDevIO.
-func (f *fakeStorageDevIO) CollectUSEMetrics(outputs map[string]utils.ParsedOutput) error {
-	metrics := f.Metrics
-	metrics.Timestamp = time.Date(2021, time.July, 21, 9, 59, 30, 0, time.UTC)
-	// setting an arbitrary start time.
-	start := metrics.Timestamp
-	if err := f.CollectUtilization(outputs); err != nil {
-		return fmt.Errorf("failed to collect utilization for CPU: %v", err)
-	}
-	if err := f.CollectSaturation(outputs); err != nil {
-		return fmt.Errorf("failed to collect saturation for CPU: %v", err)
-	}
-	// setting an arbitrary end time.
-	end := time.Date(2021, time.July, 21, 10, 3, 0, 0, time.UTC)
-	metrics.Interval = end.Sub(start)
-	return nil
-}
-
 // USEMetrics behavior with regards to type fakeStorageDevIO.
 func (f *fakeStorageDevIO) USEMetrics() *profiler.USEMetrics {
 	return f.Metrics
@@ -461,7 +406,8 @@
 		if gotErr := err != nil; gotErr != test.wantErr {
 			t.Errorf("LogProfilerReport(%v, %v) = %v, wantErr %t", f, test.input, err, test.wantErr)
 		}
-		if diff := cmp.Diff(test.wantOutput, f.logged); diff != "" {
+
+		if diff := cmp.Diff(f.logged, test.wantOutput, cmpopts.IgnoreFields(profiler.USEMetrics{}, "Timestamp", "Interval")); diff != "" {
 			t.Errorf("ran LogProfilerReport(fakeStructuredLogger,%+v), but got mismatch between got and want (-got, +want): \n diff %s", test.input, diff)
 
 		}
diff --git a/src/pkg/nodeprofiler/profiler/components.go b/src/pkg/nodeprofiler/profiler/components.go
index 40b16bf..86730b1 100644
--- a/src/pkg/nodeprofiler/profiler/components.go
+++ b/src/pkg/nodeprofiler/profiler/components.go
@@ -27,8 +27,6 @@
 	// It takes in a map of commands to their parsed output and uses that
 	// to specify which commands (and therefore output) it needs.
 	CollectErrors(cmdOutputs map[string]utils.ParsedOutput) error
-	// CollectUSEMetrics collects USEMetrics for the component.
-	CollectUSEMetrics(cmdOutputs map[string]utils.ParsedOutput) error
 	// USEMetrics returns the USEMetrics of the component.
 	USEMetrics() *USEMetrics
 	// Name returns the name of the component.
@@ -187,32 +185,6 @@
 	return nil
 }
 
-// CollectUSEMetrics collects USE Metrics for the CPU component.
-func (c *CPU) CollectUSEMetrics(outputs map[string]utils.ParsedOutput) error {
-	metrics := c.metrics
-	metrics.Timestamp = time.Now()
-	start := metrics.Timestamp
-
-	var gotErr bool
-	if err := c.CollectUtilization(outputs); err != nil {
-		gotErr = true
-		log.Errorf("failed to collect utilization for CPU: %v", err)
-	}
-	if err := c.CollectSaturation(outputs); err != nil {
-		gotErr = true
-		log.Errorf("failed to collect saturation for CPU: %v", err)
-	}
-	end := time.Now()
-	metrics.Interval = end.Sub(start)
-
-	if gotErr {
-		err := "failed to collect all USE Metrics for CPU. " +
-			"Please check the logs for more information"
-		return fmt.Errorf(err)
-	}
-	return nil
-}
-
 // MemCap holds information about the Memory capacity component:
 // name and USE Metrics collected.
 type MemCap struct {
@@ -358,32 +330,6 @@
 	return nil
 }
 
-// CollectUSEMetrics collects USE Metrics for the MemCap component.
-func (m *MemCap) CollectUSEMetrics(outputs map[string]utils.ParsedOutput) error {
-	metrics := m.metrics
-	metrics.Timestamp = time.Now()
-	start := metrics.Timestamp
-
-	var gotErr bool
-	if err := m.CollectUtilization(outputs); err != nil {
-		gotErr = true
-		log.Errorf("failed to collect utilization for Memory capacity: %v", err)
-	}
-	if err := m.CollectSaturation(outputs); err != nil {
-		gotErr = true
-		log.Errorf("failed to collect saturation for Memory capacity: %v", err)
-	}
-	end := time.Now()
-	metrics.Interval = end.Sub(start)
-
-	if gotErr {
-		err := "failed to collect all USE metrics for Memory Capacity. " +
-			"Please check the logs for more information"
-		return fmt.Errorf(err)
-	}
-	return nil
-}
-
 // StorageDevIO holds information about the Storage device I/O component:
 // name and USE Metrics collected.
 type StorageDevIO struct {
@@ -466,32 +412,6 @@
 	return nil
 }
 
-// CollectUSEMetrics collects USE Metrics for the Storage Device I/O component.
-func (d *StorageDevIO) CollectUSEMetrics(outputs map[string]utils.ParsedOutput) error {
-	metrics := d.metrics
-	metrics.Timestamp = time.Now()
-	start := metrics.Timestamp
-
-	var gotErr bool
-	if err := d.CollectUtilization(outputs); err != nil {
-		gotErr = true
-		log.Errorf("failed to collect utilization for Storage Device I/O: %v", err)
-	}
-	if err := d.CollectSaturation(outputs); err != nil {
-		gotErr = true
-		log.Errorf("failed to collect saturation for Storage Device I/O: %v", err)
-	}
-	end := time.Now()
-	metrics.Interval = end.Sub(start)
-
-	if gotErr {
-		err := "failed to collect all USE metrics for Storage Device I/O. " +
-			"Please check the logs for more information"
-		return fmt.Errorf(err)
-	}
-	return nil
-}
-
 // StorageCap holds information about the Storage Capacity component:
 // name and USE Metrics collected.
 type StorageCap struct {
@@ -601,30 +521,6 @@
 	return nil
 }
 
-// CollectUSEMetrics collects USE Metrics for the Storage Capacity component
-func (s *StorageCap) CollectUSEMetrics(outputs map[string]utils.ParsedOutput) error {
-	metrics := s.metrics
-	metrics.Timestamp = time.Now()
-	start := metrics.Timestamp
-
-	var gotErr bool
-	if err := s.CollectUtilization(outputs); err != nil {
-		gotErr = true
-		log.Errorf("failed to collect utilization for Storage capacity: %v", err)
-	}
-	if err := s.CollectSaturation(outputs); err != nil {
-		gotErr = true
-		log.Errorf("failed to collect saturation for Storage capacity: %v", err)
-	}
-	end := time.Now()
-	metrics.Interval = end.Sub(start)
-
-	if gotErr {
-		return fmt.Errorf("got error when collecting USE Metrics for Storage Capacity")
-	}
-	return nil
-}
-
 func (s *StorageCap) USEMetrics() *USEMetrics {
 	return s.metrics
 }
@@ -633,6 +529,34 @@
 	return s.name
 }
 
+// CollectUSEMetrics collects USE Metrics for the component specified. It does this by calling
+// the necessary methods to collect utilization, saturation and errors.
+func CollectUSEMetrics(component Component, outputs map[string]utils.ParsedOutput) error {
+
+	metrics := component.USEMetrics()
+	metrics.Timestamp = time.Now()
+	start := metrics.Timestamp
+
+	var gotErr bool
+	if err := component.CollectUtilization(outputs); err != nil {
+		gotErr = true
+		log.Errorf("failed to collect utilization for %q: %v", component.Name(), err)
+	}
+	if err := component.CollectSaturation(outputs); err != nil {
+		gotErr = true
+		log.Errorf("failed to collect saturation for %q: %v", component.Name(), err)
+	}
+	end := time.Now()
+	metrics.Interval = end.Sub(start)
+
+	if gotErr {
+		err := "failed to collect all USE metrics for %q. " +
+			"Please check the logs for more information"
+		return fmt.Errorf(err, component.Name())
+	}
+	return nil
+}
+
 // GenerateUSEReport generates USE Metrics for all the components
 // as well as an analysis string to help the diagnose performance issues.
 func GenerateUSEReport(components []Component, cmds []Command) (USEReport, error) {
@@ -649,7 +573,7 @@
 	}
 	var failed []string
 	for _, s := range components {
-		if err := s.CollectUSEMetrics(outputs); err != nil {
+		if err := CollectUSEMetrics(s, outputs); err != nil {
 			log.Errorf("failed to collect USE metrics for %q", s.Name())
 			failed = append(failed, s.Name())
 		}