| @@ -211,7 +211,6 @@ func (p *criStatsProvider) listPodStatsPartiallyFromCRI(ctx context.Context, upd | |||||||
| 		p.addPodNetworkStats(ps, podSandboxID, caInfos, cs, containerNetworkStats[podSandboxID]) | 		p.addPodNetworkStats(ps, podSandboxID, caInfos, cs, containerNetworkStats[podSandboxID]) | ||||||
| 		p.addPodCPUMemoryStats(ps, types.UID(podSandbox.Metadata.Uid), allInfos, cs) | 		p.addPodCPUMemoryStats(ps, types.UID(podSandbox.Metadata.Uid), allInfos, cs) | ||||||
| 		p.addSwapStats(ps, types.UID(podSandbox.Metadata.Uid), allInfos, cs) | 		p.addSwapStats(ps, types.UID(podSandbox.Metadata.Uid), allInfos, cs) | ||||||
| 		p.addProcessStats(ps, types.UID(podSandbox.Metadata.Uid), allInfos, cs) |  | ||||||
|  |  | ||||||
| 		// If cadvisor stats is available for the container, use it to populate | 		// If cadvisor stats is available for the container, use it to populate | ||||||
| 		// container stats | 		// container stats | ||||||
| @@ -220,7 +219,9 @@ func (p *criStatsProvider) listPodStatsPartiallyFromCRI(ctx context.Context, upd | |||||||
| 			klog.V(5).InfoS("Unable to find cadvisor stats for container", "containerID", containerID) | 			klog.V(5).InfoS("Unable to find cadvisor stats for container", "containerID", containerID) | ||||||
| 		} else { | 		} else { | ||||||
| 			p.addCadvisorContainerStats(cs, &caStats) | 			p.addCadvisorContainerStats(cs, &caStats) | ||||||
|  | 			p.addProcessStats(ps, &caStats) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		ps.Containers = append(ps.Containers, *cs) | 		ps.Containers = append(ps.Containers, *cs) | ||||||
| 	} | 	} | ||||||
| 	// cleanup outdated caches. | 	// cleanup outdated caches. | ||||||
| @@ -584,17 +585,13 @@ func (p *criStatsProvider) addSwapStats( | |||||||
|  |  | ||||||
| func (p *criStatsProvider) addProcessStats( | func (p *criStatsProvider) addProcessStats( | ||||||
| 	ps *statsapi.PodStats, | 	ps *statsapi.PodStats, | ||||||
| 	podUID types.UID, | 	container *cadvisorapiv2.ContainerInfo, | ||||||
| 	allInfos map[string]cadvisorapiv2.ContainerInfo, |  | ||||||
| 	cs *statsapi.ContainerStats, |  | ||||||
| ) { | ) { | ||||||
| 	// try get process stats from cadvisor only. | 	processStats := cadvisorInfoToProcessStats(container) | ||||||
| 	info := getCadvisorPodInfoFromPodUID(podUID, allInfos) | 	// Sum up all of the process stats for each of the containers to obtain the cumulative pod level process count | ||||||
| 	if info != nil { | 	ps.ProcessStats = mergeProcessStats(ps.ProcessStats, processStats) | ||||||
| 		ps.ProcessStats = cadvisorInfoToProcessStats(info) |  | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *criStatsProvider) makeContainerStats( | func (p *criStatsProvider) makeContainerStats( | ||||||
| 	stats *runtimeapi.ContainerStats, | 	stats *runtimeapi.ContainerStats, | ||||||
|   | |||||||
| @@ -168,6 +168,31 @@ func cadvisorInfoToProcessStats(info *cadvisorapiv2.ContainerInfo) *statsapi.Pro | |||||||
| 	return &statsapi.ProcessStats{ProcessCount: uint64Ptr(num)} | 	return &statsapi.ProcessStats{ProcessCount: uint64Ptr(num)} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func mergeProcessStats(first *statsapi.ProcessStats, second *statsapi.ProcessStats) *statsapi.ProcessStats { | ||||||
|  | 	if first == nil && second == nil { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if first == nil { | ||||||
|  | 		return second | ||||||
|  | 	} | ||||||
|  | 	if second == nil { | ||||||
|  | 		return first | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	firstProcessCount := uint64(0) | ||||||
|  | 	if first.ProcessCount != nil { | ||||||
|  | 		firstProcessCount = *first.ProcessCount | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	secondProcessCount := uint64(0) | ||||||
|  | 	if second.ProcessCount != nil { | ||||||
|  | 		secondProcessCount = *second.ProcessCount | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return &statsapi.ProcessStats{ProcessCount: uint64Ptr(firstProcessCount + secondProcessCount)} | ||||||
|  | } | ||||||
|  |  | ||||||
| // cadvisorInfoToNetworkStats returns the statsapi.NetworkStats converted from | // cadvisorInfoToNetworkStats returns the statsapi.NetworkStats converted from | ||||||
| // the container info from cadvisor. | // the container info from cadvisor. | ||||||
| func cadvisorInfoToNetworkStats(info *cadvisorapiv2.ContainerInfo) *statsapi.NetworkStats { | func cadvisorInfoToNetworkStats(info *cadvisorapiv2.ContainerInfo) *statsapi.NetworkStats { | ||||||
|   | |||||||
| @@ -22,10 +22,12 @@ import ( | |||||||
|  |  | ||||||
| 	cadvisorapiv1 "github.com/google/cadvisor/info/v1" | 	cadvisorapiv1 "github.com/google/cadvisor/info/v1" | ||||||
| 	cadvisorapiv2 "github.com/google/cadvisor/info/v2" | 	cadvisorapiv2 "github.com/google/cadvisor/info/v2" | ||||||
|  | 	"github.com/google/go-cmp/cmp" | ||||||
| 	"github.com/stretchr/testify/assert" | 	"github.com/stretchr/testify/assert" | ||||||
|  |  | ||||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||||
| 	statsapi "k8s.io/kubelet/pkg/apis/stats/v1alpha1" | 	statsapi "k8s.io/kubelet/pkg/apis/stats/v1alpha1" | ||||||
|  | 	"k8s.io/utils/pointer" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func TestCustomMetrics(t *testing.T) { | func TestCustomMetrics(t *testing.T) { | ||||||
| @@ -97,3 +99,44 @@ func TestCustomMetrics(t *testing.T) { | |||||||
| 			Value: 2.1, | 			Value: 2.1, | ||||||
| 		}) | 		}) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestMergeProcessStats(t *testing.T) { | ||||||
|  | 	for _, tc := range []struct { | ||||||
|  | 		desc     string | ||||||
|  | 		first    *statsapi.ProcessStats | ||||||
|  | 		second   *statsapi.ProcessStats | ||||||
|  | 		expected *statsapi.ProcessStats | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			desc:     "both nil", | ||||||
|  | 			first:    nil, | ||||||
|  | 			second:   nil, | ||||||
|  | 			expected: nil, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			desc:     "first non-nil, second not", | ||||||
|  | 			first:    &statsapi.ProcessStats{ProcessCount: pointer.Uint64(100)}, | ||||||
|  | 			second:   nil, | ||||||
|  | 			expected: &statsapi.ProcessStats{ProcessCount: pointer.Uint64(100)}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			desc:     "first nil, second non-nil", | ||||||
|  | 			first:    nil, | ||||||
|  | 			second:   &statsapi.ProcessStats{ProcessCount: pointer.Uint64(100)}, | ||||||
|  | 			expected: &statsapi.ProcessStats{ProcessCount: pointer.Uint64(100)}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			desc:     "both non nill", | ||||||
|  | 			first:    &statsapi.ProcessStats{ProcessCount: pointer.Uint64(100)}, | ||||||
|  | 			second:   &statsapi.ProcessStats{ProcessCount: pointer.Uint64(100)}, | ||||||
|  | 			expected: &statsapi.ProcessStats{ProcessCount: pointer.Uint64(200)}, | ||||||
|  | 		}, | ||||||
|  | 	} { | ||||||
|  | 		t.Run(tc.desc, func(t *testing.T) { | ||||||
|  | 			got := mergeProcessStats(tc.first, tc.second) | ||||||
|  | 			if diff := cmp.Diff(tc.expected, got); diff != "" { | ||||||
|  | 				t.Fatalf("Unexpected diff on process stats (-want,+got):\n%s", diff) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 David Porter
					David Porter