Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add decimal precision to CPU and memory metrics in pod info #2221

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 26 additions & 5 deletions server/apis/v1/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -1598,24 +1598,24 @@ func (h *handler) getPodDetails(pod corev1.Pod) (PodDetails, error) {
memQuantity := container.Usage.Memory()
details, ok := containerDetails[containerName]
if !ok {
details = ContainerDetails{Name: container.Name} // Initialize if not found
details = ContainerDetails{Name: container.Name}
}
if cpuQuantity != nil {
details.TotalCPU = strconv.FormatInt(cpuQuantity.MilliValue(), 10) + "m"
details.TotalCPU = cpuToMillicores(cpuQuantity.String())
totalCPU.Add(*cpuQuantity)
}
if memQuantity != nil {
details.TotalMemory = strconv.FormatInt(memQuantity.Value()/(1024*1024), 10) + "Mi"
details.TotalMemory = fmt.Sprintf("%.2fMi", float64(memQuantity.Value())/(1024*1024))
totalMemory.Add(*memQuantity)
}
containerDetails[containerName] = details
}
if totalCPU != nil {
podDetails.TotalCPU = strconv.FormatInt(totalCPU.MilliValue(), 10) + "m"
podDetails.TotalCPU = cpuToMillicores(totalCPU.String())
}

if totalMemory != nil {
podDetails.TotalMemory = strconv.FormatInt(totalMemory.Value()/(1024*1024), 10) + "Mi"
podDetails.TotalMemory = fmt.Sprintf("%.2fMi", float64(totalMemory.Value())/(1024*1024))
}
}
return podDetails, nil
Expand Down Expand Up @@ -1684,3 +1684,24 @@ func (h *handler) getContainerStatus(state corev1.ContainerState) string {
return "Unknown"
}
}

func cpuToMillicores(quantityStr string) string {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't take Quantity directly so that there's no need to parse?

Copy link
Contributor Author

@adarsh0728 adarsh0728 Nov 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quantity is like:
quantity::= signedNumber|suffix. To get the suffix and calculate accordingly we're parsing the string.
For eg: 2847159n this is the cpuQuantity, cpuQuantity.MilliValue() will give us 3, but we want 2.84m as our final result. For that we divide 2847159/1e6

Screenshot 2024-11-19 at 12 22 08 PM

var value float64
var format string

// Parse the quantity string
if _, err := fmt.Sscanf(quantityStr, "%f%s", &value, &format); err != nil {
fmt.Println("Error parsing cpu quantity string:", err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there's a need for error handling, return it and handle it in upper layer.

return "0m"
}

// Adjust value based on the format suffix
switch {
case strings.HasSuffix(format, "n"):
value /= 1e6
case !strings.HasSuffix(format, "m"):
fmt.Println("Error parsing quantity string: invalid format")
return "0m"
}
return fmt.Sprintf("%.2fm", value)
}
43 changes: 33 additions & 10 deletions server/apis/v1/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -464,8 +464,8 @@ func TestHandler_GetMonoVertexPodsInfo(t *testing.T) {
if len(podInfos) > 0 {
assert.Equal(t, "test-pod-1", podInfos[0].Name)
assert.Equal(t, string(corev1.PodRunning), podInfos[0].Status)
assert.Equal(t, "150m", podInfos[0].TotalCPU)
assert.Equal(t, "150Mi", podInfos[0].TotalMemory)
assert.Equal(t, "150.00m", podInfos[0].TotalCPU)
assert.Equal(t, "150.00Mi", podInfos[0].TotalMemory)
}
}
})
Expand Down Expand Up @@ -662,8 +662,8 @@ func TestHandler_GetVertexPodsInfo(t *testing.T) {
assert.Len(t, podInfos, 1)
assert.Equal(t, "test-pod-1", podInfos[0].Name)
assert.Equal(t, string(corev1.PodRunning), podInfos[0].Status)
assert.Equal(t, "150m", podInfos[0].TotalCPU)
assert.Equal(t, "150Mi", podInfos[0].TotalMemory)
assert.Equal(t, "150.00m", podInfos[0].TotalCPU)
assert.Equal(t, "150.00Mi", podInfos[0].TotalMemory)
}
})
}
Expand Down Expand Up @@ -764,8 +764,8 @@ func TestHandler_GetPodDetails(t *testing.T) {
Status: "Running",
Message: "",
Reason: "",
TotalCPU: "250m",
TotalMemory: "500Mi",
TotalCPU: "250.00m",
TotalMemory: "500.00Mi",
ContainerDetailsMap: map[string]ContainerDetails{
"container-1": {
Name: "container-1",
Expand All @@ -777,8 +777,8 @@ func TestHandler_GetPodDetails(t *testing.T) {
RequestedMemory: "200Mi",
LimitCPU: "200m",
LimitMemory: "400Mi",
TotalCPU: "100m",
TotalMemory: "200Mi",
TotalCPU: "100.00m",
TotalMemory: "200.00Mi",
LastTerminationReason: "",
LastTerminationMessage: "",
WaitingReason: "",
Expand All @@ -794,8 +794,8 @@ func TestHandler_GetPodDetails(t *testing.T) {
RequestedMemory: "300Mi",
LimitCPU: "300m",
LimitMemory: "600Mi",
TotalCPU: "150m",
TotalMemory: "300Mi",
TotalCPU: "150.00m",
TotalMemory: "300.00Mi",
LastTerminationReason: "",
LastTerminationMessage: "",
LastStartedAt: "",
Expand Down Expand Up @@ -1028,3 +1028,26 @@ func TestHandler_GetContainerStatus(t *testing.T) {
})
}
}

func TestHandler_cpuToMillicores(t *testing.T) {
testCases := []struct {
input string
expected string
}{
{"2953072n", "2.95m"},
{"500m", "500.00m"},
{"10000n", "0.01m"},
{"0n", "0.00m"},
{"100000000g", "0m"},
{"invalid input", "0m"}, // Error case
}

for _, tc := range testCases {
t.Run(fmt.Sprintf("Input: %s", tc.input), func(t *testing.T) {
result := cpuToMillicores(tc.input)
if result != tc.expected {
t.Errorf("Expected: %s, Got: %s", tc.expected, result)
}
})
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions ui/src/utils/fetcherHooks/podsViewFetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
PodDetail,
} from "../../types/declarations/pods";


// TODO: calculate podsDetails from pods-info API
export const usePodsViewFetch = (
namespaceId: string | undefined,
pipelineId: string | undefined,
Expand Down
Loading