Skip to content

Commit

Permalink
limitrequest metrics added : for pod + container (#40)
Browse files Browse the repository at this point in the history
  • Loading branch information
bhogayatakb authored Jan 6, 2024
1 parent f4169e2 commit d9e87fd
Show file tree
Hide file tree
Showing 14 changed files with 1,182 additions and 271 deletions.
64 changes: 64 additions & 0 deletions receiver/kubeletstatsreceiver/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,38 @@ The time since the container started
| ---- | ----------- | ---------- | ----------------------- | --------- |
| s | Sum | Int | Cumulative | true |
### k8s.container.cpu_limit_utilization
Container cpu utilization as a ratio of the container's limits
| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| 1 | Gauge | Double |
### k8s.container.cpu_request_utilization
Container cpu utilization as a ratio of the container's requests
| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| 1 | Gauge | Double |
### k8s.container.memory_limit_utilization
Container memory utilization as a ratio of the container's limits
| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| 1 | Gauge | Double |
### k8s.container.memory_request_utilization
Container memory utilization as a ratio of the container's requests
| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| 1 | Gauge | Double |
### k8s.node.uptime
The time since the node started
Expand All @@ -402,6 +434,38 @@ The time since the node started
| ---- | ----------- | ---------- | ----------------------- | --------- |
| s | Sum | Int | Cumulative | true |
### k8s.pod.cpu_limit_utilization
Pod cpu utilization as a ratio of the pod's total container limits. If any container is missing a limit the metric is not emitted.
| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| 1 | Gauge | Double |
### k8s.pod.cpu_request_utilization
Pod cpu utilization as a ratio of the pod's total container requests. If any container is missing a request the metric is not emitted.
| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| 1 | Gauge | Double |
### k8s.pod.memory_limit_utilization
Pod memory utilization as a ratio of the pod's total container limits. If any container is missing a limit the metric is not emitted.
| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| 1 | Gauge | Double |
### k8s.pod.memory_request_utilization
Pod memory utilization as a ratio of the pod's total container requests. If any container is missing a request the metric is not emitted.
| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| 1 | Gauge | Double |
### k8s.pod.uptime
The time since the pod started
Expand Down
13 changes: 7 additions & 6 deletions receiver/kubeletstatsreceiver/internal/kubelet/accumulator.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ func (a *metricDataAccumulator) nodeStats(s stats.NodeStats) {

currentTime := pcommon.NewTimestampFromTime(a.time)
addUptimeMetric(a.mbs.NodeMetricsBuilder, metadata.NodeUptimeMetrics.Uptime, s.StartTime, currentTime)
addCPUMetrics(a.mbs.NodeMetricsBuilder, metadata.NodeCPUMetrics, s.CPU, currentTime)
addMemoryMetrics(a.mbs.NodeMetricsBuilder, metadata.NodeMemoryMetrics, s.Memory, currentTime)
addCPUMetrics(a.mbs.NodeMetricsBuilder, metadata.NodeCPUMetrics, s.CPU, currentTime, resources{})
addMemoryMetrics(a.mbs.NodeMetricsBuilder, metadata.NodeMemoryMetrics, s.Memory, currentTime, resources{})
addFilesystemMetrics(a.mbs.NodeMetricsBuilder, metadata.NodeFilesystemMetrics, s.Fs, currentTime)
addNetworkMetrics(a.mbs.NodeMetricsBuilder, metadata.NodeNetworkMetrics, s.Network, currentTime)
// todo s.Runtime.ImageFs
Expand Down Expand Up @@ -91,8 +91,8 @@ func (a *metricDataAccumulator) podStats(s stats.PodStats) {

currentTime := pcommon.NewTimestampFromTime(a.time)
addUptimeMetric(a.mbs.PodMetricsBuilder, metadata.PodUptimeMetrics.Uptime, s.StartTime, currentTime)
addCPUMetrics(a.mbs.PodMetricsBuilder, metadata.PodCPUMetrics, s.CPU, currentTime)
addMemoryMetrics(a.mbs.PodMetricsBuilder, metadata.PodMemoryMetrics, s.Memory, currentTime)
addCPUMetrics(a.mbs.PodMetricsBuilder, metadata.PodCPUMetrics, s.CPU, currentTime, a.metadata.podResources[s.PodRef.UID])
addMemoryMetrics(a.mbs.PodMetricsBuilder, metadata.PodMemoryMetrics, s.Memory, currentTime, a.metadata.podResources[s.PodRef.UID])
addFilesystemMetrics(a.mbs.PodMetricsBuilder, metadata.PodFilesystemMetrics, s.EphemeralStorage, currentTime)
addNetworkMetrics(a.mbs.PodMetricsBuilder, metadata.PodNetworkMetrics, s.Network, currentTime)

Expand Down Expand Up @@ -155,10 +155,11 @@ func (a *metricDataAccumulator) containerStats(sPod stats.PodStats, s stats.Cont
return
}

resourceKey := sPod.PodRef.UID + s.Name
currentTime := pcommon.NewTimestampFromTime(a.time)
addUptimeMetric(a.mbs.ContainerMetricsBuilder, metadata.ContainerUptimeMetrics.Uptime, s.StartTime, currentTime)
addCPUMetrics(a.mbs.ContainerMetricsBuilder, metadata.ContainerCPUMetrics, s.CPU, currentTime)
addMemoryMetrics(a.mbs.ContainerMetricsBuilder, metadata.ContainerMemoryMetrics, s.Memory, currentTime)
addCPUMetrics(a.mbs.ContainerMetricsBuilder, metadata.ContainerCPUMetrics, s.CPU, currentTime, a.metadata.containerResources[resourceKey])
addMemoryMetrics(a.mbs.ContainerMetricsBuilder, metadata.ContainerMemoryMetrics, s.Memory, currentTime, a.metadata.containerResources[resourceKey])
addFilesystemMetrics(a.mbs.ContainerMetricsBuilder, metadata.ContainerFilesystemMetrics, s.Rootfs, currentTime)

a.m = append(a.m, a.mbs.ContainerMetricsBuilder.Emit(
Expand Down
15 changes: 11 additions & 4 deletions receiver/kubeletstatsreceiver/internal/kubelet/cpu.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,27 @@ import (
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/kubeletstatsreceiver/internal/metadata"
)

func addCPUMetrics(mb *metadata.MetricsBuilder, cpuMetrics metadata.CPUMetrics, s *stats.CPUStats, currentTime pcommon.Timestamp) {
func addCPUMetrics(mb *metadata.MetricsBuilder, cpuMetrics metadata.CPUMetrics, s *stats.CPUStats, currentTime pcommon.Timestamp, r resources) {
if s == nil {
return
}
addCPUUsageMetric(mb, cpuMetrics.Utilization, s, currentTime)
addCPUUsageMetric(mb, cpuMetrics, s, currentTime, r)
addCPUTimeMetric(mb, cpuMetrics.Time, s, currentTime)
}

func addCPUUsageMetric(mb *metadata.MetricsBuilder, recordDataPoint metadata.RecordDoubleDataPointFunc, s *stats.CPUStats, currentTime pcommon.Timestamp) {
func addCPUUsageMetric(mb *metadata.MetricsBuilder, cpuMetrics metadata.CPUMetrics, s *stats.CPUStats, currentTime pcommon.Timestamp, r resources) {
if s.UsageNanoCores == nil {
return
}
value := float64(*s.UsageNanoCores) / 1_000_000_000
recordDataPoint(mb, currentTime, value)
cpuMetrics.Utilization(mb, currentTime, value)

if r.cpuLimit > 0 {
cpuMetrics.LimitUtilization(mb, currentTime, value/r.cpuLimit)
}
if r.cpuRequest > 0 {
cpuMetrics.RequestUtilization(mb, currentTime, value/r.cpuRequest)
}
}

func addCPUTimeMetric(mb *metadata.MetricsBuilder, recordDataPoint metadata.RecordDoubleDataPointFunc, s *stats.CPUStats, currentTime pcommon.Timestamp) {
Expand Down
11 changes: 10 additions & 1 deletion receiver/kubeletstatsreceiver/internal/kubelet/mem.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/kubeletstatsreceiver/internal/metadata"
)

func addMemoryMetrics(mb *metadata.MetricsBuilder, memoryMetrics metadata.MemoryMetrics, s *stats.MemoryStats, currentTime pcommon.Timestamp) {
func addMemoryMetrics(mb *metadata.MetricsBuilder, memoryMetrics metadata.MemoryMetrics, s *stats.MemoryStats, currentTime pcommon.Timestamp, r resources) {
if s == nil {
return
}
Expand All @@ -21,4 +21,13 @@ func addMemoryMetrics(mb *metadata.MetricsBuilder, memoryMetrics metadata.Memory
recordIntDataPoint(mb, memoryMetrics.WorkingSet, s.WorkingSetBytes, currentTime)
recordIntDataPoint(mb, memoryMetrics.PageFaults, s.PageFaults, currentTime)
recordIntDataPoint(mb, memoryMetrics.MajorPageFaults, s.MajorPageFaults, currentTime)

if s.UsageBytes != nil {
if r.memoryLimit > 0 {
memoryMetrics.LimitUtilization(mb, currentTime, float64(*s.UsageBytes)/float64(r.memoryLimit))
}
if r.memoryRequest > 0 {
memoryMetrics.RequestUtilization(mb, currentTime, float64(*s.UsageBytes)/float64(r.memoryRequest))
}
}
}
74 changes: 73 additions & 1 deletion receiver/kubeletstatsreceiver/internal/kubelet/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,88 @@ type Metadata struct {
PodsMetadata *v1.PodList
NodesMetadata *v1.NodeList
DetailedPVCResourceSetter func(rb *metadata.ResourceBuilder, volCacheID, volumeClaim, namespace string) ([]metadata.ResourceMetricsOption, error)
podResources map[string]resources
containerResources map[string]resources
}

type resources struct {
cpuRequest float64
cpuLimit float64
memoryRequest int64
memoryLimit int64
}

func getContainerResources(r *v1.ResourceRequirements) resources {
if r == nil {
return resources{}
}

return resources{
cpuRequest: r.Requests.Cpu().AsApproximateFloat64(),
cpuLimit: r.Limits.Cpu().AsApproximateFloat64(),
memoryRequest: r.Requests.Memory().Value(),
memoryLimit: r.Limits.Memory().Value(),
}
}

func NewMetadata(labels []MetadataLabel, podsMetadata *v1.PodList, nodesMetadata *v1.NodeList,
detailedPVCResourceSetter func(rb *metadata.ResourceBuilder, volCacheID, volumeClaim, namespace string) ([]metadata.ResourceMetricsOption, error)) Metadata {
return Metadata{
m := Metadata{
Labels: getLabelsMap(labels),
PodsMetadata: podsMetadata,
NodesMetadata: nodesMetadata,
DetailedPVCResourceSetter: detailedPVCResourceSetter,
podResources: make(map[string]resources, 0),
containerResources: make(map[string]resources, 0),
}

if podsMetadata != nil {
for _, pod := range podsMetadata.Items {
var podResource resources
allContainersCPULimitsDefined := true
allContainersCPURequestsDefined := true
allContainersMemoryLimitsDefined := true
allContainersMemoryRequestsDefined := true
for _, container := range pod.Spec.Containers {
containerResource := getContainerResources(&container.Resources)

if allContainersCPULimitsDefined && containerResource.cpuLimit == 0 {
allContainersCPULimitsDefined = false
podResource.cpuLimit = 0
}
if allContainersCPURequestsDefined && containerResource.cpuRequest == 0 {
allContainersCPURequestsDefined = false
podResource.cpuRequest = 0
}
if allContainersMemoryLimitsDefined && containerResource.memoryLimit == 0 {
allContainersMemoryLimitsDefined = false
podResource.memoryLimit = 0
}
if allContainersMemoryRequestsDefined && containerResource.memoryRequest == 0 {
allContainersMemoryRequestsDefined = false
podResource.memoryRequest = 0
}

if allContainersCPULimitsDefined {
podResource.cpuLimit += containerResource.cpuLimit
}
if allContainersCPURequestsDefined {
podResource.cpuRequest += containerResource.cpuRequest
}
if allContainersMemoryLimitsDefined {
podResource.memoryLimit += containerResource.memoryLimit
}
if allContainersMemoryRequestsDefined {
podResource.memoryRequest += containerResource.memoryRequest
}

m.containerResources[string(pod.UID)+container.Name] = containerResource
}
m.podResources[string(pod.UID)] = podResource
}
}

return m
}

func getLabelsMap(metadataLabels []MetadataLabel) map[MetadataLabel]bool {
Expand Down
Loading

0 comments on commit d9e87fd

Please sign in to comment.