Просмотр исходного кода

Log clarity update -- quick fix (#3550)

Signed-off-by: Warwick Peatey <warwick.peatey@ibm.com>
Co-authored-by: Claude <noreply@anthropic.com>
Warwick 3 месяцев назад
Родитель
Сommit
da76af789f
3 измененных файлов с 123 добавлено и 3 удалено
  1. 1 1
      pkg/costmodel/cluster_helpers.go
  2. 121 0
      pkg/costmodel/cluster_helpers_test.go
  3. 1 2
      pkg/costmodel/costmodel.go

+ 1 - 1
pkg/costmodel/cluster_helpers.go

@@ -385,7 +385,7 @@ func buildCPUBreakdownMap(resNodeCPUModeTotal []*source.NodeCPUModeTotalResult)
 
 		mode := result.Mode
 		if mode == "" {
-			log.Warnf("ClusterNodes: unable to read CPU mode data.")
+			log.DedupedWarningf(10, "ClusterNodes: unable to read CPU mode data for node %s.", node)
 			mode = "other"
 		}
 

+ 121 - 0
pkg/costmodel/cluster_helpers_test.go

@@ -1230,3 +1230,124 @@ func TestBuildLabelsMap(t *testing.T) {
 		}
 	}
 }
+
+func TestBuildCPUBreakdownMap(t *testing.T) {
+	cases := []struct {
+		name     string
+		input    []*source.NodeCPUModeTotalResult
+		expected map[nodeIdentifierNoProviderID]*ClusterCostsBreakdown
+	}{
+		{
+			name:     "empty input",
+			input:    []*source.NodeCPUModeTotalResult{},
+			expected: map[nodeIdentifierNoProviderID]*ClusterCostsBreakdown{},
+		},
+		{
+			name: "normal modes",
+			input: []*source.NodeCPUModeTotalResult{
+				{
+					Cluster: "cluster1",
+					Node:    "node1",
+					Mode:    "idle",
+					Data:    []*util.Vector{{Value: 50.0}},
+				},
+				{
+					Cluster: "cluster1",
+					Node:    "node1",
+					Mode:    "user",
+					Data:    []*util.Vector{{Value: 30.0}},
+				},
+				{
+					Cluster: "cluster1",
+					Node:    "node1",
+					Mode:    "system",
+					Data:    []*util.Vector{{Value: 20.0}},
+				},
+			},
+			expected: map[nodeIdentifierNoProviderID]*ClusterCostsBreakdown{
+				{Cluster: "cluster1", Name: "node1"}: {
+					Idle:   0.5,
+					User:   0.3,
+					System: 0.2,
+				},
+			},
+		},
+		{
+			name: "empty mode falls back to other",
+			input: []*source.NodeCPUModeTotalResult{
+				{
+					Cluster: "cluster1",
+					Node:    "node1",
+					Mode:    "idle",
+					Data:    []*util.Vector{{Value: 50.0}},
+				},
+				{
+					Cluster: "cluster1",
+					Node:    "node1",
+					Mode:    "", // empty mode should be treated as "other"
+					Data:    []*util.Vector{{Value: 50.0}},
+				},
+			},
+			expected: map[nodeIdentifierNoProviderID]*ClusterCostsBreakdown{
+				{Cluster: "cluster1", Name: "node1"}: {
+					Idle:  0.5,
+					Other: 0.5,
+				},
+			},
+		},
+		{
+			name: "missing node is skipped",
+			input: []*source.NodeCPUModeTotalResult{
+				{
+					Cluster: "cluster1",
+					Node:    "", // empty node should be skipped
+					Mode:    "idle",
+					Data:    []*util.Vector{{Value: 50.0}},
+				},
+				{
+					Cluster: "cluster1",
+					Node:    "node1",
+					Mode:    "user",
+					Data:    []*util.Vector{{Value: 100.0}},
+				},
+			},
+			expected: map[nodeIdentifierNoProviderID]*ClusterCostsBreakdown{
+				{Cluster: "cluster1", Name: "node1"}: {
+					User: 1.0,
+				},
+			},
+		},
+	}
+
+	for _, tc := range cases {
+		t.Run(tc.name, func(t *testing.T) {
+			result := buildCPUBreakdownMap(tc.input)
+
+			if len(result) != len(tc.expected) {
+				t.Errorf("buildCPUBreakdownMap case %s: expected %d entries, got %d", tc.name, len(tc.expected), len(result))
+				return
+			}
+
+			for key, expectedBreakdown := range tc.expected {
+				actualBreakdown, ok := result[key]
+				if !ok {
+					t.Errorf("buildCPUBreakdownMap case %s: missing key %+v", tc.name, key)
+					continue
+				}
+
+				if !util.IsApproximately(actualBreakdown.Idle, expectedBreakdown.Idle) {
+					t.Errorf("buildCPUBreakdownMap case %s: Idle mismatch for %+v: expected %f, got %f", tc.name, key, expectedBreakdown.Idle, actualBreakdown.Idle)
+				}
+				if !util.IsApproximately(actualBreakdown.User, expectedBreakdown.User) {
+					t.Errorf("buildCPUBreakdownMap case %s: User mismatch for %+v: expected %f, got %f", tc.name, key, expectedBreakdown.User, actualBreakdown.User)
+				}
+				if !util.IsApproximately(actualBreakdown.System, expectedBreakdown.System) {
+					t.Errorf("buildCPUBreakdownMap case %s: System mismatch for %+v: expected %f, got %f", tc.name, key, expectedBreakdown.System, actualBreakdown.System)
+				}
+				if !util.IsApproximately(actualBreakdown.Other, expectedBreakdown.Other) {
+					t.Errorf("buildCPUBreakdownMap case %s: Other mismatch for %+v: expected %f, got %f", tc.name, key, expectedBreakdown.Other, actualBreakdown.Other)
+				}
+			}
+		})
+	}
+}

+ 1 - 2
pkg/costmodel/costmodel.go

@@ -915,8 +915,7 @@ func (cm *CostModel) GetNodeCost() (map[string]*costAnalyzerCloud.Node, error) {
 
 		cnode, _, err := cp.NodePricing(cp.GetKey(nodeLabels, n))
 		if err != nil {
-			log.Infof("Could not get node pricing for node %s. Falling back to default pricing", name)
-			log.Debugf("Error getting node pricing: %s", err.Error())
+			log.DedupedInfof(10, "Could not get node pricing for node %s: %s. Falling back to default pricing.", name, err.Error())
 			if cnode != nil {
 				nodes[name] = cnode
 				continue