From d9e87fd037e58c833a34a691f436f6f52966f995 Mon Sep 17 00:00:00 2001 From: Keval Bhogayata <90185475+bhogayatakb@users.noreply.github.com> Date: Sat, 6 Jan 2024 22:32:17 +0530 Subject: [PATCH] limitrequest metrics added : for pod + container (#40) --- .../kubeletstatsreceiver/documentation.md | 64 ++ .../internal/kubelet/accumulator.go | 13 +- .../internal/kubelet/cpu.go | 15 +- .../internal/kubelet/mem.go | 11 +- .../internal/kubelet/metadata.go | 74 +- .../internal/metadata/generated_config.go | 136 ++-- .../metadata/generated_config_test.go | 196 +++--- .../internal/metadata/generated_metrics.go | 654 +++++++++++++++--- .../metadata/generated_metrics_test.go | 121 ++++ .../internal/metadata/generated_status.go | 10 + .../internal/metadata/metrics.go | 60 +- .../internal/metadata/testdata/config.yaml | 32 + receiver/kubeletstatsreceiver/metadata.yaml | 56 ++ receiver/kubeletstatsreceiver/scraper.go | 11 +- 14 files changed, 1182 insertions(+), 271 deletions(-) diff --git a/receiver/kubeletstatsreceiver/documentation.md b/receiver/kubeletstatsreceiver/documentation.md index d8568719bf44..839276a2b877 100644 --- a/receiver/kubeletstatsreceiver/documentation.md +++ b/receiver/kubeletstatsreceiver/documentation.md @@ -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 @@ -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 diff --git a/receiver/kubeletstatsreceiver/internal/kubelet/accumulator.go b/receiver/kubeletstatsreceiver/internal/kubelet/accumulator.go index efb6acb122d2..0437beec029f 100644 --- a/receiver/kubeletstatsreceiver/internal/kubelet/accumulator.go +++ b/receiver/kubeletstatsreceiver/internal/kubelet/accumulator.go @@ -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 @@ -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) @@ -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( diff --git a/receiver/kubeletstatsreceiver/internal/kubelet/cpu.go b/receiver/kubeletstatsreceiver/internal/kubelet/cpu.go index ad5d617efa21..00ec2e00451f 100644 --- a/receiver/kubeletstatsreceiver/internal/kubelet/cpu.go +++ b/receiver/kubeletstatsreceiver/internal/kubelet/cpu.go @@ -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) { diff --git a/receiver/kubeletstatsreceiver/internal/kubelet/mem.go b/receiver/kubeletstatsreceiver/internal/kubelet/mem.go index 977f21b8bb8f..85713e5234c0 100644 --- a/receiver/kubeletstatsreceiver/internal/kubelet/mem.go +++ b/receiver/kubeletstatsreceiver/internal/kubelet/mem.go @@ -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 } @@ -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)) + } + } } diff --git a/receiver/kubeletstatsreceiver/internal/kubelet/metadata.go b/receiver/kubeletstatsreceiver/internal/kubelet/metadata.go index 8aa9296b1f4d..b159d9e381db 100644 --- a/receiver/kubeletstatsreceiver/internal/kubelet/metadata.go +++ b/receiver/kubeletstatsreceiver/internal/kubelet/metadata.go @@ -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 { diff --git a/receiver/kubeletstatsreceiver/internal/metadata/generated_config.go b/receiver/kubeletstatsreceiver/internal/metadata/generated_config.go index 8ac4b50ce02a..fc60dd040e76 100644 --- a/receiver/kubeletstatsreceiver/internal/metadata/generated_config.go +++ b/receiver/kubeletstatsreceiver/internal/metadata/generated_config.go @@ -25,51 +25,59 @@ func (ms *MetricConfig) Unmarshal(parser *confmap.Conf) error { // MetricsConfig provides config for kubeletstats metrics. type MetricsConfig struct { - ContainerCPUTime MetricConfig `mapstructure:"container.cpu.time"` - ContainerCPUUtilization MetricConfig `mapstructure:"container.cpu.utilization"` - ContainerFilesystemAvailable MetricConfig `mapstructure:"container.filesystem.available"` - ContainerFilesystemCapacity MetricConfig `mapstructure:"container.filesystem.capacity"` - ContainerFilesystemUsage MetricConfig `mapstructure:"container.filesystem.usage"` - ContainerMemoryAvailable MetricConfig `mapstructure:"container.memory.available"` - ContainerMemoryMajorPageFaults MetricConfig `mapstructure:"container.memory.major_page_faults"` - ContainerMemoryPageFaults MetricConfig `mapstructure:"container.memory.page_faults"` - ContainerMemoryRss MetricConfig `mapstructure:"container.memory.rss"` - ContainerMemoryUsage MetricConfig `mapstructure:"container.memory.usage"` - ContainerMemoryWorkingSet MetricConfig `mapstructure:"container.memory.working_set"` - ContainerUptime MetricConfig `mapstructure:"container.uptime"` - K8sNodeCPUTime MetricConfig `mapstructure:"k8s.node.cpu.time"` - K8sNodeCPUUtilization MetricConfig `mapstructure:"k8s.node.cpu.utilization"` - K8sNodeFilesystemAvailable MetricConfig `mapstructure:"k8s.node.filesystem.available"` - K8sNodeFilesystemCapacity MetricConfig `mapstructure:"k8s.node.filesystem.capacity"` - K8sNodeFilesystemUsage MetricConfig `mapstructure:"k8s.node.filesystem.usage"` - K8sNodeMemoryAvailable MetricConfig `mapstructure:"k8s.node.memory.available"` - K8sNodeMemoryMajorPageFaults MetricConfig `mapstructure:"k8s.node.memory.major_page_faults"` - K8sNodeMemoryPageFaults MetricConfig `mapstructure:"k8s.node.memory.page_faults"` - K8sNodeMemoryRss MetricConfig `mapstructure:"k8s.node.memory.rss"` - K8sNodeMemoryUsage MetricConfig `mapstructure:"k8s.node.memory.usage"` - K8sNodeMemoryWorkingSet MetricConfig `mapstructure:"k8s.node.memory.working_set"` - K8sNodeNetworkErrors MetricConfig `mapstructure:"k8s.node.network.errors"` - K8sNodeNetworkIo MetricConfig `mapstructure:"k8s.node.network.io"` - K8sNodeUptime MetricConfig `mapstructure:"k8s.node.uptime"` - K8sPodCPUTime MetricConfig `mapstructure:"k8s.pod.cpu.time"` - K8sPodCPUUtilization MetricConfig `mapstructure:"k8s.pod.cpu.utilization"` - K8sPodFilesystemAvailable MetricConfig `mapstructure:"k8s.pod.filesystem.available"` - K8sPodFilesystemCapacity MetricConfig `mapstructure:"k8s.pod.filesystem.capacity"` - K8sPodFilesystemUsage MetricConfig `mapstructure:"k8s.pod.filesystem.usage"` - K8sPodMemoryAvailable MetricConfig `mapstructure:"k8s.pod.memory.available"` - K8sPodMemoryMajorPageFaults MetricConfig `mapstructure:"k8s.pod.memory.major_page_faults"` - K8sPodMemoryPageFaults MetricConfig `mapstructure:"k8s.pod.memory.page_faults"` - K8sPodMemoryRss MetricConfig `mapstructure:"k8s.pod.memory.rss"` - K8sPodMemoryUsage MetricConfig `mapstructure:"k8s.pod.memory.usage"` - K8sPodMemoryWorkingSet MetricConfig `mapstructure:"k8s.pod.memory.working_set"` - K8sPodNetworkErrors MetricConfig `mapstructure:"k8s.pod.network.errors"` - K8sPodNetworkIo MetricConfig `mapstructure:"k8s.pod.network.io"` - K8sPodUptime MetricConfig `mapstructure:"k8s.pod.uptime"` - K8sVolumeAvailable MetricConfig `mapstructure:"k8s.volume.available"` - K8sVolumeCapacity MetricConfig `mapstructure:"k8s.volume.capacity"` - K8sVolumeInodes MetricConfig `mapstructure:"k8s.volume.inodes"` - K8sVolumeInodesFree MetricConfig `mapstructure:"k8s.volume.inodes.free"` - K8sVolumeInodesUsed MetricConfig `mapstructure:"k8s.volume.inodes.used"` + ContainerCPUTime MetricConfig `mapstructure:"container.cpu.time"` + ContainerCPUUtilization MetricConfig `mapstructure:"container.cpu.utilization"` + ContainerFilesystemAvailable MetricConfig `mapstructure:"container.filesystem.available"` + ContainerFilesystemCapacity MetricConfig `mapstructure:"container.filesystem.capacity"` + ContainerFilesystemUsage MetricConfig `mapstructure:"container.filesystem.usage"` + ContainerMemoryAvailable MetricConfig `mapstructure:"container.memory.available"` + ContainerMemoryMajorPageFaults MetricConfig `mapstructure:"container.memory.major_page_faults"` + ContainerMemoryPageFaults MetricConfig `mapstructure:"container.memory.page_faults"` + ContainerMemoryRss MetricConfig `mapstructure:"container.memory.rss"` + ContainerMemoryUsage MetricConfig `mapstructure:"container.memory.usage"` + ContainerMemoryWorkingSet MetricConfig `mapstructure:"container.memory.working_set"` + ContainerUptime MetricConfig `mapstructure:"container.uptime"` + K8sContainerCPULimitUtilization MetricConfig `mapstructure:"k8s.container.cpu_limit_utilization"` + K8sContainerCPURequestUtilization MetricConfig `mapstructure:"k8s.container.cpu_request_utilization"` + K8sContainerMemoryLimitUtilization MetricConfig `mapstructure:"k8s.container.memory_limit_utilization"` + K8sContainerMemoryRequestUtilization MetricConfig `mapstructure:"k8s.container.memory_request_utilization"` + K8sNodeCPUTime MetricConfig `mapstructure:"k8s.node.cpu.time"` + K8sNodeCPUUtilization MetricConfig `mapstructure:"k8s.node.cpu.utilization"` + K8sNodeFilesystemAvailable MetricConfig `mapstructure:"k8s.node.filesystem.available"` + K8sNodeFilesystemCapacity MetricConfig `mapstructure:"k8s.node.filesystem.capacity"` + K8sNodeFilesystemUsage MetricConfig `mapstructure:"k8s.node.filesystem.usage"` + K8sNodeMemoryAvailable MetricConfig `mapstructure:"k8s.node.memory.available"` + K8sNodeMemoryMajorPageFaults MetricConfig `mapstructure:"k8s.node.memory.major_page_faults"` + K8sNodeMemoryPageFaults MetricConfig `mapstructure:"k8s.node.memory.page_faults"` + K8sNodeMemoryRss MetricConfig `mapstructure:"k8s.node.memory.rss"` + K8sNodeMemoryUsage MetricConfig `mapstructure:"k8s.node.memory.usage"` + K8sNodeMemoryWorkingSet MetricConfig `mapstructure:"k8s.node.memory.working_set"` + K8sNodeNetworkErrors MetricConfig `mapstructure:"k8s.node.network.errors"` + K8sNodeNetworkIo MetricConfig `mapstructure:"k8s.node.network.io"` + K8sNodeUptime MetricConfig `mapstructure:"k8s.node.uptime"` + K8sPodCPUTime MetricConfig `mapstructure:"k8s.pod.cpu.time"` + K8sPodCPUUtilization MetricConfig `mapstructure:"k8s.pod.cpu.utilization"` + K8sPodCPULimitUtilization MetricConfig `mapstructure:"k8s.pod.cpu_limit_utilization"` + K8sPodCPURequestUtilization MetricConfig `mapstructure:"k8s.pod.cpu_request_utilization"` + K8sPodFilesystemAvailable MetricConfig `mapstructure:"k8s.pod.filesystem.available"` + K8sPodFilesystemCapacity MetricConfig `mapstructure:"k8s.pod.filesystem.capacity"` + K8sPodFilesystemUsage MetricConfig `mapstructure:"k8s.pod.filesystem.usage"` + K8sPodMemoryAvailable MetricConfig `mapstructure:"k8s.pod.memory.available"` + K8sPodMemoryMajorPageFaults MetricConfig `mapstructure:"k8s.pod.memory.major_page_faults"` + K8sPodMemoryPageFaults MetricConfig `mapstructure:"k8s.pod.memory.page_faults"` + K8sPodMemoryRss MetricConfig `mapstructure:"k8s.pod.memory.rss"` + K8sPodMemoryUsage MetricConfig `mapstructure:"k8s.pod.memory.usage"` + K8sPodMemoryWorkingSet MetricConfig `mapstructure:"k8s.pod.memory.working_set"` + K8sPodMemoryLimitUtilization MetricConfig `mapstructure:"k8s.pod.memory_limit_utilization"` + K8sPodMemoryRequestUtilization MetricConfig `mapstructure:"k8s.pod.memory_request_utilization"` + K8sPodNetworkErrors MetricConfig `mapstructure:"k8s.pod.network.errors"` + K8sPodNetworkIo MetricConfig `mapstructure:"k8s.pod.network.io"` + K8sPodUptime MetricConfig `mapstructure:"k8s.pod.uptime"` + K8sVolumeAvailable MetricConfig `mapstructure:"k8s.volume.available"` + K8sVolumeCapacity MetricConfig `mapstructure:"k8s.volume.capacity"` + K8sVolumeInodes MetricConfig `mapstructure:"k8s.volume.inodes"` + K8sVolumeInodesFree MetricConfig `mapstructure:"k8s.volume.inodes.free"` + K8sVolumeInodesUsed MetricConfig `mapstructure:"k8s.volume.inodes.used"` } func DefaultMetricsConfig() MetricsConfig { @@ -110,6 +118,18 @@ func DefaultMetricsConfig() MetricsConfig { ContainerUptime: MetricConfig{ Enabled: false, }, + K8sContainerCPULimitUtilization: MetricConfig{ + Enabled: false, + }, + K8sContainerCPURequestUtilization: MetricConfig{ + Enabled: false, + }, + K8sContainerMemoryLimitUtilization: MetricConfig{ + Enabled: false, + }, + K8sContainerMemoryRequestUtilization: MetricConfig{ + Enabled: false, + }, K8sNodeCPUTime: MetricConfig{ Enabled: true, }, @@ -158,6 +178,12 @@ func DefaultMetricsConfig() MetricsConfig { K8sPodCPUUtilization: MetricConfig{ Enabled: true, }, + K8sPodCPULimitUtilization: MetricConfig{ + Enabled: false, + }, + K8sPodCPURequestUtilization: MetricConfig{ + Enabled: false, + }, K8sPodFilesystemAvailable: MetricConfig{ Enabled: true, }, @@ -185,6 +211,12 @@ func DefaultMetricsConfig() MetricsConfig { K8sPodMemoryWorkingSet: MetricConfig{ Enabled: true, }, + K8sPodMemoryLimitUtilization: MetricConfig{ + Enabled: false, + }, + K8sPodMemoryRequestUtilization: MetricConfig{ + Enabled: false, + }, K8sPodNetworkErrors: MetricConfig{ Enabled: true, }, @@ -215,6 +247,20 @@ func DefaultMetricsConfig() MetricsConfig { // ResourceAttributeConfig provides common config for a particular resource attribute. type ResourceAttributeConfig struct { Enabled bool `mapstructure:"enabled"` + + enabledSetByUser bool +} + +func (rac *ResourceAttributeConfig) Unmarshal(parser *confmap.Conf) error { + if parser == nil { + return nil + } + err := parser.Unmarshal(rac, confmap.WithErrorUnused()) + if err != nil { + return err + } + rac.enabledSetByUser = parser.IsSet("enabled") + return nil } // ResourceAttributesConfig provides config for kubeletstats resource attributes. diff --git a/receiver/kubeletstatsreceiver/internal/metadata/generated_config_test.go b/receiver/kubeletstatsreceiver/internal/metadata/generated_config_test.go index b7d06ab338f4..2581f618e18b 100644 --- a/receiver/kubeletstatsreceiver/internal/metadata/generated_config_test.go +++ b/receiver/kubeletstatsreceiver/internal/metadata/generated_config_test.go @@ -26,51 +26,59 @@ func TestMetricsBuilderConfig(t *testing.T) { name: "all_set", want: MetricsBuilderConfig{ Metrics: MetricsConfig{ - ContainerCPUTime: MetricConfig{Enabled: true}, - ContainerCPUUtilization: MetricConfig{Enabled: true}, - ContainerFilesystemAvailable: MetricConfig{Enabled: true}, - ContainerFilesystemCapacity: MetricConfig{Enabled: true}, - ContainerFilesystemUsage: MetricConfig{Enabled: true}, - ContainerMemoryAvailable: MetricConfig{Enabled: true}, - ContainerMemoryMajorPageFaults: MetricConfig{Enabled: true}, - ContainerMemoryPageFaults: MetricConfig{Enabled: true}, - ContainerMemoryRss: MetricConfig{Enabled: true}, - ContainerMemoryUsage: MetricConfig{Enabled: true}, - ContainerMemoryWorkingSet: MetricConfig{Enabled: true}, - ContainerUptime: MetricConfig{Enabled: true}, - K8sNodeCPUTime: MetricConfig{Enabled: true}, - K8sNodeCPUUtilization: MetricConfig{Enabled: true}, - K8sNodeFilesystemAvailable: MetricConfig{Enabled: true}, - K8sNodeFilesystemCapacity: MetricConfig{Enabled: true}, - K8sNodeFilesystemUsage: MetricConfig{Enabled: true}, - K8sNodeMemoryAvailable: MetricConfig{Enabled: true}, - K8sNodeMemoryMajorPageFaults: MetricConfig{Enabled: true}, - K8sNodeMemoryPageFaults: MetricConfig{Enabled: true}, - K8sNodeMemoryRss: MetricConfig{Enabled: true}, - K8sNodeMemoryUsage: MetricConfig{Enabled: true}, - K8sNodeMemoryWorkingSet: MetricConfig{Enabled: true}, - K8sNodeNetworkErrors: MetricConfig{Enabled: true}, - K8sNodeNetworkIo: MetricConfig{Enabled: true}, - K8sNodeUptime: MetricConfig{Enabled: true}, - K8sPodCPUTime: MetricConfig{Enabled: true}, - K8sPodCPUUtilization: MetricConfig{Enabled: true}, - K8sPodFilesystemAvailable: MetricConfig{Enabled: true}, - K8sPodFilesystemCapacity: MetricConfig{Enabled: true}, - K8sPodFilesystemUsage: MetricConfig{Enabled: true}, - K8sPodMemoryAvailable: MetricConfig{Enabled: true}, - K8sPodMemoryMajorPageFaults: MetricConfig{Enabled: true}, - K8sPodMemoryPageFaults: MetricConfig{Enabled: true}, - K8sPodMemoryRss: MetricConfig{Enabled: true}, - K8sPodMemoryUsage: MetricConfig{Enabled: true}, - K8sPodMemoryWorkingSet: MetricConfig{Enabled: true}, - K8sPodNetworkErrors: MetricConfig{Enabled: true}, - K8sPodNetworkIo: MetricConfig{Enabled: true}, - K8sPodUptime: MetricConfig{Enabled: true}, - K8sVolumeAvailable: MetricConfig{Enabled: true}, - K8sVolumeCapacity: MetricConfig{Enabled: true}, - K8sVolumeInodes: MetricConfig{Enabled: true}, - K8sVolumeInodesFree: MetricConfig{Enabled: true}, - K8sVolumeInodesUsed: MetricConfig{Enabled: true}, + ContainerCPUTime: MetricConfig{Enabled: true}, + ContainerCPUUtilization: MetricConfig{Enabled: true}, + ContainerFilesystemAvailable: MetricConfig{Enabled: true}, + ContainerFilesystemCapacity: MetricConfig{Enabled: true}, + ContainerFilesystemUsage: MetricConfig{Enabled: true}, + ContainerMemoryAvailable: MetricConfig{Enabled: true}, + ContainerMemoryMajorPageFaults: MetricConfig{Enabled: true}, + ContainerMemoryPageFaults: MetricConfig{Enabled: true}, + ContainerMemoryRss: MetricConfig{Enabled: true}, + ContainerMemoryUsage: MetricConfig{Enabled: true}, + ContainerMemoryWorkingSet: MetricConfig{Enabled: true}, + ContainerUptime: MetricConfig{Enabled: true}, + K8sContainerCPULimitUtilization: MetricConfig{Enabled: true}, + K8sContainerCPURequestUtilization: MetricConfig{Enabled: true}, + K8sContainerMemoryLimitUtilization: MetricConfig{Enabled: true}, + K8sContainerMemoryRequestUtilization: MetricConfig{Enabled: true}, + K8sNodeCPUTime: MetricConfig{Enabled: true}, + K8sNodeCPUUtilization: MetricConfig{Enabled: true}, + K8sNodeFilesystemAvailable: MetricConfig{Enabled: true}, + K8sNodeFilesystemCapacity: MetricConfig{Enabled: true}, + K8sNodeFilesystemUsage: MetricConfig{Enabled: true}, + K8sNodeMemoryAvailable: MetricConfig{Enabled: true}, + K8sNodeMemoryMajorPageFaults: MetricConfig{Enabled: true}, + K8sNodeMemoryPageFaults: MetricConfig{Enabled: true}, + K8sNodeMemoryRss: MetricConfig{Enabled: true}, + K8sNodeMemoryUsage: MetricConfig{Enabled: true}, + K8sNodeMemoryWorkingSet: MetricConfig{Enabled: true}, + K8sNodeNetworkErrors: MetricConfig{Enabled: true}, + K8sNodeNetworkIo: MetricConfig{Enabled: true}, + K8sNodeUptime: MetricConfig{Enabled: true}, + K8sPodCPUTime: MetricConfig{Enabled: true}, + K8sPodCPUUtilization: MetricConfig{Enabled: true}, + K8sPodCPULimitUtilization: MetricConfig{Enabled: true}, + K8sPodCPURequestUtilization: MetricConfig{Enabled: true}, + K8sPodFilesystemAvailable: MetricConfig{Enabled: true}, + K8sPodFilesystemCapacity: MetricConfig{Enabled: true}, + K8sPodFilesystemUsage: MetricConfig{Enabled: true}, + K8sPodMemoryAvailable: MetricConfig{Enabled: true}, + K8sPodMemoryMajorPageFaults: MetricConfig{Enabled: true}, + K8sPodMemoryPageFaults: MetricConfig{Enabled: true}, + K8sPodMemoryRss: MetricConfig{Enabled: true}, + K8sPodMemoryUsage: MetricConfig{Enabled: true}, + K8sPodMemoryWorkingSet: MetricConfig{Enabled: true}, + K8sPodMemoryLimitUtilization: MetricConfig{Enabled: true}, + K8sPodMemoryRequestUtilization: MetricConfig{Enabled: true}, + K8sPodNetworkErrors: MetricConfig{Enabled: true}, + K8sPodNetworkIo: MetricConfig{Enabled: true}, + K8sPodUptime: MetricConfig{Enabled: true}, + K8sVolumeAvailable: MetricConfig{Enabled: true}, + K8sVolumeCapacity: MetricConfig{Enabled: true}, + K8sVolumeInodes: MetricConfig{Enabled: true}, + K8sVolumeInodesFree: MetricConfig{Enabled: true}, + K8sVolumeInodesUsed: MetricConfig{Enabled: true}, }, ResourceAttributes: ResourceAttributesConfig{ AwsVolumeID: ResourceAttributeConfig{Enabled: true}, @@ -100,51 +108,59 @@ func TestMetricsBuilderConfig(t *testing.T) { name: "none_set", want: MetricsBuilderConfig{ Metrics: MetricsConfig{ - ContainerCPUTime: MetricConfig{Enabled: false}, - ContainerCPUUtilization: MetricConfig{Enabled: false}, - ContainerFilesystemAvailable: MetricConfig{Enabled: false}, - ContainerFilesystemCapacity: MetricConfig{Enabled: false}, - ContainerFilesystemUsage: MetricConfig{Enabled: false}, - ContainerMemoryAvailable: MetricConfig{Enabled: false}, - ContainerMemoryMajorPageFaults: MetricConfig{Enabled: false}, - ContainerMemoryPageFaults: MetricConfig{Enabled: false}, - ContainerMemoryRss: MetricConfig{Enabled: false}, - ContainerMemoryUsage: MetricConfig{Enabled: false}, - ContainerMemoryWorkingSet: MetricConfig{Enabled: false}, - ContainerUptime: MetricConfig{Enabled: false}, - K8sNodeCPUTime: MetricConfig{Enabled: false}, - K8sNodeCPUUtilization: MetricConfig{Enabled: false}, - K8sNodeFilesystemAvailable: MetricConfig{Enabled: false}, - K8sNodeFilesystemCapacity: MetricConfig{Enabled: false}, - K8sNodeFilesystemUsage: MetricConfig{Enabled: false}, - K8sNodeMemoryAvailable: MetricConfig{Enabled: false}, - K8sNodeMemoryMajorPageFaults: MetricConfig{Enabled: false}, - K8sNodeMemoryPageFaults: MetricConfig{Enabled: false}, - K8sNodeMemoryRss: MetricConfig{Enabled: false}, - K8sNodeMemoryUsage: MetricConfig{Enabled: false}, - K8sNodeMemoryWorkingSet: MetricConfig{Enabled: false}, - K8sNodeNetworkErrors: MetricConfig{Enabled: false}, - K8sNodeNetworkIo: MetricConfig{Enabled: false}, - K8sNodeUptime: MetricConfig{Enabled: false}, - K8sPodCPUTime: MetricConfig{Enabled: false}, - K8sPodCPUUtilization: MetricConfig{Enabled: false}, - K8sPodFilesystemAvailable: MetricConfig{Enabled: false}, - K8sPodFilesystemCapacity: MetricConfig{Enabled: false}, - K8sPodFilesystemUsage: MetricConfig{Enabled: false}, - K8sPodMemoryAvailable: MetricConfig{Enabled: false}, - K8sPodMemoryMajorPageFaults: MetricConfig{Enabled: false}, - K8sPodMemoryPageFaults: MetricConfig{Enabled: false}, - K8sPodMemoryRss: MetricConfig{Enabled: false}, - K8sPodMemoryUsage: MetricConfig{Enabled: false}, - K8sPodMemoryWorkingSet: MetricConfig{Enabled: false}, - K8sPodNetworkErrors: MetricConfig{Enabled: false}, - K8sPodNetworkIo: MetricConfig{Enabled: false}, - K8sPodUptime: MetricConfig{Enabled: false}, - K8sVolumeAvailable: MetricConfig{Enabled: false}, - K8sVolumeCapacity: MetricConfig{Enabled: false}, - K8sVolumeInodes: MetricConfig{Enabled: false}, - K8sVolumeInodesFree: MetricConfig{Enabled: false}, - K8sVolumeInodesUsed: MetricConfig{Enabled: false}, + ContainerCPUTime: MetricConfig{Enabled: false}, + ContainerCPUUtilization: MetricConfig{Enabled: false}, + ContainerFilesystemAvailable: MetricConfig{Enabled: false}, + ContainerFilesystemCapacity: MetricConfig{Enabled: false}, + ContainerFilesystemUsage: MetricConfig{Enabled: false}, + ContainerMemoryAvailable: MetricConfig{Enabled: false}, + ContainerMemoryMajorPageFaults: MetricConfig{Enabled: false}, + ContainerMemoryPageFaults: MetricConfig{Enabled: false}, + ContainerMemoryRss: MetricConfig{Enabled: false}, + ContainerMemoryUsage: MetricConfig{Enabled: false}, + ContainerMemoryWorkingSet: MetricConfig{Enabled: false}, + ContainerUptime: MetricConfig{Enabled: false}, + K8sContainerCPULimitUtilization: MetricConfig{Enabled: false}, + K8sContainerCPURequestUtilization: MetricConfig{Enabled: false}, + K8sContainerMemoryLimitUtilization: MetricConfig{Enabled: false}, + K8sContainerMemoryRequestUtilization: MetricConfig{Enabled: false}, + K8sNodeCPUTime: MetricConfig{Enabled: false}, + K8sNodeCPUUtilization: MetricConfig{Enabled: false}, + K8sNodeFilesystemAvailable: MetricConfig{Enabled: false}, + K8sNodeFilesystemCapacity: MetricConfig{Enabled: false}, + K8sNodeFilesystemUsage: MetricConfig{Enabled: false}, + K8sNodeMemoryAvailable: MetricConfig{Enabled: false}, + K8sNodeMemoryMajorPageFaults: MetricConfig{Enabled: false}, + K8sNodeMemoryPageFaults: MetricConfig{Enabled: false}, + K8sNodeMemoryRss: MetricConfig{Enabled: false}, + K8sNodeMemoryUsage: MetricConfig{Enabled: false}, + K8sNodeMemoryWorkingSet: MetricConfig{Enabled: false}, + K8sNodeNetworkErrors: MetricConfig{Enabled: false}, + K8sNodeNetworkIo: MetricConfig{Enabled: false}, + K8sNodeUptime: MetricConfig{Enabled: false}, + K8sPodCPUTime: MetricConfig{Enabled: false}, + K8sPodCPUUtilization: MetricConfig{Enabled: false}, + K8sPodCPULimitUtilization: MetricConfig{Enabled: false}, + K8sPodCPURequestUtilization: MetricConfig{Enabled: false}, + K8sPodFilesystemAvailable: MetricConfig{Enabled: false}, + K8sPodFilesystemCapacity: MetricConfig{Enabled: false}, + K8sPodFilesystemUsage: MetricConfig{Enabled: false}, + K8sPodMemoryAvailable: MetricConfig{Enabled: false}, + K8sPodMemoryMajorPageFaults: MetricConfig{Enabled: false}, + K8sPodMemoryPageFaults: MetricConfig{Enabled: false}, + K8sPodMemoryRss: MetricConfig{Enabled: false}, + K8sPodMemoryUsage: MetricConfig{Enabled: false}, + K8sPodMemoryWorkingSet: MetricConfig{Enabled: false}, + K8sPodMemoryLimitUtilization: MetricConfig{Enabled: false}, + K8sPodMemoryRequestUtilization: MetricConfig{Enabled: false}, + K8sPodNetworkErrors: MetricConfig{Enabled: false}, + K8sPodNetworkIo: MetricConfig{Enabled: false}, + K8sPodUptime: MetricConfig{Enabled: false}, + K8sVolumeAvailable: MetricConfig{Enabled: false}, + K8sVolumeCapacity: MetricConfig{Enabled: false}, + K8sVolumeInodes: MetricConfig{Enabled: false}, + K8sVolumeInodesFree: MetricConfig{Enabled: false}, + K8sVolumeInodesUsed: MetricConfig{Enabled: false}, }, ResourceAttributes: ResourceAttributesConfig{ AwsVolumeID: ResourceAttributeConfig{Enabled: false}, diff --git a/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics.go b/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics.go index 1c5511b47c62..03f94dc800bf 100644 --- a/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics.go +++ b/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics.go @@ -629,6 +629,202 @@ func newMetricContainerUptime(cfg MetricConfig) metricContainerUptime { return m } +type metricK8sContainerCPULimitUtilization struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills k8s.container.cpu_limit_utilization metric with initial data. +func (m *metricK8sContainerCPULimitUtilization) init() { + m.data.SetName("k8s.container.cpu_limit_utilization") + m.data.SetDescription("Container cpu utilization as a ratio of the container's limits") + m.data.SetUnit("1") + m.data.SetEmptyGauge() +} + +func (m *metricK8sContainerCPULimitUtilization) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64) { + if !m.config.Enabled { + return + } + dp := m.data.Gauge().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetDoubleValue(val) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricK8sContainerCPULimitUtilization) updateCapacity() { + if m.data.Gauge().DataPoints().Len() > m.capacity { + m.capacity = m.data.Gauge().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricK8sContainerCPULimitUtilization) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricK8sContainerCPULimitUtilization(cfg MetricConfig) metricK8sContainerCPULimitUtilization { + m := metricK8sContainerCPULimitUtilization{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +type metricK8sContainerCPURequestUtilization struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills k8s.container.cpu_request_utilization metric with initial data. +func (m *metricK8sContainerCPURequestUtilization) init() { + m.data.SetName("k8s.container.cpu_request_utilization") + m.data.SetDescription("Container cpu utilization as a ratio of the container's requests") + m.data.SetUnit("1") + m.data.SetEmptyGauge() +} + +func (m *metricK8sContainerCPURequestUtilization) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64) { + if !m.config.Enabled { + return + } + dp := m.data.Gauge().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetDoubleValue(val) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricK8sContainerCPURequestUtilization) updateCapacity() { + if m.data.Gauge().DataPoints().Len() > m.capacity { + m.capacity = m.data.Gauge().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricK8sContainerCPURequestUtilization) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricK8sContainerCPURequestUtilization(cfg MetricConfig) metricK8sContainerCPURequestUtilization { + m := metricK8sContainerCPURequestUtilization{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +type metricK8sContainerMemoryLimitUtilization struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills k8s.container.memory_limit_utilization metric with initial data. +func (m *metricK8sContainerMemoryLimitUtilization) init() { + m.data.SetName("k8s.container.memory_limit_utilization") + m.data.SetDescription("Container memory utilization as a ratio of the container's limits") + m.data.SetUnit("1") + m.data.SetEmptyGauge() +} + +func (m *metricK8sContainerMemoryLimitUtilization) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64) { + if !m.config.Enabled { + return + } + dp := m.data.Gauge().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetDoubleValue(val) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricK8sContainerMemoryLimitUtilization) updateCapacity() { + if m.data.Gauge().DataPoints().Len() > m.capacity { + m.capacity = m.data.Gauge().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricK8sContainerMemoryLimitUtilization) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricK8sContainerMemoryLimitUtilization(cfg MetricConfig) metricK8sContainerMemoryLimitUtilization { + m := metricK8sContainerMemoryLimitUtilization{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +type metricK8sContainerMemoryRequestUtilization struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills k8s.container.memory_request_utilization metric with initial data. +func (m *metricK8sContainerMemoryRequestUtilization) init() { + m.data.SetName("k8s.container.memory_request_utilization") + m.data.SetDescription("Container memory utilization as a ratio of the container's requests") + m.data.SetUnit("1") + m.data.SetEmptyGauge() +} + +func (m *metricK8sContainerMemoryRequestUtilization) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64) { + if !m.config.Enabled { + return + } + dp := m.data.Gauge().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetDoubleValue(val) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricK8sContainerMemoryRequestUtilization) updateCapacity() { + if m.data.Gauge().DataPoints().Len() > m.capacity { + m.capacity = m.data.Gauge().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricK8sContainerMemoryRequestUtilization) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricK8sContainerMemoryRequestUtilization(cfg MetricConfig) metricK8sContainerMemoryRequestUtilization { + m := metricK8sContainerMemoryRequestUtilization{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + type metricK8sNodeCPUTime struct { data pmetric.Metric // data buffer for generated metric. config MetricConfig // metric config provided by user. @@ -1429,6 +1625,104 @@ func newMetricK8sPodCPUUtilization(cfg MetricConfig) metricK8sPodCPUUtilization return m } +type metricK8sPodCPULimitUtilization struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills k8s.pod.cpu_limit_utilization metric with initial data. +func (m *metricK8sPodCPULimitUtilization) init() { + m.data.SetName("k8s.pod.cpu_limit_utilization") + m.data.SetDescription("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.") + m.data.SetUnit("1") + m.data.SetEmptyGauge() +} + +func (m *metricK8sPodCPULimitUtilization) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64) { + if !m.config.Enabled { + return + } + dp := m.data.Gauge().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetDoubleValue(val) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricK8sPodCPULimitUtilization) updateCapacity() { + if m.data.Gauge().DataPoints().Len() > m.capacity { + m.capacity = m.data.Gauge().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricK8sPodCPULimitUtilization) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricK8sPodCPULimitUtilization(cfg MetricConfig) metricK8sPodCPULimitUtilization { + m := metricK8sPodCPULimitUtilization{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +type metricK8sPodCPURequestUtilization struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills k8s.pod.cpu_request_utilization metric with initial data. +func (m *metricK8sPodCPURequestUtilization) init() { + m.data.SetName("k8s.pod.cpu_request_utilization") + m.data.SetDescription("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.") + m.data.SetUnit("1") + m.data.SetEmptyGauge() +} + +func (m *metricK8sPodCPURequestUtilization) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64) { + if !m.config.Enabled { + return + } + dp := m.data.Gauge().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetDoubleValue(val) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricK8sPodCPURequestUtilization) updateCapacity() { + if m.data.Gauge().DataPoints().Len() > m.capacity { + m.capacity = m.data.Gauge().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricK8sPodCPURequestUtilization) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricK8sPodCPURequestUtilization(cfg MetricConfig) metricK8sPodCPURequestUtilization { + m := metricK8sPodCPURequestUtilization{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + type metricK8sPodFilesystemAvailable struct { data pmetric.Metric // data buffer for generated metric. config MetricConfig // metric config provided by user. @@ -1870,6 +2164,104 @@ func newMetricK8sPodMemoryWorkingSet(cfg MetricConfig) metricK8sPodMemoryWorking return m } +type metricK8sPodMemoryLimitUtilization struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills k8s.pod.memory_limit_utilization metric with initial data. +func (m *metricK8sPodMemoryLimitUtilization) init() { + m.data.SetName("k8s.pod.memory_limit_utilization") + m.data.SetDescription("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.") + m.data.SetUnit("1") + m.data.SetEmptyGauge() +} + +func (m *metricK8sPodMemoryLimitUtilization) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64) { + if !m.config.Enabled { + return + } + dp := m.data.Gauge().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetDoubleValue(val) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricK8sPodMemoryLimitUtilization) updateCapacity() { + if m.data.Gauge().DataPoints().Len() > m.capacity { + m.capacity = m.data.Gauge().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricK8sPodMemoryLimitUtilization) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricK8sPodMemoryLimitUtilization(cfg MetricConfig) metricK8sPodMemoryLimitUtilization { + m := metricK8sPodMemoryLimitUtilization{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +type metricK8sPodMemoryRequestUtilization struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills k8s.pod.memory_request_utilization metric with initial data. +func (m *metricK8sPodMemoryRequestUtilization) init() { + m.data.SetName("k8s.pod.memory_request_utilization") + m.data.SetDescription("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.") + m.data.SetUnit("1") + m.data.SetEmptyGauge() +} + +func (m *metricK8sPodMemoryRequestUtilization) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64) { + if !m.config.Enabled { + return + } + dp := m.data.Gauge().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetDoubleValue(val) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricK8sPodMemoryRequestUtilization) updateCapacity() { + if m.data.Gauge().DataPoints().Len() > m.capacity { + m.capacity = m.data.Gauge().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricK8sPodMemoryRequestUtilization) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricK8sPodMemoryRequestUtilization(cfg MetricConfig) metricK8sPodMemoryRequestUtilization { + m := metricK8sPodMemoryRequestUtilization{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + type metricK8sPodNetworkErrors struct { data pmetric.Metric // data buffer for generated metric. config MetricConfig // metric config provided by user. @@ -2277,56 +2669,64 @@ func newMetricK8sVolumeInodesUsed(cfg MetricConfig) metricK8sVolumeInodesUsed { // MetricsBuilder provides an interface for scrapers to report metrics while taking care of all the transformations // required to produce metric representation defined in metadata and user config. type MetricsBuilder struct { - config MetricsBuilderConfig // config of the metrics builder. - startTime pcommon.Timestamp // start time that will be applied to all recorded data points. - metricsCapacity int // maximum observed number of metrics per resource. - metricsBuffer pmetric.Metrics // accumulates metrics data before emitting. - buildInfo component.BuildInfo // contains version information. - metricContainerCPUTime metricContainerCPUTime - metricContainerCPUUtilization metricContainerCPUUtilization - metricContainerFilesystemAvailable metricContainerFilesystemAvailable - metricContainerFilesystemCapacity metricContainerFilesystemCapacity - metricContainerFilesystemUsage metricContainerFilesystemUsage - metricContainerMemoryAvailable metricContainerMemoryAvailable - metricContainerMemoryMajorPageFaults metricContainerMemoryMajorPageFaults - metricContainerMemoryPageFaults metricContainerMemoryPageFaults - metricContainerMemoryRss metricContainerMemoryRss - metricContainerMemoryUsage metricContainerMemoryUsage - metricContainerMemoryWorkingSet metricContainerMemoryWorkingSet - metricContainerUptime metricContainerUptime - metricK8sNodeCPUTime metricK8sNodeCPUTime - metricK8sNodeCPUUtilization metricK8sNodeCPUUtilization - metricK8sNodeFilesystemAvailable metricK8sNodeFilesystemAvailable - metricK8sNodeFilesystemCapacity metricK8sNodeFilesystemCapacity - metricK8sNodeFilesystemUsage metricK8sNodeFilesystemUsage - metricK8sNodeMemoryAvailable metricK8sNodeMemoryAvailable - metricK8sNodeMemoryMajorPageFaults metricK8sNodeMemoryMajorPageFaults - metricK8sNodeMemoryPageFaults metricK8sNodeMemoryPageFaults - metricK8sNodeMemoryRss metricK8sNodeMemoryRss - metricK8sNodeMemoryUsage metricK8sNodeMemoryUsage - metricK8sNodeMemoryWorkingSet metricK8sNodeMemoryWorkingSet - metricK8sNodeNetworkErrors metricK8sNodeNetworkErrors - metricK8sNodeNetworkIo metricK8sNodeNetworkIo - metricK8sNodeUptime metricK8sNodeUptime - metricK8sPodCPUTime metricK8sPodCPUTime - metricK8sPodCPUUtilization metricK8sPodCPUUtilization - metricK8sPodFilesystemAvailable metricK8sPodFilesystemAvailable - metricK8sPodFilesystemCapacity metricK8sPodFilesystemCapacity - metricK8sPodFilesystemUsage metricK8sPodFilesystemUsage - metricK8sPodMemoryAvailable metricK8sPodMemoryAvailable - metricK8sPodMemoryMajorPageFaults metricK8sPodMemoryMajorPageFaults - metricK8sPodMemoryPageFaults metricK8sPodMemoryPageFaults - metricK8sPodMemoryRss metricK8sPodMemoryRss - metricK8sPodMemoryUsage metricK8sPodMemoryUsage - metricK8sPodMemoryWorkingSet metricK8sPodMemoryWorkingSet - metricK8sPodNetworkErrors metricK8sPodNetworkErrors - metricK8sPodNetworkIo metricK8sPodNetworkIo - metricK8sPodUptime metricK8sPodUptime - metricK8sVolumeAvailable metricK8sVolumeAvailable - metricK8sVolumeCapacity metricK8sVolumeCapacity - metricK8sVolumeInodes metricK8sVolumeInodes - metricK8sVolumeInodesFree metricK8sVolumeInodesFree - metricK8sVolumeInodesUsed metricK8sVolumeInodesUsed + config MetricsBuilderConfig // config of the metrics builder. + startTime pcommon.Timestamp // start time that will be applied to all recorded data points. + metricsCapacity int // maximum observed number of metrics per resource. + metricsBuffer pmetric.Metrics // accumulates metrics data before emitting. + buildInfo component.BuildInfo // contains version information. + metricContainerCPUTime metricContainerCPUTime + metricContainerCPUUtilization metricContainerCPUUtilization + metricContainerFilesystemAvailable metricContainerFilesystemAvailable + metricContainerFilesystemCapacity metricContainerFilesystemCapacity + metricContainerFilesystemUsage metricContainerFilesystemUsage + metricContainerMemoryAvailable metricContainerMemoryAvailable + metricContainerMemoryMajorPageFaults metricContainerMemoryMajorPageFaults + metricContainerMemoryPageFaults metricContainerMemoryPageFaults + metricContainerMemoryRss metricContainerMemoryRss + metricContainerMemoryUsage metricContainerMemoryUsage + metricContainerMemoryWorkingSet metricContainerMemoryWorkingSet + metricContainerUptime metricContainerUptime + metricK8sContainerCPULimitUtilization metricK8sContainerCPULimitUtilization + metricK8sContainerCPURequestUtilization metricK8sContainerCPURequestUtilization + metricK8sContainerMemoryLimitUtilization metricK8sContainerMemoryLimitUtilization + metricK8sContainerMemoryRequestUtilization metricK8sContainerMemoryRequestUtilization + metricK8sNodeCPUTime metricK8sNodeCPUTime + metricK8sNodeCPUUtilization metricK8sNodeCPUUtilization + metricK8sNodeFilesystemAvailable metricK8sNodeFilesystemAvailable + metricK8sNodeFilesystemCapacity metricK8sNodeFilesystemCapacity + metricK8sNodeFilesystemUsage metricK8sNodeFilesystemUsage + metricK8sNodeMemoryAvailable metricK8sNodeMemoryAvailable + metricK8sNodeMemoryMajorPageFaults metricK8sNodeMemoryMajorPageFaults + metricK8sNodeMemoryPageFaults metricK8sNodeMemoryPageFaults + metricK8sNodeMemoryRss metricK8sNodeMemoryRss + metricK8sNodeMemoryUsage metricK8sNodeMemoryUsage + metricK8sNodeMemoryWorkingSet metricK8sNodeMemoryWorkingSet + metricK8sNodeNetworkErrors metricK8sNodeNetworkErrors + metricK8sNodeNetworkIo metricK8sNodeNetworkIo + metricK8sNodeUptime metricK8sNodeUptime + metricK8sPodCPUTime metricK8sPodCPUTime + metricK8sPodCPUUtilization metricK8sPodCPUUtilization + metricK8sPodCPULimitUtilization metricK8sPodCPULimitUtilization + metricK8sPodCPURequestUtilization metricK8sPodCPURequestUtilization + metricK8sPodFilesystemAvailable metricK8sPodFilesystemAvailable + metricK8sPodFilesystemCapacity metricK8sPodFilesystemCapacity + metricK8sPodFilesystemUsage metricK8sPodFilesystemUsage + metricK8sPodMemoryAvailable metricK8sPodMemoryAvailable + metricK8sPodMemoryMajorPageFaults metricK8sPodMemoryMajorPageFaults + metricK8sPodMemoryPageFaults metricK8sPodMemoryPageFaults + metricK8sPodMemoryRss metricK8sPodMemoryRss + metricK8sPodMemoryUsage metricK8sPodMemoryUsage + metricK8sPodMemoryWorkingSet metricK8sPodMemoryWorkingSet + metricK8sPodMemoryLimitUtilization metricK8sPodMemoryLimitUtilization + metricK8sPodMemoryRequestUtilization metricK8sPodMemoryRequestUtilization + metricK8sPodNetworkErrors metricK8sPodNetworkErrors + metricK8sPodNetworkIo metricK8sPodNetworkIo + metricK8sPodUptime metricK8sPodUptime + metricK8sVolumeAvailable metricK8sVolumeAvailable + metricK8sVolumeCapacity metricK8sVolumeCapacity + metricK8sVolumeInodes metricK8sVolumeInodes + metricK8sVolumeInodesFree metricK8sVolumeInodesFree + metricK8sVolumeInodesUsed metricK8sVolumeInodesUsed } // metricBuilderOption applies changes to default metrics builder. @@ -2341,55 +2741,63 @@ func WithStartTime(startTime pcommon.Timestamp) metricBuilderOption { func NewMetricsBuilder(mbc MetricsBuilderConfig, settings receiver.CreateSettings, options ...metricBuilderOption) *MetricsBuilder { mb := &MetricsBuilder{ - config: mbc, - startTime: pcommon.NewTimestampFromTime(time.Now()), - metricsBuffer: pmetric.NewMetrics(), - buildInfo: settings.BuildInfo, - metricContainerCPUTime: newMetricContainerCPUTime(mbc.Metrics.ContainerCPUTime), - metricContainerCPUUtilization: newMetricContainerCPUUtilization(mbc.Metrics.ContainerCPUUtilization), - metricContainerFilesystemAvailable: newMetricContainerFilesystemAvailable(mbc.Metrics.ContainerFilesystemAvailable), - metricContainerFilesystemCapacity: newMetricContainerFilesystemCapacity(mbc.Metrics.ContainerFilesystemCapacity), - metricContainerFilesystemUsage: newMetricContainerFilesystemUsage(mbc.Metrics.ContainerFilesystemUsage), - metricContainerMemoryAvailable: newMetricContainerMemoryAvailable(mbc.Metrics.ContainerMemoryAvailable), - metricContainerMemoryMajorPageFaults: newMetricContainerMemoryMajorPageFaults(mbc.Metrics.ContainerMemoryMajorPageFaults), - metricContainerMemoryPageFaults: newMetricContainerMemoryPageFaults(mbc.Metrics.ContainerMemoryPageFaults), - metricContainerMemoryRss: newMetricContainerMemoryRss(mbc.Metrics.ContainerMemoryRss), - metricContainerMemoryUsage: newMetricContainerMemoryUsage(mbc.Metrics.ContainerMemoryUsage), - metricContainerMemoryWorkingSet: newMetricContainerMemoryWorkingSet(mbc.Metrics.ContainerMemoryWorkingSet), - metricContainerUptime: newMetricContainerUptime(mbc.Metrics.ContainerUptime), - metricK8sNodeCPUTime: newMetricK8sNodeCPUTime(mbc.Metrics.K8sNodeCPUTime), - metricK8sNodeCPUUtilization: newMetricK8sNodeCPUUtilization(mbc.Metrics.K8sNodeCPUUtilization), - metricK8sNodeFilesystemAvailable: newMetricK8sNodeFilesystemAvailable(mbc.Metrics.K8sNodeFilesystemAvailable), - metricK8sNodeFilesystemCapacity: newMetricK8sNodeFilesystemCapacity(mbc.Metrics.K8sNodeFilesystemCapacity), - metricK8sNodeFilesystemUsage: newMetricK8sNodeFilesystemUsage(mbc.Metrics.K8sNodeFilesystemUsage), - metricK8sNodeMemoryAvailable: newMetricK8sNodeMemoryAvailable(mbc.Metrics.K8sNodeMemoryAvailable), - metricK8sNodeMemoryMajorPageFaults: newMetricK8sNodeMemoryMajorPageFaults(mbc.Metrics.K8sNodeMemoryMajorPageFaults), - metricK8sNodeMemoryPageFaults: newMetricK8sNodeMemoryPageFaults(mbc.Metrics.K8sNodeMemoryPageFaults), - metricK8sNodeMemoryRss: newMetricK8sNodeMemoryRss(mbc.Metrics.K8sNodeMemoryRss), - metricK8sNodeMemoryUsage: newMetricK8sNodeMemoryUsage(mbc.Metrics.K8sNodeMemoryUsage), - metricK8sNodeMemoryWorkingSet: newMetricK8sNodeMemoryWorkingSet(mbc.Metrics.K8sNodeMemoryWorkingSet), - metricK8sNodeNetworkErrors: newMetricK8sNodeNetworkErrors(mbc.Metrics.K8sNodeNetworkErrors), - metricK8sNodeNetworkIo: newMetricK8sNodeNetworkIo(mbc.Metrics.K8sNodeNetworkIo), - metricK8sNodeUptime: newMetricK8sNodeUptime(mbc.Metrics.K8sNodeUptime), - metricK8sPodCPUTime: newMetricK8sPodCPUTime(mbc.Metrics.K8sPodCPUTime), - metricK8sPodCPUUtilization: newMetricK8sPodCPUUtilization(mbc.Metrics.K8sPodCPUUtilization), - metricK8sPodFilesystemAvailable: newMetricK8sPodFilesystemAvailable(mbc.Metrics.K8sPodFilesystemAvailable), - metricK8sPodFilesystemCapacity: newMetricK8sPodFilesystemCapacity(mbc.Metrics.K8sPodFilesystemCapacity), - metricK8sPodFilesystemUsage: newMetricK8sPodFilesystemUsage(mbc.Metrics.K8sPodFilesystemUsage), - metricK8sPodMemoryAvailable: newMetricK8sPodMemoryAvailable(mbc.Metrics.K8sPodMemoryAvailable), - metricK8sPodMemoryMajorPageFaults: newMetricK8sPodMemoryMajorPageFaults(mbc.Metrics.K8sPodMemoryMajorPageFaults), - metricK8sPodMemoryPageFaults: newMetricK8sPodMemoryPageFaults(mbc.Metrics.K8sPodMemoryPageFaults), - metricK8sPodMemoryRss: newMetricK8sPodMemoryRss(mbc.Metrics.K8sPodMemoryRss), - metricK8sPodMemoryUsage: newMetricK8sPodMemoryUsage(mbc.Metrics.K8sPodMemoryUsage), - metricK8sPodMemoryWorkingSet: newMetricK8sPodMemoryWorkingSet(mbc.Metrics.K8sPodMemoryWorkingSet), - metricK8sPodNetworkErrors: newMetricK8sPodNetworkErrors(mbc.Metrics.K8sPodNetworkErrors), - metricK8sPodNetworkIo: newMetricK8sPodNetworkIo(mbc.Metrics.K8sPodNetworkIo), - metricK8sPodUptime: newMetricK8sPodUptime(mbc.Metrics.K8sPodUptime), - metricK8sVolumeAvailable: newMetricK8sVolumeAvailable(mbc.Metrics.K8sVolumeAvailable), - metricK8sVolumeCapacity: newMetricK8sVolumeCapacity(mbc.Metrics.K8sVolumeCapacity), - metricK8sVolumeInodes: newMetricK8sVolumeInodes(mbc.Metrics.K8sVolumeInodes), - metricK8sVolumeInodesFree: newMetricK8sVolumeInodesFree(mbc.Metrics.K8sVolumeInodesFree), - metricK8sVolumeInodesUsed: newMetricK8sVolumeInodesUsed(mbc.Metrics.K8sVolumeInodesUsed), + config: mbc, + startTime: pcommon.NewTimestampFromTime(time.Now()), + metricsBuffer: pmetric.NewMetrics(), + buildInfo: settings.BuildInfo, + metricContainerCPUTime: newMetricContainerCPUTime(mbc.Metrics.ContainerCPUTime), + metricContainerCPUUtilization: newMetricContainerCPUUtilization(mbc.Metrics.ContainerCPUUtilization), + metricContainerFilesystemAvailable: newMetricContainerFilesystemAvailable(mbc.Metrics.ContainerFilesystemAvailable), + metricContainerFilesystemCapacity: newMetricContainerFilesystemCapacity(mbc.Metrics.ContainerFilesystemCapacity), + metricContainerFilesystemUsage: newMetricContainerFilesystemUsage(mbc.Metrics.ContainerFilesystemUsage), + metricContainerMemoryAvailable: newMetricContainerMemoryAvailable(mbc.Metrics.ContainerMemoryAvailable), + metricContainerMemoryMajorPageFaults: newMetricContainerMemoryMajorPageFaults(mbc.Metrics.ContainerMemoryMajorPageFaults), + metricContainerMemoryPageFaults: newMetricContainerMemoryPageFaults(mbc.Metrics.ContainerMemoryPageFaults), + metricContainerMemoryRss: newMetricContainerMemoryRss(mbc.Metrics.ContainerMemoryRss), + metricContainerMemoryUsage: newMetricContainerMemoryUsage(mbc.Metrics.ContainerMemoryUsage), + metricContainerMemoryWorkingSet: newMetricContainerMemoryWorkingSet(mbc.Metrics.ContainerMemoryWorkingSet), + metricContainerUptime: newMetricContainerUptime(mbc.Metrics.ContainerUptime), + metricK8sContainerCPULimitUtilization: newMetricK8sContainerCPULimitUtilization(mbc.Metrics.K8sContainerCPULimitUtilization), + metricK8sContainerCPURequestUtilization: newMetricK8sContainerCPURequestUtilization(mbc.Metrics.K8sContainerCPURequestUtilization), + metricK8sContainerMemoryLimitUtilization: newMetricK8sContainerMemoryLimitUtilization(mbc.Metrics.K8sContainerMemoryLimitUtilization), + metricK8sContainerMemoryRequestUtilization: newMetricK8sContainerMemoryRequestUtilization(mbc.Metrics.K8sContainerMemoryRequestUtilization), + metricK8sNodeCPUTime: newMetricK8sNodeCPUTime(mbc.Metrics.K8sNodeCPUTime), + metricK8sNodeCPUUtilization: newMetricK8sNodeCPUUtilization(mbc.Metrics.K8sNodeCPUUtilization), + metricK8sNodeFilesystemAvailable: newMetricK8sNodeFilesystemAvailable(mbc.Metrics.K8sNodeFilesystemAvailable), + metricK8sNodeFilesystemCapacity: newMetricK8sNodeFilesystemCapacity(mbc.Metrics.K8sNodeFilesystemCapacity), + metricK8sNodeFilesystemUsage: newMetricK8sNodeFilesystemUsage(mbc.Metrics.K8sNodeFilesystemUsage), + metricK8sNodeMemoryAvailable: newMetricK8sNodeMemoryAvailable(mbc.Metrics.K8sNodeMemoryAvailable), + metricK8sNodeMemoryMajorPageFaults: newMetricK8sNodeMemoryMajorPageFaults(mbc.Metrics.K8sNodeMemoryMajorPageFaults), + metricK8sNodeMemoryPageFaults: newMetricK8sNodeMemoryPageFaults(mbc.Metrics.K8sNodeMemoryPageFaults), + metricK8sNodeMemoryRss: newMetricK8sNodeMemoryRss(mbc.Metrics.K8sNodeMemoryRss), + metricK8sNodeMemoryUsage: newMetricK8sNodeMemoryUsage(mbc.Metrics.K8sNodeMemoryUsage), + metricK8sNodeMemoryWorkingSet: newMetricK8sNodeMemoryWorkingSet(mbc.Metrics.K8sNodeMemoryWorkingSet), + metricK8sNodeNetworkErrors: newMetricK8sNodeNetworkErrors(mbc.Metrics.K8sNodeNetworkErrors), + metricK8sNodeNetworkIo: newMetricK8sNodeNetworkIo(mbc.Metrics.K8sNodeNetworkIo), + metricK8sNodeUptime: newMetricK8sNodeUptime(mbc.Metrics.K8sNodeUptime), + metricK8sPodCPUTime: newMetricK8sPodCPUTime(mbc.Metrics.K8sPodCPUTime), + metricK8sPodCPUUtilization: newMetricK8sPodCPUUtilization(mbc.Metrics.K8sPodCPUUtilization), + metricK8sPodCPULimitUtilization: newMetricK8sPodCPULimitUtilization(mbc.Metrics.K8sPodCPULimitUtilization), + metricK8sPodCPURequestUtilization: newMetricK8sPodCPURequestUtilization(mbc.Metrics.K8sPodCPURequestUtilization), + metricK8sPodFilesystemAvailable: newMetricK8sPodFilesystemAvailable(mbc.Metrics.K8sPodFilesystemAvailable), + metricK8sPodFilesystemCapacity: newMetricK8sPodFilesystemCapacity(mbc.Metrics.K8sPodFilesystemCapacity), + metricK8sPodFilesystemUsage: newMetricK8sPodFilesystemUsage(mbc.Metrics.K8sPodFilesystemUsage), + metricK8sPodMemoryAvailable: newMetricK8sPodMemoryAvailable(mbc.Metrics.K8sPodMemoryAvailable), + metricK8sPodMemoryMajorPageFaults: newMetricK8sPodMemoryMajorPageFaults(mbc.Metrics.K8sPodMemoryMajorPageFaults), + metricK8sPodMemoryPageFaults: newMetricK8sPodMemoryPageFaults(mbc.Metrics.K8sPodMemoryPageFaults), + metricK8sPodMemoryRss: newMetricK8sPodMemoryRss(mbc.Metrics.K8sPodMemoryRss), + metricK8sPodMemoryUsage: newMetricK8sPodMemoryUsage(mbc.Metrics.K8sPodMemoryUsage), + metricK8sPodMemoryWorkingSet: newMetricK8sPodMemoryWorkingSet(mbc.Metrics.K8sPodMemoryWorkingSet), + metricK8sPodMemoryLimitUtilization: newMetricK8sPodMemoryLimitUtilization(mbc.Metrics.K8sPodMemoryLimitUtilization), + metricK8sPodMemoryRequestUtilization: newMetricK8sPodMemoryRequestUtilization(mbc.Metrics.K8sPodMemoryRequestUtilization), + metricK8sPodNetworkErrors: newMetricK8sPodNetworkErrors(mbc.Metrics.K8sPodNetworkErrors), + metricK8sPodNetworkIo: newMetricK8sPodNetworkIo(mbc.Metrics.K8sPodNetworkIo), + metricK8sPodUptime: newMetricK8sPodUptime(mbc.Metrics.K8sPodUptime), + metricK8sVolumeAvailable: newMetricK8sVolumeAvailable(mbc.Metrics.K8sVolumeAvailable), + metricK8sVolumeCapacity: newMetricK8sVolumeCapacity(mbc.Metrics.K8sVolumeCapacity), + metricK8sVolumeInodes: newMetricK8sVolumeInodes(mbc.Metrics.K8sVolumeInodes), + metricK8sVolumeInodesFree: newMetricK8sVolumeInodesFree(mbc.Metrics.K8sVolumeInodesFree), + metricK8sVolumeInodesUsed: newMetricK8sVolumeInodesUsed(mbc.Metrics.K8sVolumeInodesUsed), } for _, op := range options { op(mb) @@ -2463,6 +2871,10 @@ func (mb *MetricsBuilder) EmitForResource(rmo ...ResourceMetricsOption) { mb.metricContainerMemoryUsage.emit(ils.Metrics()) mb.metricContainerMemoryWorkingSet.emit(ils.Metrics()) mb.metricContainerUptime.emit(ils.Metrics()) + mb.metricK8sContainerCPULimitUtilization.emit(ils.Metrics()) + mb.metricK8sContainerCPURequestUtilization.emit(ils.Metrics()) + mb.metricK8sContainerMemoryLimitUtilization.emit(ils.Metrics()) + mb.metricK8sContainerMemoryRequestUtilization.emit(ils.Metrics()) mb.metricK8sNodeCPUTime.emit(ils.Metrics()) mb.metricK8sNodeCPUUtilization.emit(ils.Metrics()) mb.metricK8sNodeFilesystemAvailable.emit(ils.Metrics()) @@ -2479,6 +2891,8 @@ func (mb *MetricsBuilder) EmitForResource(rmo ...ResourceMetricsOption) { mb.metricK8sNodeUptime.emit(ils.Metrics()) mb.metricK8sPodCPUTime.emit(ils.Metrics()) mb.metricK8sPodCPUUtilization.emit(ils.Metrics()) + mb.metricK8sPodCPULimitUtilization.emit(ils.Metrics()) + mb.metricK8sPodCPURequestUtilization.emit(ils.Metrics()) mb.metricK8sPodFilesystemAvailable.emit(ils.Metrics()) mb.metricK8sPodFilesystemCapacity.emit(ils.Metrics()) mb.metricK8sPodFilesystemUsage.emit(ils.Metrics()) @@ -2488,6 +2902,8 @@ func (mb *MetricsBuilder) EmitForResource(rmo ...ResourceMetricsOption) { mb.metricK8sPodMemoryRss.emit(ils.Metrics()) mb.metricK8sPodMemoryUsage.emit(ils.Metrics()) mb.metricK8sPodMemoryWorkingSet.emit(ils.Metrics()) + mb.metricK8sPodMemoryLimitUtilization.emit(ils.Metrics()) + mb.metricK8sPodMemoryRequestUtilization.emit(ils.Metrics()) mb.metricK8sPodNetworkErrors.emit(ils.Metrics()) mb.metricK8sPodNetworkIo.emit(ils.Metrics()) mb.metricK8sPodUptime.emit(ils.Metrics()) @@ -2576,6 +2992,26 @@ func (mb *MetricsBuilder) RecordContainerUptimeDataPoint(ts pcommon.Timestamp, v mb.metricContainerUptime.recordDataPoint(mb.startTime, ts, val) } +// RecordK8sContainerCPULimitUtilizationDataPoint adds a data point to k8s.container.cpu_limit_utilization metric. +func (mb *MetricsBuilder) RecordK8sContainerCPULimitUtilizationDataPoint(ts pcommon.Timestamp, val float64) { + mb.metricK8sContainerCPULimitUtilization.recordDataPoint(mb.startTime, ts, val) +} + +// RecordK8sContainerCPURequestUtilizationDataPoint adds a data point to k8s.container.cpu_request_utilization metric. +func (mb *MetricsBuilder) RecordK8sContainerCPURequestUtilizationDataPoint(ts pcommon.Timestamp, val float64) { + mb.metricK8sContainerCPURequestUtilization.recordDataPoint(mb.startTime, ts, val) +} + +// RecordK8sContainerMemoryLimitUtilizationDataPoint adds a data point to k8s.container.memory_limit_utilization metric. +func (mb *MetricsBuilder) RecordK8sContainerMemoryLimitUtilizationDataPoint(ts pcommon.Timestamp, val float64) { + mb.metricK8sContainerMemoryLimitUtilization.recordDataPoint(mb.startTime, ts, val) +} + +// RecordK8sContainerMemoryRequestUtilizationDataPoint adds a data point to k8s.container.memory_request_utilization metric. +func (mb *MetricsBuilder) RecordK8sContainerMemoryRequestUtilizationDataPoint(ts pcommon.Timestamp, val float64) { + mb.metricK8sContainerMemoryRequestUtilization.recordDataPoint(mb.startTime, ts, val) +} + // RecordK8sNodeCPUTimeDataPoint adds a data point to k8s.node.cpu.time metric. func (mb *MetricsBuilder) RecordK8sNodeCPUTimeDataPoint(ts pcommon.Timestamp, val float64) { mb.metricK8sNodeCPUTime.recordDataPoint(mb.startTime, ts, val) @@ -2656,6 +3092,16 @@ func (mb *MetricsBuilder) RecordK8sPodCPUUtilizationDataPoint(ts pcommon.Timesta mb.metricK8sPodCPUUtilization.recordDataPoint(mb.startTime, ts, val) } +// RecordK8sPodCPULimitUtilizationDataPoint adds a data point to k8s.pod.cpu_limit_utilization metric. +func (mb *MetricsBuilder) RecordK8sPodCPULimitUtilizationDataPoint(ts pcommon.Timestamp, val float64) { + mb.metricK8sPodCPULimitUtilization.recordDataPoint(mb.startTime, ts, val) +} + +// RecordK8sPodCPURequestUtilizationDataPoint adds a data point to k8s.pod.cpu_request_utilization metric. +func (mb *MetricsBuilder) RecordK8sPodCPURequestUtilizationDataPoint(ts pcommon.Timestamp, val float64) { + mb.metricK8sPodCPURequestUtilization.recordDataPoint(mb.startTime, ts, val) +} + // RecordK8sPodFilesystemAvailableDataPoint adds a data point to k8s.pod.filesystem.available metric. func (mb *MetricsBuilder) RecordK8sPodFilesystemAvailableDataPoint(ts pcommon.Timestamp, val int64) { mb.metricK8sPodFilesystemAvailable.recordDataPoint(mb.startTime, ts, val) @@ -2701,6 +3147,16 @@ func (mb *MetricsBuilder) RecordK8sPodMemoryWorkingSetDataPoint(ts pcommon.Times mb.metricK8sPodMemoryWorkingSet.recordDataPoint(mb.startTime, ts, val) } +// RecordK8sPodMemoryLimitUtilizationDataPoint adds a data point to k8s.pod.memory_limit_utilization metric. +func (mb *MetricsBuilder) RecordK8sPodMemoryLimitUtilizationDataPoint(ts pcommon.Timestamp, val float64) { + mb.metricK8sPodMemoryLimitUtilization.recordDataPoint(mb.startTime, ts, val) +} + +// RecordK8sPodMemoryRequestUtilizationDataPoint adds a data point to k8s.pod.memory_request_utilization metric. +func (mb *MetricsBuilder) RecordK8sPodMemoryRequestUtilizationDataPoint(ts pcommon.Timestamp, val float64) { + mb.metricK8sPodMemoryRequestUtilization.recordDataPoint(mb.startTime, ts, val) +} + // RecordK8sPodNetworkErrorsDataPoint adds a data point to k8s.pod.network.errors metric. func (mb *MetricsBuilder) RecordK8sPodNetworkErrorsDataPoint(ts pcommon.Timestamp, val int64, interfaceAttributeValue string, directionAttributeValue AttributeDirection) { mb.metricK8sPodNetworkErrors.recordDataPoint(mb.startTime, ts, val, interfaceAttributeValue, directionAttributeValue.String()) diff --git a/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics_test.go b/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics_test.go index 8cb04a401cfc..868412f52261 100644 --- a/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics_test.go +++ b/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics_test.go @@ -49,6 +49,7 @@ func TestMetricsBuilder(t *testing.T) { mb := NewMetricsBuilder(loadMetricsBuilderConfig(t, test.name), settings, WithStartTime(start)) expectedWarnings := 0 + assert.Equal(t, expectedWarnings, observedLogs.Len()) defaultMetricsCount := 0 @@ -101,6 +102,18 @@ func TestMetricsBuilder(t *testing.T) { allMetricsCount++ mb.RecordContainerUptimeDataPoint(ts, 1) + allMetricsCount++ + mb.RecordK8sContainerCPULimitUtilizationDataPoint(ts, 1) + + allMetricsCount++ + mb.RecordK8sContainerCPURequestUtilizationDataPoint(ts, 1) + + allMetricsCount++ + mb.RecordK8sContainerMemoryLimitUtilizationDataPoint(ts, 1) + + allMetricsCount++ + mb.RecordK8sContainerMemoryRequestUtilizationDataPoint(ts, 1) + defaultMetricsCount++ allMetricsCount++ mb.RecordK8sNodeCPUTimeDataPoint(ts, 1) @@ -164,6 +177,12 @@ func TestMetricsBuilder(t *testing.T) { allMetricsCount++ mb.RecordK8sPodCPUUtilizationDataPoint(ts, 1) + allMetricsCount++ + mb.RecordK8sPodCPULimitUtilizationDataPoint(ts, 1) + + allMetricsCount++ + mb.RecordK8sPodCPURequestUtilizationDataPoint(ts, 1) + defaultMetricsCount++ allMetricsCount++ mb.RecordK8sPodFilesystemAvailableDataPoint(ts, 1) @@ -200,6 +219,12 @@ func TestMetricsBuilder(t *testing.T) { allMetricsCount++ mb.RecordK8sPodMemoryWorkingSetDataPoint(ts, 1) + allMetricsCount++ + mb.RecordK8sPodMemoryLimitUtilizationDataPoint(ts, 1) + + allMetricsCount++ + mb.RecordK8sPodMemoryRequestUtilizationDataPoint(ts, 1) + defaultMetricsCount++ allMetricsCount++ mb.RecordK8sPodNetworkErrorsDataPoint(ts, 1, "interface-val", AttributeDirectionReceive) @@ -422,6 +447,54 @@ func TestMetricsBuilder(t *testing.T) { assert.Equal(t, ts, dp.Timestamp()) assert.Equal(t, pmetric.NumberDataPointValueTypeInt, dp.ValueType()) assert.Equal(t, int64(1), dp.IntValue()) + case "k8s.container.cpu_limit_utilization": + assert.False(t, validatedMetrics["k8s.container.cpu_limit_utilization"], "Found a duplicate in the metrics slice: k8s.container.cpu_limit_utilization") + validatedMetrics["k8s.container.cpu_limit_utilization"] = true + assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len()) + assert.Equal(t, "Container cpu utilization as a ratio of the container's limits", ms.At(i).Description()) + assert.Equal(t, "1", ms.At(i).Unit()) + dp := ms.At(i).Gauge().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType()) + assert.Equal(t, float64(1), dp.DoubleValue()) + case "k8s.container.cpu_request_utilization": + assert.False(t, validatedMetrics["k8s.container.cpu_request_utilization"], "Found a duplicate in the metrics slice: k8s.container.cpu_request_utilization") + validatedMetrics["k8s.container.cpu_request_utilization"] = true + assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len()) + assert.Equal(t, "Container cpu utilization as a ratio of the container's requests", ms.At(i).Description()) + assert.Equal(t, "1", ms.At(i).Unit()) + dp := ms.At(i).Gauge().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType()) + assert.Equal(t, float64(1), dp.DoubleValue()) + case "k8s.container.memory_limit_utilization": + assert.False(t, validatedMetrics["k8s.container.memory_limit_utilization"], "Found a duplicate in the metrics slice: k8s.container.memory_limit_utilization") + validatedMetrics["k8s.container.memory_limit_utilization"] = true + assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len()) + assert.Equal(t, "Container memory utilization as a ratio of the container's limits", ms.At(i).Description()) + assert.Equal(t, "1", ms.At(i).Unit()) + dp := ms.At(i).Gauge().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType()) + assert.Equal(t, float64(1), dp.DoubleValue()) + case "k8s.container.memory_request_utilization": + assert.False(t, validatedMetrics["k8s.container.memory_request_utilization"], "Found a duplicate in the metrics slice: k8s.container.memory_request_utilization") + validatedMetrics["k8s.container.memory_request_utilization"] = true + assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len()) + assert.Equal(t, "Container memory utilization as a ratio of the container's requests", ms.At(i).Description()) + assert.Equal(t, "1", ms.At(i).Unit()) + dp := ms.At(i).Gauge().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType()) + assert.Equal(t, float64(1), dp.DoubleValue()) case "k8s.node.cpu.time": assert.False(t, validatedMetrics["k8s.node.cpu.time"], "Found a duplicate in the metrics slice: k8s.node.cpu.time") validatedMetrics["k8s.node.cpu.time"] = true @@ -636,6 +709,30 @@ func TestMetricsBuilder(t *testing.T) { assert.Equal(t, ts, dp.Timestamp()) assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType()) assert.Equal(t, float64(1), dp.DoubleValue()) + case "k8s.pod.cpu_limit_utilization": + assert.False(t, validatedMetrics["k8s.pod.cpu_limit_utilization"], "Found a duplicate in the metrics slice: k8s.pod.cpu_limit_utilization") + validatedMetrics["k8s.pod.cpu_limit_utilization"] = true + assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len()) + assert.Equal(t, "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.", ms.At(i).Description()) + assert.Equal(t, "1", ms.At(i).Unit()) + dp := ms.At(i).Gauge().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType()) + assert.Equal(t, float64(1), dp.DoubleValue()) + case "k8s.pod.cpu_request_utilization": + assert.False(t, validatedMetrics["k8s.pod.cpu_request_utilization"], "Found a duplicate in the metrics slice: k8s.pod.cpu_request_utilization") + validatedMetrics["k8s.pod.cpu_request_utilization"] = true + assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len()) + assert.Equal(t, "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.", ms.At(i).Description()) + assert.Equal(t, "1", ms.At(i).Unit()) + dp := ms.At(i).Gauge().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType()) + assert.Equal(t, float64(1), dp.DoubleValue()) case "k8s.pod.filesystem.available": assert.False(t, validatedMetrics["k8s.pod.filesystem.available"], "Found a duplicate in the metrics slice: k8s.pod.filesystem.available") validatedMetrics["k8s.pod.filesystem.available"] = true @@ -744,6 +841,30 @@ func TestMetricsBuilder(t *testing.T) { assert.Equal(t, ts, dp.Timestamp()) assert.Equal(t, pmetric.NumberDataPointValueTypeInt, dp.ValueType()) assert.Equal(t, int64(1), dp.IntValue()) + case "k8s.pod.memory_limit_utilization": + assert.False(t, validatedMetrics["k8s.pod.memory_limit_utilization"], "Found a duplicate in the metrics slice: k8s.pod.memory_limit_utilization") + validatedMetrics["k8s.pod.memory_limit_utilization"] = true + assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len()) + assert.Equal(t, "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.", ms.At(i).Description()) + assert.Equal(t, "1", ms.At(i).Unit()) + dp := ms.At(i).Gauge().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType()) + assert.Equal(t, float64(1), dp.DoubleValue()) + case "k8s.pod.memory_request_utilization": + assert.False(t, validatedMetrics["k8s.pod.memory_request_utilization"], "Found a duplicate in the metrics slice: k8s.pod.memory_request_utilization") + validatedMetrics["k8s.pod.memory_request_utilization"] = true + assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len()) + assert.Equal(t, "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.", ms.At(i).Description()) + assert.Equal(t, "1", ms.At(i).Unit()) + dp := ms.At(i).Gauge().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType()) + assert.Equal(t, float64(1), dp.DoubleValue()) case "k8s.pod.network.errors": assert.False(t, validatedMetrics["k8s.pod.network.errors"], "Found a duplicate in the metrics slice: k8s.pod.network.errors") validatedMetrics["k8s.pod.network.errors"] = true diff --git a/receiver/kubeletstatsreceiver/internal/metadata/generated_status.go b/receiver/kubeletstatsreceiver/internal/metadata/generated_status.go index 464c8e8a8707..69c4917f6879 100644 --- a/receiver/kubeletstatsreceiver/internal/metadata/generated_status.go +++ b/receiver/kubeletstatsreceiver/internal/metadata/generated_status.go @@ -4,9 +4,19 @@ package metadata import ( "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" ) const ( Type = "kubeletstats" MetricsStability = component.StabilityLevelBeta ) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("otelcol/kubeletstatsreceiver") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("otelcol/kubeletstatsreceiver") +} diff --git a/receiver/kubeletstatsreceiver/internal/metadata/metrics.go b/receiver/kubeletstatsreceiver/internal/metadata/metrics.go index 838a53efd3ba..b999cec70a4e 100644 --- a/receiver/kubeletstatsreceiver/internal/metadata/metrics.go +++ b/receiver/kubeletstatsreceiver/internal/metadata/metrics.go @@ -19,8 +19,10 @@ type MetricsBuilders struct { } type CPUMetrics struct { - Time RecordDoubleDataPointFunc - Utilization RecordDoubleDataPointFunc + Time RecordDoubleDataPointFunc + Utilization RecordDoubleDataPointFunc + LimitUtilization RecordDoubleDataPointFunc + RequestUtilization RecordDoubleDataPointFunc } var NodeCPUMetrics = CPUMetrics{ @@ -29,22 +31,28 @@ var NodeCPUMetrics = CPUMetrics{ } var PodCPUMetrics = CPUMetrics{ - Time: (*MetricsBuilder).RecordK8sPodCPUTimeDataPoint, - Utilization: (*MetricsBuilder).RecordK8sPodCPUUtilizationDataPoint, + Time: (*MetricsBuilder).RecordK8sPodCPUTimeDataPoint, + Utilization: (*MetricsBuilder).RecordK8sPodCPUUtilizationDataPoint, + LimitUtilization: (*MetricsBuilder).RecordK8sPodCPULimitUtilizationDataPoint, + RequestUtilization: (*MetricsBuilder).RecordK8sPodCPURequestUtilizationDataPoint, } var ContainerCPUMetrics = CPUMetrics{ - Time: (*MetricsBuilder).RecordContainerCPUTimeDataPoint, - Utilization: (*MetricsBuilder).RecordContainerCPUUtilizationDataPoint, + Time: (*MetricsBuilder).RecordContainerCPUTimeDataPoint, + Utilization: (*MetricsBuilder).RecordContainerCPUUtilizationDataPoint, + LimitUtilization: (*MetricsBuilder).RecordK8sContainerCPULimitUtilizationDataPoint, + RequestUtilization: (*MetricsBuilder).RecordK8sContainerCPURequestUtilizationDataPoint, } type MemoryMetrics struct { - Available RecordIntDataPointFunc - Usage RecordIntDataPointFunc - Rss RecordIntDataPointFunc - WorkingSet RecordIntDataPointFunc - PageFaults RecordIntDataPointFunc - MajorPageFaults RecordIntDataPointFunc + Available RecordIntDataPointFunc + Usage RecordIntDataPointFunc + Rss RecordIntDataPointFunc + WorkingSet RecordIntDataPointFunc + PageFaults RecordIntDataPointFunc + MajorPageFaults RecordIntDataPointFunc + LimitUtilization RecordDoubleDataPointFunc + RequestUtilization RecordDoubleDataPointFunc } var NodeMemoryMetrics = MemoryMetrics{ @@ -57,21 +65,25 @@ var NodeMemoryMetrics = MemoryMetrics{ } var PodMemoryMetrics = MemoryMetrics{ - Available: (*MetricsBuilder).RecordK8sPodMemoryAvailableDataPoint, - Usage: (*MetricsBuilder).RecordK8sPodMemoryUsageDataPoint, - Rss: (*MetricsBuilder).RecordK8sPodMemoryRssDataPoint, - WorkingSet: (*MetricsBuilder).RecordK8sPodMemoryWorkingSetDataPoint, - PageFaults: (*MetricsBuilder).RecordK8sPodMemoryPageFaultsDataPoint, - MajorPageFaults: (*MetricsBuilder).RecordK8sPodMemoryMajorPageFaultsDataPoint, + Available: (*MetricsBuilder).RecordK8sPodMemoryAvailableDataPoint, + Usage: (*MetricsBuilder).RecordK8sPodMemoryUsageDataPoint, + Rss: (*MetricsBuilder).RecordK8sPodMemoryRssDataPoint, + WorkingSet: (*MetricsBuilder).RecordK8sPodMemoryWorkingSetDataPoint, + PageFaults: (*MetricsBuilder).RecordK8sPodMemoryPageFaultsDataPoint, + MajorPageFaults: (*MetricsBuilder).RecordK8sPodMemoryMajorPageFaultsDataPoint, + LimitUtilization: (*MetricsBuilder).RecordK8sPodMemoryLimitUtilizationDataPoint, + RequestUtilization: (*MetricsBuilder).RecordK8sPodMemoryRequestUtilizationDataPoint, } var ContainerMemoryMetrics = MemoryMetrics{ - Available: (*MetricsBuilder).RecordContainerMemoryAvailableDataPoint, - Usage: (*MetricsBuilder).RecordContainerMemoryUsageDataPoint, - Rss: (*MetricsBuilder).RecordContainerMemoryRssDataPoint, - WorkingSet: (*MetricsBuilder).RecordContainerMemoryWorkingSetDataPoint, - PageFaults: (*MetricsBuilder).RecordContainerMemoryPageFaultsDataPoint, - MajorPageFaults: (*MetricsBuilder).RecordContainerMemoryMajorPageFaultsDataPoint, + Available: (*MetricsBuilder).RecordContainerMemoryAvailableDataPoint, + Usage: (*MetricsBuilder).RecordContainerMemoryUsageDataPoint, + Rss: (*MetricsBuilder).RecordContainerMemoryRssDataPoint, + WorkingSet: (*MetricsBuilder).RecordContainerMemoryWorkingSetDataPoint, + PageFaults: (*MetricsBuilder).RecordContainerMemoryPageFaultsDataPoint, + MajorPageFaults: (*MetricsBuilder).RecordContainerMemoryMajorPageFaultsDataPoint, + LimitUtilization: (*MetricsBuilder).RecordK8sContainerMemoryLimitUtilizationDataPoint, + RequestUtilization: (*MetricsBuilder).RecordK8sContainerMemoryRequestUtilizationDataPoint, } type FilesystemMetrics struct { diff --git a/receiver/kubeletstatsreceiver/internal/metadata/testdata/config.yaml b/receiver/kubeletstatsreceiver/internal/metadata/testdata/config.yaml index 0139a4fb32ff..9d122bd2f8ef 100644 --- a/receiver/kubeletstatsreceiver/internal/metadata/testdata/config.yaml +++ b/receiver/kubeletstatsreceiver/internal/metadata/testdata/config.yaml @@ -25,6 +25,14 @@ all_set: enabled: true container.uptime: enabled: true + k8s.container.cpu_limit_utilization: + enabled: true + k8s.container.cpu_request_utilization: + enabled: true + k8s.container.memory_limit_utilization: + enabled: true + k8s.container.memory_request_utilization: + enabled: true k8s.node.cpu.time: enabled: true k8s.node.cpu.utilization: @@ -57,6 +65,10 @@ all_set: enabled: true k8s.pod.cpu.utilization: enabled: true + k8s.pod.cpu_limit_utilization: + enabled: true + k8s.pod.cpu_request_utilization: + enabled: true k8s.pod.filesystem.available: enabled: true k8s.pod.filesystem.capacity: @@ -75,6 +87,10 @@ all_set: enabled: true k8s.pod.memory.working_set: enabled: true + k8s.pod.memory_limit_utilization: + enabled: true + k8s.pod.memory_request_utilization: + enabled: true k8s.pod.network.errors: enabled: true k8s.pod.network.io: @@ -158,6 +174,14 @@ none_set: enabled: false container.uptime: enabled: false + k8s.container.cpu_limit_utilization: + enabled: false + k8s.container.cpu_request_utilization: + enabled: false + k8s.container.memory_limit_utilization: + enabled: false + k8s.container.memory_request_utilization: + enabled: false k8s.node.cpu.time: enabled: false k8s.node.cpu.utilization: @@ -190,6 +214,10 @@ none_set: enabled: false k8s.pod.cpu.utilization: enabled: false + k8s.pod.cpu_limit_utilization: + enabled: false + k8s.pod.cpu_request_utilization: + enabled: false k8s.pod.filesystem.available: enabled: false k8s.pod.filesystem.capacity: @@ -208,6 +236,10 @@ none_set: enabled: false k8s.pod.memory.working_set: enabled: false + k8s.pod.memory_limit_utilization: + enabled: false + k8s.pod.memory_request_utilization: + enabled: false k8s.pod.network.errors: enabled: false k8s.pod.network.io: diff --git a/receiver/kubeletstatsreceiver/metadata.yaml b/receiver/kubeletstatsreceiver/metadata.yaml index bc009c848a06..e994d7883a78 100644 --- a/receiver/kubeletstatsreceiver/metadata.yaml +++ b/receiver/kubeletstatsreceiver/metadata.yaml @@ -237,6 +237,34 @@ metrics: gauge: value_type: int attributes: [] + k8s.pod.cpu_limit_utilization: + enabled: false + description: "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: 1 + gauge: + value_type: double + attributes: [ ] + k8s.pod.cpu_request_utilization: + enabled: false + description: "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: 1 + gauge: + value_type: double + attributes: [ ] + k8s.pod.memory_limit_utilization: + enabled: false + description: "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: 1 + gauge: + value_type: double + attributes: [ ] + k8s.pod.memory_request_utilization: + enabled: false + description: "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: 1 + gauge: + value_type: double + attributes: [ ] k8s.pod.memory.rss: enabled: true description: "Pod memory rss" @@ -343,6 +371,34 @@ metrics: gauge: value_type: int attributes: [] + k8s.container.cpu_limit_utilization: + enabled: false + description: "Container cpu utilization as a ratio of the container's limits" + unit: 1 + gauge: + value_type: double + attributes: [ ] + k8s.container.cpu_request_utilization: + enabled: false + description: "Container cpu utilization as a ratio of the container's requests" + unit: 1 + gauge: + value_type: double + attributes: [ ] + k8s.container.memory_limit_utilization: + enabled: false + description: "Container memory utilization as a ratio of the container's limits" + unit: 1 + gauge: + value_type: double + attributes: [ ] + k8s.container.memory_request_utilization: + enabled: false + description: "Container memory utilization as a ratio of the container's requests" + unit: 1 + gauge: + value_type: double + attributes: [ ] container.memory.rss: enabled: true description: "Container memory rss" diff --git a/receiver/kubeletstatsreceiver/scraper.go b/receiver/kubeletstatsreceiver/scraper.go index 26beef78efc4..d4c7e0b95d1f 100644 --- a/receiver/kubeletstatsreceiver/scraper.go +++ b/receiver/kubeletstatsreceiver/scraper.go @@ -37,6 +37,7 @@ type kubletScraper struct { k8sAPIClient kubernetes.Interface cachedVolumeSource map[string]v1.PersistentVolumeSource mbs *metadata.MetricsBuilders + needsResources bool } func newKubletScraper( @@ -59,6 +60,14 @@ func newKubletScraper( ContainerMetricsBuilder: metadata.NewMetricsBuilder(metricsConfig, set), OtherMetricsBuilder: metadata.NewMetricsBuilder(metricsConfig, set), }, + needsResources: metricsConfig.Metrics.K8sPodCPULimitUtilization.Enabled || + metricsConfig.Metrics.K8sPodCPURequestUtilization.Enabled || + metricsConfig.Metrics.K8sContainerCPULimitUtilization.Enabled || + metricsConfig.Metrics.K8sContainerCPURequestUtilization.Enabled || + metricsConfig.Metrics.K8sPodMemoryLimitUtilization.Enabled || + metricsConfig.Metrics.K8sPodMemoryRequestUtilization.Enabled || + metricsConfig.Metrics.K8sContainerMemoryLimitUtilization.Enabled || + metricsConfig.Metrics.K8sContainerMemoryRequestUtilization.Enabled, } return scraperhelper.NewScraper(metadata.Type, ks.scrape) } @@ -72,7 +81,7 @@ func (r *kubletScraper) scrape(context.Context) (pmetric.Metrics, error) { var podsMetadata *v1.PodList // fetch metadata only when extra metadata labels are needed - if len(r.extraMetadataLabels) > 0 { + if len(r.extraMetadataLabels) > 0 || r.needsResources { podsMetadata, err = r.metadataProvider.Pods() if err != nil { r.logger.Error("call to /pods endpoint failed", zap.Error(err))