From 263c955c4598a5e97f8f36d7d31438f8e8fc1bb7 Mon Sep 17 00:00:00 2001 From: hiromasa-iwayama Date: Mon, 4 Dec 2023 20:36:56 +0900 Subject: [PATCH] wip --- receiver/k8sclusterreceiver/documentation.md | 30 ++ .../internal/collection/collector.go | 5 + .../k8sclusterreceiver/internal/gvk/gvk.go | 29 +- .../k8sclusterreceiver/internal/gvr/gvr.go | 11 + .../hierarchicalresourcequotas.go | 44 ++ .../hierarchicalresourcequotas_test.go | 39 ++ .../testdata/expected.yaml | 38 ++ .../internal/metadata/generated_config.go | 170 ++++--- .../metadata/generated_config_test.go | 452 +++++++++--------- .../internal/metadata/generated_metrics.go | 298 ++++++++---- .../metadata/generated_metrics_test.go | 40 ++ .../internal/metadata/generated_resource.go | 14 + .../metadata/generated_resource_test.go | 16 +- .../internal/metadata/testdata/config.yaml | 16 + .../internal/testutils/objects.go | 25 + receiver/k8sclusterreceiver/metadata.yaml | 26 + receiver/k8sclusterreceiver/watcher.go | 38 +- 17 files changed, 886 insertions(+), 405 deletions(-) create mode 100644 receiver/k8sclusterreceiver/internal/gvr/gvr.go create mode 100644 receiver/k8sclusterreceiver/internal/hierarchicalresourcequota/hierarchicalresourcequotas.go create mode 100644 receiver/k8sclusterreceiver/internal/hierarchicalresourcequota/hierarchicalresourcequotas_test.go create mode 100644 receiver/k8sclusterreceiver/internal/hierarchicalresourcequota/testdata/expected.yaml diff --git a/receiver/k8sclusterreceiver/documentation.md b/receiver/k8sclusterreceiver/documentation.md index 5cbe995baaa0..4bf87275f7f6 100644 --- a/receiver/k8sclusterreceiver/documentation.md +++ b/receiver/k8sclusterreceiver/documentation.md @@ -148,6 +148,34 @@ Number of desired pods in this deployment | ---- | ----------- | ---------- | | {pod} | Gauge | Int | +### k8s.hierarchical_resource_quota.hard_limit + +The upper limit for a particular resource in a specific namespace. Will only be sent if a quota is specified. CPU requests/limits will be sent as millicores + +| Unit | Metric Type | Value Type | +| ---- | ----------- | ---------- | +| {resource} | Gauge | Int | + +#### Attributes + +| Name | Description | Values | +| ---- | ----------- | ------ | +| resource | the name of the resource on which the quota is applied | Any Str | + +### k8s.hierarchical_resource_quota.used + +The usage for a particular resource in a specific namespace. Will only be sent if a quota is specified. CPU requests/limits will be sent as millicores + +| Unit | Metric Type | Value Type | +| ---- | ----------- | ---------- | +| {resource} | Gauge | Int | + +#### Attributes + +| Name | Description | Values | +| ---- | ----------- | ------ | +| resource | the name of the resource on which the quota is applied | Any Str | + ### k8s.hpa.current_replicas Current number of pod replicas managed by this autoscaler. @@ -432,6 +460,8 @@ Current status reason of the pod (1 - Evicted, 2 - NodeAffinity, 3 - NodeLost, 4 | k8s.daemonset.uid | The k8s daemonset uid. | Any Str | true | | k8s.deployment.name | The name of the Deployment. | Any Str | true | | k8s.deployment.uid | The UID of the Deployment. | Any Str | true | +| k8s.hierarchicalresourcequota.name | The k8s HierarchicalresourceQuota name. | Any Str | true | +| k8s.hierarchicalresourcequota.uid | The k8s HierarchicalResourceQuota uid. | Any Str | true | | k8s.hpa.name | The k8s hpa name. | Any Str | true | | k8s.hpa.uid | The k8s hpa uid. | Any Str | true | | k8s.job.name | The k8s pod name. | Any Str | true | diff --git a/receiver/k8sclusterreceiver/internal/collection/collector.go b/receiver/k8sclusterreceiver/internal/collection/collector.go index 4269d4f112ae..1dc0799e5fbc 100644 --- a/receiver/k8sclusterreceiver/internal/collection/collector.go +++ b/receiver/k8sclusterreceiver/internal/collection/collector.go @@ -14,12 +14,14 @@ import ( autoscalingv2 "k8s.io/api/autoscaling/v2" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/clusterresourcequota" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/cronjob" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/demonset" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/deployment" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/gvk" + "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/hierarchicalresourcequota" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/hpa" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/jobs" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/metadata" @@ -104,6 +106,9 @@ func (dc *DataCollector) CollectMetricData(currentTime time.Time) pmetric.Metric dc.metadataStore.ForEach(gvk.ClusterResourceQuota, func(o any) { clusterresourcequota.RecordMetrics(dc.metricsBuilder, o.(*quotav1.ClusterResourceQuota), ts) }) + dc.metadataStore.ForEach(gvk.HierarchicalResourceQuota, func(o any) { + hierarchicalresourcequota.RecordMetrics(dc.metricsBuilder, o.(*unstructured.Unstructured), ts) + }) m := dc.metricsBuilder.Emit() customRMs.MoveAndAppendTo(m.ResourceMetrics()) diff --git a/receiver/k8sclusterreceiver/internal/gvk/gvk.go b/receiver/k8sclusterreceiver/internal/gvk/gvk.go index 58e540821077..8fc587597332 100644 --- a/receiver/k8sclusterreceiver/internal/gvk/gvk.go +++ b/receiver/k8sclusterreceiver/internal/gvk/gvk.go @@ -7,18 +7,19 @@ import "k8s.io/apimachinery/pkg/runtime/schema" // Kubernetes group version kinds var ( - Pod = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"} - Node = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Node"} - Namespace = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Namespace"} - ReplicationController = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "ReplicationController"} - ResourceQuota = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "ResourceQuota"} - Service = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Service"} - DaemonSet = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "DaemonSet"} - Deployment = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"} - ReplicaSet = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "ReplicaSet"} - StatefulSet = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "StatefulSet"} - Job = schema.GroupVersionKind{Group: "batch", Version: "v1", Kind: "Job"} - CronJob = schema.GroupVersionKind{Group: "batch", Version: "v1", Kind: "CronJob"} - HorizontalPodAutoscaler = schema.GroupVersionKind{Group: "autoscaling", Version: "v2", Kind: "HorizontalPodAutoscaler"} - ClusterResourceQuota = schema.GroupVersionKind{Group: "quota", Version: "v1", Kind: "ClusterResourceQuota"} + Pod = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"} + Node = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Node"} + Namespace = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Namespace"} + ReplicationController = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "ReplicationController"} + ResourceQuota = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "ResourceQuota"} + Service = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Service"} + DaemonSet = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "DaemonSet"} + Deployment = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"} + ReplicaSet = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "ReplicaSet"} + StatefulSet = schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "StatefulSet"} + Job = schema.GroupVersionKind{Group: "batch", Version: "v1", Kind: "Job"} + CronJob = schema.GroupVersionKind{Group: "batch", Version: "v1", Kind: "CronJob"} + HorizontalPodAutoscaler = schema.GroupVersionKind{Group: "autoscaling", Version: "v2", Kind: "HorizontalPodAutoscaler"} + ClusterResourceQuota = schema.GroupVersionKind{Group: "quota", Version: "v1", Kind: "ClusterResourceQuota"} + HierarchicalResourceQuota = schema.GroupVersionKind{Group: "hnc.x-k8s.io", Version: "v1alpha2", Kind: "HierarchicalResourceQuota"} ) diff --git a/receiver/k8sclusterreceiver/internal/gvr/gvr.go b/receiver/k8sclusterreceiver/internal/gvr/gvr.go new file mode 100644 index 000000000000..ddfb434f9377 --- /dev/null +++ b/receiver/k8sclusterreceiver/internal/gvr/gvr.go @@ -0,0 +1,11 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package gvr // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/gvr" + +import "k8s.io/apimachinery/pkg/runtime/schema" + +// Kubernetes group version resources +var ( + HierarchicalResourceQuota = schema.GroupVersionResource{Group: "hnc.x-k8s.io", Version: "v1alpha2", Resource: "hierarchicalresourcequotas"} +) diff --git a/receiver/k8sclusterreceiver/internal/hierarchicalresourcequota/hierarchicalresourcequotas.go b/receiver/k8sclusterreceiver/internal/hierarchicalresourcequota/hierarchicalresourcequotas.go new file mode 100644 index 000000000000..5fdb49e79bff --- /dev/null +++ b/receiver/k8sclusterreceiver/internal/hierarchicalresourcequota/hierarchicalresourcequotas.go @@ -0,0 +1,44 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package hierarchicalresourcequota // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/hierarchicalresourcequota" + +import ( + "strings" + + "go.opentelemetry.io/collector/pdata/pcommon" + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + + "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/metadata" +) + +func RecordMetrics(mb *metadata.MetricsBuilder, hrq *unstructured.Unstructured, ts pcommon.Timestamp) { + name, _, _ := unstructured.NestedString(hrq.Object, "metadata", "name") + uid, _, _ := unstructured.NestedString(hrq.Object, "metadata", "uid") + namespace, _, _ := unstructured.NestedString(hrq.Object, "metadata", "namespace") + statusHard, _, _ := unstructured.NestedMap(hrq.Object, "status", "hard") + for k, v := range statusHard { + q := resource.MustParse(v.(string)) + val := q.Value() + if strings.HasSuffix(string(k), ".cpu") { + val = q.MilliValue() + } + mb.RecordK8sHierarchicalResourceQuotaHardLimitDataPoint(ts, val, string(k)) + } + statusUsed, _, _ := unstructured.NestedMap(hrq.Object, "status", "used") + for k, v := range statusUsed { + q := resource.MustParse(v.(string)) + val := q.Value() + if strings.HasSuffix(string(k), ".cpu") { + val = q.MilliValue() + } + mb.RecordK8sHierarchicalResourceQuotaHardLimitDataPoint(ts, val, string(k)) + } + + rb := mb.NewResourceBuilder() + rb.SetK8sHierarchicalresourcequotaUID(string(uid)) + rb.SetK8sHierarchicalresourcequotaName(name) + rb.SetK8sNamespaceName(namespace) + mb.EmitForResource(metadata.WithResource(rb.Emit())) +} diff --git a/receiver/k8sclusterreceiver/internal/hierarchicalresourcequota/hierarchicalresourcequotas_test.go b/receiver/k8sclusterreceiver/internal/hierarchicalresourcequota/hierarchicalresourcequotas_test.go new file mode 100644 index 000000000000..cdba5fbe7795 --- /dev/null +++ b/receiver/k8sclusterreceiver/internal/hierarchicalresourcequota/hierarchicalresourcequotas_test.go @@ -0,0 +1,39 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package hierarchicalresourcequota + +import ( + "path/filepath" + "testing" + "time" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/receiver/receivertest" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + + "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/golden" + "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest/pmetrictest" + "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/metadata" + "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/testutils" +) + +func TestRequestQuotaMetrics(t *testing.T) { + rq := testutils.NewHierachilalResourceQuota("1") + ts := pcommon.Timestamp(time.Now().UnixNano()) + mb := metadata.NewMetricsBuilder(metadata.DefaultMetricsBuilderConfig(), receivertest.NewNopCreateSettings()) + RecordMetrics(mb, rq.(*unstructured.Unstructured), ts) + m := mb.Emit() + + expected, err := golden.ReadMetrics(filepath.Join("testdata", "expected.yaml")) + require.NoError(t, err) + require.NoError(t, pmetrictest.CompareMetrics(expected, m, + pmetrictest.IgnoreTimestamp(), + pmetrictest.IgnoreStartTimestamp(), + pmetrictest.IgnoreResourceMetricsOrder(), + pmetrictest.IgnoreMetricsOrder(), + pmetrictest.IgnoreScopeMetricsOrder(), + ), + ) +} diff --git a/receiver/k8sclusterreceiver/internal/hierarchicalresourcequota/testdata/expected.yaml b/receiver/k8sclusterreceiver/internal/hierarchicalresourcequota/testdata/expected.yaml new file mode 100644 index 000000000000..05f4a14c9500 --- /dev/null +++ b/receiver/k8sclusterreceiver/internal/hierarchicalresourcequota/testdata/expected.yaml @@ -0,0 +1,38 @@ +resourceMetrics: + - resource: + attributes: + - key: k8s.namespace.name + value: + stringValue: test-namespace + - key: k8s.hierarchicalresourcequota.name + value: + stringValue: test-hierarchicalresourcequota-1 + - key: k8s.hierarchicalresourcequota.uid + value: + stringValue: test-hierarchicalresourcequota-1-uid + schemaUrl: https://opentelemetry.io/schemas/1.18.0 + scopeMetrics: + - metrics: + - description: The upper limit for a particular resource in a specific namespace. Will only be sent if a quota is specified. CPU requests/limits will be sent as millicores + gauge: + dataPoints: + - asInt: "2000" + attributes: + - key: resource + value: + stringValue: requests.cpu + name: k8s.hierarchical_resource_quota.hard_limit + unit: "{resource}" + - description: The usage for a particular resource in a specific namespace. Will only be sent if a quota is specified. CPU requests/limits will be sent as millicores + gauge: + dataPoints: + - asInt: "1000" + attributes: + - key: resource + value: + stringValue: requests.cpu + name: k8s.hierarchical_resource_quota.used + unit: "{resource}" + scope: + name: otelcol/k8sclusterreceiver + version: latest diff --git a/receiver/k8sclusterreceiver/internal/metadata/generated_config.go b/receiver/k8sclusterreceiver/internal/metadata/generated_config.go index 163b8b4bbddf..4b8ed338ea9b 100644 --- a/receiver/k8sclusterreceiver/internal/metadata/generated_config.go +++ b/receiver/k8sclusterreceiver/internal/metadata/generated_config.go @@ -25,50 +25,52 @@ func (ms *MetricConfig) Unmarshal(parser *confmap.Conf) error { // MetricsConfig provides config for k8s_cluster metrics. type MetricsConfig struct { - K8sContainerCPULimit MetricConfig `mapstructure:"k8s.container.cpu_limit"` - K8sContainerCPURequest MetricConfig `mapstructure:"k8s.container.cpu_request"` - K8sContainerEphemeralstorageLimit MetricConfig `mapstructure:"k8s.container.ephemeralstorage_limit"` - K8sContainerEphemeralstorageRequest MetricConfig `mapstructure:"k8s.container.ephemeralstorage_request"` - K8sContainerMemoryLimit MetricConfig `mapstructure:"k8s.container.memory_limit"` - K8sContainerMemoryRequest MetricConfig `mapstructure:"k8s.container.memory_request"` - K8sContainerReady MetricConfig `mapstructure:"k8s.container.ready"` - K8sContainerRestarts MetricConfig `mapstructure:"k8s.container.restarts"` - K8sContainerStorageLimit MetricConfig `mapstructure:"k8s.container.storage_limit"` - K8sContainerStorageRequest MetricConfig `mapstructure:"k8s.container.storage_request"` - K8sCronjobActiveJobs MetricConfig `mapstructure:"k8s.cronjob.active_jobs"` - K8sDaemonsetCurrentScheduledNodes MetricConfig `mapstructure:"k8s.daemonset.current_scheduled_nodes"` - K8sDaemonsetDesiredScheduledNodes MetricConfig `mapstructure:"k8s.daemonset.desired_scheduled_nodes"` - K8sDaemonsetMisscheduledNodes MetricConfig `mapstructure:"k8s.daemonset.misscheduled_nodes"` - K8sDaemonsetReadyNodes MetricConfig `mapstructure:"k8s.daemonset.ready_nodes"` - K8sDeploymentAvailable MetricConfig `mapstructure:"k8s.deployment.available"` - K8sDeploymentDesired MetricConfig `mapstructure:"k8s.deployment.desired"` - K8sHpaCurrentReplicas MetricConfig `mapstructure:"k8s.hpa.current_replicas"` - K8sHpaDesiredReplicas MetricConfig `mapstructure:"k8s.hpa.desired_replicas"` - K8sHpaMaxReplicas MetricConfig `mapstructure:"k8s.hpa.max_replicas"` - K8sHpaMinReplicas MetricConfig `mapstructure:"k8s.hpa.min_replicas"` - K8sJobActivePods MetricConfig `mapstructure:"k8s.job.active_pods"` - K8sJobDesiredSuccessfulPods MetricConfig `mapstructure:"k8s.job.desired_successful_pods"` - K8sJobFailedPods MetricConfig `mapstructure:"k8s.job.failed_pods"` - K8sJobMaxParallelPods MetricConfig `mapstructure:"k8s.job.max_parallel_pods"` - K8sJobSuccessfulPods MetricConfig `mapstructure:"k8s.job.successful_pods"` - K8sNamespacePhase MetricConfig `mapstructure:"k8s.namespace.phase"` - K8sNodeCondition MetricConfig `mapstructure:"k8s.node.condition"` - K8sPodPhase MetricConfig `mapstructure:"k8s.pod.phase"` - K8sPodStatusReason MetricConfig `mapstructure:"k8s.pod.status_reason"` - K8sReplicasetAvailable MetricConfig `mapstructure:"k8s.replicaset.available"` - K8sReplicasetDesired MetricConfig `mapstructure:"k8s.replicaset.desired"` - K8sReplicationControllerAvailable MetricConfig `mapstructure:"k8s.replication_controller.available"` - K8sReplicationControllerDesired MetricConfig `mapstructure:"k8s.replication_controller.desired"` - K8sResourceQuotaHardLimit MetricConfig `mapstructure:"k8s.resource_quota.hard_limit"` - K8sResourceQuotaUsed MetricConfig `mapstructure:"k8s.resource_quota.used"` - K8sStatefulsetCurrentPods MetricConfig `mapstructure:"k8s.statefulset.current_pods"` - K8sStatefulsetDesiredPods MetricConfig `mapstructure:"k8s.statefulset.desired_pods"` - K8sStatefulsetReadyPods MetricConfig `mapstructure:"k8s.statefulset.ready_pods"` - K8sStatefulsetUpdatedPods MetricConfig `mapstructure:"k8s.statefulset.updated_pods"` - OpenshiftAppliedclusterquotaLimit MetricConfig `mapstructure:"openshift.appliedclusterquota.limit"` - OpenshiftAppliedclusterquotaUsed MetricConfig `mapstructure:"openshift.appliedclusterquota.used"` - OpenshiftClusterquotaLimit MetricConfig `mapstructure:"openshift.clusterquota.limit"` - OpenshiftClusterquotaUsed MetricConfig `mapstructure:"openshift.clusterquota.used"` + K8sContainerCPULimit MetricConfig `mapstructure:"k8s.container.cpu_limit"` + K8sContainerCPURequest MetricConfig `mapstructure:"k8s.container.cpu_request"` + K8sContainerEphemeralstorageLimit MetricConfig `mapstructure:"k8s.container.ephemeralstorage_limit"` + K8sContainerEphemeralstorageRequest MetricConfig `mapstructure:"k8s.container.ephemeralstorage_request"` + K8sContainerMemoryLimit MetricConfig `mapstructure:"k8s.container.memory_limit"` + K8sContainerMemoryRequest MetricConfig `mapstructure:"k8s.container.memory_request"` + K8sContainerReady MetricConfig `mapstructure:"k8s.container.ready"` + K8sContainerRestarts MetricConfig `mapstructure:"k8s.container.restarts"` + K8sContainerStorageLimit MetricConfig `mapstructure:"k8s.container.storage_limit"` + K8sContainerStorageRequest MetricConfig `mapstructure:"k8s.container.storage_request"` + K8sCronjobActiveJobs MetricConfig `mapstructure:"k8s.cronjob.active_jobs"` + K8sDaemonsetCurrentScheduledNodes MetricConfig `mapstructure:"k8s.daemonset.current_scheduled_nodes"` + K8sDaemonsetDesiredScheduledNodes MetricConfig `mapstructure:"k8s.daemonset.desired_scheduled_nodes"` + K8sDaemonsetMisscheduledNodes MetricConfig `mapstructure:"k8s.daemonset.misscheduled_nodes"` + K8sDaemonsetReadyNodes MetricConfig `mapstructure:"k8s.daemonset.ready_nodes"` + K8sDeploymentAvailable MetricConfig `mapstructure:"k8s.deployment.available"` + K8sDeploymentDesired MetricConfig `mapstructure:"k8s.deployment.desired"` + K8sHierarchicalResourceQuotaHardLimit MetricConfig `mapstructure:"k8s.hierarchical_resource_quota.hard_limit"` + K8sHierarchicalResourceQuotaUsed MetricConfig `mapstructure:"k8s.hierarchical_resource_quota.used"` + K8sHpaCurrentReplicas MetricConfig `mapstructure:"k8s.hpa.current_replicas"` + K8sHpaDesiredReplicas MetricConfig `mapstructure:"k8s.hpa.desired_replicas"` + K8sHpaMaxReplicas MetricConfig `mapstructure:"k8s.hpa.max_replicas"` + K8sHpaMinReplicas MetricConfig `mapstructure:"k8s.hpa.min_replicas"` + K8sJobActivePods MetricConfig `mapstructure:"k8s.job.active_pods"` + K8sJobDesiredSuccessfulPods MetricConfig `mapstructure:"k8s.job.desired_successful_pods"` + K8sJobFailedPods MetricConfig `mapstructure:"k8s.job.failed_pods"` + K8sJobMaxParallelPods MetricConfig `mapstructure:"k8s.job.max_parallel_pods"` + K8sJobSuccessfulPods MetricConfig `mapstructure:"k8s.job.successful_pods"` + K8sNamespacePhase MetricConfig `mapstructure:"k8s.namespace.phase"` + K8sNodeCondition MetricConfig `mapstructure:"k8s.node.condition"` + K8sPodPhase MetricConfig `mapstructure:"k8s.pod.phase"` + K8sPodStatusReason MetricConfig `mapstructure:"k8s.pod.status_reason"` + K8sReplicasetAvailable MetricConfig `mapstructure:"k8s.replicaset.available"` + K8sReplicasetDesired MetricConfig `mapstructure:"k8s.replicaset.desired"` + K8sReplicationControllerAvailable MetricConfig `mapstructure:"k8s.replication_controller.available"` + K8sReplicationControllerDesired MetricConfig `mapstructure:"k8s.replication_controller.desired"` + K8sResourceQuotaHardLimit MetricConfig `mapstructure:"k8s.resource_quota.hard_limit"` + K8sResourceQuotaUsed MetricConfig `mapstructure:"k8s.resource_quota.used"` + K8sStatefulsetCurrentPods MetricConfig `mapstructure:"k8s.statefulset.current_pods"` + K8sStatefulsetDesiredPods MetricConfig `mapstructure:"k8s.statefulset.desired_pods"` + K8sStatefulsetReadyPods MetricConfig `mapstructure:"k8s.statefulset.ready_pods"` + K8sStatefulsetUpdatedPods MetricConfig `mapstructure:"k8s.statefulset.updated_pods"` + OpenshiftAppliedclusterquotaLimit MetricConfig `mapstructure:"openshift.appliedclusterquota.limit"` + OpenshiftAppliedclusterquotaUsed MetricConfig `mapstructure:"openshift.appliedclusterquota.used"` + OpenshiftClusterquotaLimit MetricConfig `mapstructure:"openshift.clusterquota.limit"` + OpenshiftClusterquotaUsed MetricConfig `mapstructure:"openshift.clusterquota.used"` } func DefaultMetricsConfig() MetricsConfig { @@ -124,6 +126,12 @@ func DefaultMetricsConfig() MetricsConfig { K8sDeploymentDesired: MetricConfig{ Enabled: true, }, + K8sHierarchicalResourceQuotaHardLimit: MetricConfig{ + Enabled: true, + }, + K8sHierarchicalResourceQuotaUsed: MetricConfig{ + Enabled: true, + }, K8sHpaCurrentReplicas: MetricConfig{ Enabled: true, }, @@ -229,39 +237,41 @@ func (rac *ResourceAttributeConfig) Unmarshal(parser *confmap.Conf) error { // ResourceAttributesConfig provides config for k8s_cluster resource attributes. type ResourceAttributesConfig struct { - ContainerID ResourceAttributeConfig `mapstructure:"container.id"` - ContainerImageName ResourceAttributeConfig `mapstructure:"container.image.name"` - ContainerImageTag ResourceAttributeConfig `mapstructure:"container.image.tag"` - K8sContainerName ResourceAttributeConfig `mapstructure:"k8s.container.name"` - K8sCronjobName ResourceAttributeConfig `mapstructure:"k8s.cronjob.name"` - K8sCronjobUID ResourceAttributeConfig `mapstructure:"k8s.cronjob.uid"` - K8sDaemonsetName ResourceAttributeConfig `mapstructure:"k8s.daemonset.name"` - K8sDaemonsetUID ResourceAttributeConfig `mapstructure:"k8s.daemonset.uid"` - K8sDeploymentName ResourceAttributeConfig `mapstructure:"k8s.deployment.name"` - K8sDeploymentUID ResourceAttributeConfig `mapstructure:"k8s.deployment.uid"` - K8sHpaName ResourceAttributeConfig `mapstructure:"k8s.hpa.name"` - K8sHpaUID ResourceAttributeConfig `mapstructure:"k8s.hpa.uid"` - K8sJobName ResourceAttributeConfig `mapstructure:"k8s.job.name"` - K8sJobUID ResourceAttributeConfig `mapstructure:"k8s.job.uid"` - K8sKubeletVersion ResourceAttributeConfig `mapstructure:"k8s.kubelet.version"` - K8sKubeproxyVersion ResourceAttributeConfig `mapstructure:"k8s.kubeproxy.version"` - K8sNamespaceName ResourceAttributeConfig `mapstructure:"k8s.namespace.name"` - K8sNamespaceUID ResourceAttributeConfig `mapstructure:"k8s.namespace.uid"` - K8sNodeName ResourceAttributeConfig `mapstructure:"k8s.node.name"` - K8sNodeUID ResourceAttributeConfig `mapstructure:"k8s.node.uid"` - K8sPodName ResourceAttributeConfig `mapstructure:"k8s.pod.name"` - K8sPodQosClass ResourceAttributeConfig `mapstructure:"k8s.pod.qos_class"` - K8sPodUID ResourceAttributeConfig `mapstructure:"k8s.pod.uid"` - K8sReplicasetName ResourceAttributeConfig `mapstructure:"k8s.replicaset.name"` - K8sReplicasetUID ResourceAttributeConfig `mapstructure:"k8s.replicaset.uid"` - K8sReplicationcontrollerName ResourceAttributeConfig `mapstructure:"k8s.replicationcontroller.name"` - K8sReplicationcontrollerUID ResourceAttributeConfig `mapstructure:"k8s.replicationcontroller.uid"` - K8sResourcequotaName ResourceAttributeConfig `mapstructure:"k8s.resourcequota.name"` - K8sResourcequotaUID ResourceAttributeConfig `mapstructure:"k8s.resourcequota.uid"` - K8sStatefulsetName ResourceAttributeConfig `mapstructure:"k8s.statefulset.name"` - K8sStatefulsetUID ResourceAttributeConfig `mapstructure:"k8s.statefulset.uid"` - OpenshiftClusterquotaName ResourceAttributeConfig `mapstructure:"openshift.clusterquota.name"` - OpenshiftClusterquotaUID ResourceAttributeConfig `mapstructure:"openshift.clusterquota.uid"` + ContainerID ResourceAttributeConfig `mapstructure:"container.id"` + ContainerImageName ResourceAttributeConfig `mapstructure:"container.image.name"` + ContainerImageTag ResourceAttributeConfig `mapstructure:"container.image.tag"` + K8sContainerName ResourceAttributeConfig `mapstructure:"k8s.container.name"` + K8sCronjobName ResourceAttributeConfig `mapstructure:"k8s.cronjob.name"` + K8sCronjobUID ResourceAttributeConfig `mapstructure:"k8s.cronjob.uid"` + K8sDaemonsetName ResourceAttributeConfig `mapstructure:"k8s.daemonset.name"` + K8sDaemonsetUID ResourceAttributeConfig `mapstructure:"k8s.daemonset.uid"` + K8sDeploymentName ResourceAttributeConfig `mapstructure:"k8s.deployment.name"` + K8sDeploymentUID ResourceAttributeConfig `mapstructure:"k8s.deployment.uid"` + K8sHierarchicalresourcequotaName ResourceAttributeConfig `mapstructure:"k8s.hierarchicalresourcequota.name"` + K8sHierarchicalresourcequotaUID ResourceAttributeConfig `mapstructure:"k8s.hierarchicalresourcequota.uid"` + K8sHpaName ResourceAttributeConfig `mapstructure:"k8s.hpa.name"` + K8sHpaUID ResourceAttributeConfig `mapstructure:"k8s.hpa.uid"` + K8sJobName ResourceAttributeConfig `mapstructure:"k8s.job.name"` + K8sJobUID ResourceAttributeConfig `mapstructure:"k8s.job.uid"` + K8sKubeletVersion ResourceAttributeConfig `mapstructure:"k8s.kubelet.version"` + K8sKubeproxyVersion ResourceAttributeConfig `mapstructure:"k8s.kubeproxy.version"` + K8sNamespaceName ResourceAttributeConfig `mapstructure:"k8s.namespace.name"` + K8sNamespaceUID ResourceAttributeConfig `mapstructure:"k8s.namespace.uid"` + K8sNodeName ResourceAttributeConfig `mapstructure:"k8s.node.name"` + K8sNodeUID ResourceAttributeConfig `mapstructure:"k8s.node.uid"` + K8sPodName ResourceAttributeConfig `mapstructure:"k8s.pod.name"` + K8sPodQosClass ResourceAttributeConfig `mapstructure:"k8s.pod.qos_class"` + K8sPodUID ResourceAttributeConfig `mapstructure:"k8s.pod.uid"` + K8sReplicasetName ResourceAttributeConfig `mapstructure:"k8s.replicaset.name"` + K8sReplicasetUID ResourceAttributeConfig `mapstructure:"k8s.replicaset.uid"` + K8sReplicationcontrollerName ResourceAttributeConfig `mapstructure:"k8s.replicationcontroller.name"` + K8sReplicationcontrollerUID ResourceAttributeConfig `mapstructure:"k8s.replicationcontroller.uid"` + K8sResourcequotaName ResourceAttributeConfig `mapstructure:"k8s.resourcequota.name"` + K8sResourcequotaUID ResourceAttributeConfig `mapstructure:"k8s.resourcequota.uid"` + K8sStatefulsetName ResourceAttributeConfig `mapstructure:"k8s.statefulset.name"` + K8sStatefulsetUID ResourceAttributeConfig `mapstructure:"k8s.statefulset.uid"` + OpenshiftClusterquotaName ResourceAttributeConfig `mapstructure:"openshift.clusterquota.name"` + OpenshiftClusterquotaUID ResourceAttributeConfig `mapstructure:"openshift.clusterquota.uid"` } func DefaultResourceAttributesConfig() ResourceAttributesConfig { @@ -296,6 +306,12 @@ func DefaultResourceAttributesConfig() ResourceAttributesConfig { K8sDeploymentUID: ResourceAttributeConfig{ Enabled: true, }, + K8sHierarchicalresourcequotaName: ResourceAttributeConfig{ + Enabled: true, + }, + K8sHierarchicalresourcequotaUID: ResourceAttributeConfig{ + Enabled: true, + }, K8sHpaName: ResourceAttributeConfig{ Enabled: true, }, diff --git a/receiver/k8sclusterreceiver/internal/metadata/generated_config_test.go b/receiver/k8sclusterreceiver/internal/metadata/generated_config_test.go index c6178f76878c..7430f0b2b7f8 100644 --- a/receiver/k8sclusterreceiver/internal/metadata/generated_config_test.go +++ b/receiver/k8sclusterreceiver/internal/metadata/generated_config_test.go @@ -26,85 +26,89 @@ func TestMetricsBuilderConfig(t *testing.T) { name: "all_set", want: MetricsBuilderConfig{ Metrics: MetricsConfig{ - K8sContainerCPULimit: MetricConfig{Enabled: true}, - K8sContainerCPURequest: MetricConfig{Enabled: true}, - K8sContainerEphemeralstorageLimit: MetricConfig{Enabled: true}, - K8sContainerEphemeralstorageRequest: MetricConfig{Enabled: true}, - K8sContainerMemoryLimit: MetricConfig{Enabled: true}, - K8sContainerMemoryRequest: MetricConfig{Enabled: true}, - K8sContainerReady: MetricConfig{Enabled: true}, - K8sContainerRestarts: MetricConfig{Enabled: true}, - K8sContainerStorageLimit: MetricConfig{Enabled: true}, - K8sContainerStorageRequest: MetricConfig{Enabled: true}, - K8sCronjobActiveJobs: MetricConfig{Enabled: true}, - K8sDaemonsetCurrentScheduledNodes: MetricConfig{Enabled: true}, - K8sDaemonsetDesiredScheduledNodes: MetricConfig{Enabled: true}, - K8sDaemonsetMisscheduledNodes: MetricConfig{Enabled: true}, - K8sDaemonsetReadyNodes: MetricConfig{Enabled: true}, - K8sDeploymentAvailable: MetricConfig{Enabled: true}, - K8sDeploymentDesired: MetricConfig{Enabled: true}, - K8sHpaCurrentReplicas: MetricConfig{Enabled: true}, - K8sHpaDesiredReplicas: MetricConfig{Enabled: true}, - K8sHpaMaxReplicas: MetricConfig{Enabled: true}, - K8sHpaMinReplicas: MetricConfig{Enabled: true}, - K8sJobActivePods: MetricConfig{Enabled: true}, - K8sJobDesiredSuccessfulPods: MetricConfig{Enabled: true}, - K8sJobFailedPods: MetricConfig{Enabled: true}, - K8sJobMaxParallelPods: MetricConfig{Enabled: true}, - K8sJobSuccessfulPods: MetricConfig{Enabled: true}, - K8sNamespacePhase: MetricConfig{Enabled: true}, - K8sNodeCondition: MetricConfig{Enabled: true}, - K8sPodPhase: MetricConfig{Enabled: true}, - K8sPodStatusReason: MetricConfig{Enabled: true}, - K8sReplicasetAvailable: MetricConfig{Enabled: true}, - K8sReplicasetDesired: MetricConfig{Enabled: true}, - K8sReplicationControllerAvailable: MetricConfig{Enabled: true}, - K8sReplicationControllerDesired: MetricConfig{Enabled: true}, - K8sResourceQuotaHardLimit: MetricConfig{Enabled: true}, - K8sResourceQuotaUsed: MetricConfig{Enabled: true}, - K8sStatefulsetCurrentPods: MetricConfig{Enabled: true}, - K8sStatefulsetDesiredPods: MetricConfig{Enabled: true}, - K8sStatefulsetReadyPods: MetricConfig{Enabled: true}, - K8sStatefulsetUpdatedPods: MetricConfig{Enabled: true}, - OpenshiftAppliedclusterquotaLimit: MetricConfig{Enabled: true}, - OpenshiftAppliedclusterquotaUsed: MetricConfig{Enabled: true}, - OpenshiftClusterquotaLimit: MetricConfig{Enabled: true}, - OpenshiftClusterquotaUsed: MetricConfig{Enabled: true}, + K8sContainerCPULimit: MetricConfig{Enabled: true}, + K8sContainerCPURequest: MetricConfig{Enabled: true}, + K8sContainerEphemeralstorageLimit: MetricConfig{Enabled: true}, + K8sContainerEphemeralstorageRequest: MetricConfig{Enabled: true}, + K8sContainerMemoryLimit: MetricConfig{Enabled: true}, + K8sContainerMemoryRequest: MetricConfig{Enabled: true}, + K8sContainerReady: MetricConfig{Enabled: true}, + K8sContainerRestarts: MetricConfig{Enabled: true}, + K8sContainerStorageLimit: MetricConfig{Enabled: true}, + K8sContainerStorageRequest: MetricConfig{Enabled: true}, + K8sCronjobActiveJobs: MetricConfig{Enabled: true}, + K8sDaemonsetCurrentScheduledNodes: MetricConfig{Enabled: true}, + K8sDaemonsetDesiredScheduledNodes: MetricConfig{Enabled: true}, + K8sDaemonsetMisscheduledNodes: MetricConfig{Enabled: true}, + K8sDaemonsetReadyNodes: MetricConfig{Enabled: true}, + K8sDeploymentAvailable: MetricConfig{Enabled: true}, + K8sDeploymentDesired: MetricConfig{Enabled: true}, + K8sHierarchicalResourceQuotaHardLimit: MetricConfig{Enabled: true}, + K8sHierarchicalResourceQuotaUsed: MetricConfig{Enabled: true}, + K8sHpaCurrentReplicas: MetricConfig{Enabled: true}, + K8sHpaDesiredReplicas: MetricConfig{Enabled: true}, + K8sHpaMaxReplicas: MetricConfig{Enabled: true}, + K8sHpaMinReplicas: MetricConfig{Enabled: true}, + K8sJobActivePods: MetricConfig{Enabled: true}, + K8sJobDesiredSuccessfulPods: MetricConfig{Enabled: true}, + K8sJobFailedPods: MetricConfig{Enabled: true}, + K8sJobMaxParallelPods: MetricConfig{Enabled: true}, + K8sJobSuccessfulPods: MetricConfig{Enabled: true}, + K8sNamespacePhase: MetricConfig{Enabled: true}, + K8sNodeCondition: MetricConfig{Enabled: true}, + K8sPodPhase: MetricConfig{Enabled: true}, + K8sPodStatusReason: MetricConfig{Enabled: true}, + K8sReplicasetAvailable: MetricConfig{Enabled: true}, + K8sReplicasetDesired: MetricConfig{Enabled: true}, + K8sReplicationControllerAvailable: MetricConfig{Enabled: true}, + K8sReplicationControllerDesired: MetricConfig{Enabled: true}, + K8sResourceQuotaHardLimit: MetricConfig{Enabled: true}, + K8sResourceQuotaUsed: MetricConfig{Enabled: true}, + K8sStatefulsetCurrentPods: MetricConfig{Enabled: true}, + K8sStatefulsetDesiredPods: MetricConfig{Enabled: true}, + K8sStatefulsetReadyPods: MetricConfig{Enabled: true}, + K8sStatefulsetUpdatedPods: MetricConfig{Enabled: true}, + OpenshiftAppliedclusterquotaLimit: MetricConfig{Enabled: true}, + OpenshiftAppliedclusterquotaUsed: MetricConfig{Enabled: true}, + OpenshiftClusterquotaLimit: MetricConfig{Enabled: true}, + OpenshiftClusterquotaUsed: MetricConfig{Enabled: true}, }, ResourceAttributes: ResourceAttributesConfig{ - ContainerID: ResourceAttributeConfig{Enabled: true}, - ContainerImageName: ResourceAttributeConfig{Enabled: true}, - ContainerImageTag: ResourceAttributeConfig{Enabled: true}, - K8sContainerName: ResourceAttributeConfig{Enabled: true}, - K8sCronjobName: ResourceAttributeConfig{Enabled: true}, - K8sCronjobUID: ResourceAttributeConfig{Enabled: true}, - K8sDaemonsetName: ResourceAttributeConfig{Enabled: true}, - K8sDaemonsetUID: ResourceAttributeConfig{Enabled: true}, - K8sDeploymentName: ResourceAttributeConfig{Enabled: true}, - K8sDeploymentUID: ResourceAttributeConfig{Enabled: true}, - K8sHpaName: ResourceAttributeConfig{Enabled: true}, - K8sHpaUID: ResourceAttributeConfig{Enabled: true}, - K8sJobName: ResourceAttributeConfig{Enabled: true}, - K8sJobUID: ResourceAttributeConfig{Enabled: true}, - K8sKubeletVersion: ResourceAttributeConfig{Enabled: true}, - K8sKubeproxyVersion: ResourceAttributeConfig{Enabled: true}, - K8sNamespaceName: ResourceAttributeConfig{Enabled: true}, - K8sNamespaceUID: ResourceAttributeConfig{Enabled: true}, - K8sNodeName: ResourceAttributeConfig{Enabled: true}, - K8sNodeUID: ResourceAttributeConfig{Enabled: true}, - K8sPodName: ResourceAttributeConfig{Enabled: true}, - K8sPodQosClass: ResourceAttributeConfig{Enabled: true}, - K8sPodUID: ResourceAttributeConfig{Enabled: true}, - K8sReplicasetName: ResourceAttributeConfig{Enabled: true}, - K8sReplicasetUID: ResourceAttributeConfig{Enabled: true}, - K8sReplicationcontrollerName: ResourceAttributeConfig{Enabled: true}, - K8sReplicationcontrollerUID: ResourceAttributeConfig{Enabled: true}, - K8sResourcequotaName: ResourceAttributeConfig{Enabled: true}, - K8sResourcequotaUID: ResourceAttributeConfig{Enabled: true}, - K8sStatefulsetName: ResourceAttributeConfig{Enabled: true}, - K8sStatefulsetUID: ResourceAttributeConfig{Enabled: true}, - OpenshiftClusterquotaName: ResourceAttributeConfig{Enabled: true}, - OpenshiftClusterquotaUID: ResourceAttributeConfig{Enabled: true}, + ContainerID: ResourceAttributeConfig{Enabled: true}, + ContainerImageName: ResourceAttributeConfig{Enabled: true}, + ContainerImageTag: ResourceAttributeConfig{Enabled: true}, + K8sContainerName: ResourceAttributeConfig{Enabled: true}, + K8sCronjobName: ResourceAttributeConfig{Enabled: true}, + K8sCronjobUID: ResourceAttributeConfig{Enabled: true}, + K8sDaemonsetName: ResourceAttributeConfig{Enabled: true}, + K8sDaemonsetUID: ResourceAttributeConfig{Enabled: true}, + K8sDeploymentName: ResourceAttributeConfig{Enabled: true}, + K8sDeploymentUID: ResourceAttributeConfig{Enabled: true}, + K8sHierarchicalresourcequotaName: ResourceAttributeConfig{Enabled: true}, + K8sHierarchicalresourcequotaUID: ResourceAttributeConfig{Enabled: true}, + K8sHpaName: ResourceAttributeConfig{Enabled: true}, + K8sHpaUID: ResourceAttributeConfig{Enabled: true}, + K8sJobName: ResourceAttributeConfig{Enabled: true}, + K8sJobUID: ResourceAttributeConfig{Enabled: true}, + K8sKubeletVersion: ResourceAttributeConfig{Enabled: true}, + K8sKubeproxyVersion: ResourceAttributeConfig{Enabled: true}, + K8sNamespaceName: ResourceAttributeConfig{Enabled: true}, + K8sNamespaceUID: ResourceAttributeConfig{Enabled: true}, + K8sNodeName: ResourceAttributeConfig{Enabled: true}, + K8sNodeUID: ResourceAttributeConfig{Enabled: true}, + K8sPodName: ResourceAttributeConfig{Enabled: true}, + K8sPodQosClass: ResourceAttributeConfig{Enabled: true}, + K8sPodUID: ResourceAttributeConfig{Enabled: true}, + K8sReplicasetName: ResourceAttributeConfig{Enabled: true}, + K8sReplicasetUID: ResourceAttributeConfig{Enabled: true}, + K8sReplicationcontrollerName: ResourceAttributeConfig{Enabled: true}, + K8sReplicationcontrollerUID: ResourceAttributeConfig{Enabled: true}, + K8sResourcequotaName: ResourceAttributeConfig{Enabled: true}, + K8sResourcequotaUID: ResourceAttributeConfig{Enabled: true}, + K8sStatefulsetName: ResourceAttributeConfig{Enabled: true}, + K8sStatefulsetUID: ResourceAttributeConfig{Enabled: true}, + OpenshiftClusterquotaName: ResourceAttributeConfig{Enabled: true}, + OpenshiftClusterquotaUID: ResourceAttributeConfig{Enabled: true}, }, }, }, @@ -112,85 +116,89 @@ func TestMetricsBuilderConfig(t *testing.T) { name: "none_set", want: MetricsBuilderConfig{ Metrics: MetricsConfig{ - K8sContainerCPULimit: MetricConfig{Enabled: false}, - K8sContainerCPURequest: MetricConfig{Enabled: false}, - K8sContainerEphemeralstorageLimit: MetricConfig{Enabled: false}, - K8sContainerEphemeralstorageRequest: MetricConfig{Enabled: false}, - K8sContainerMemoryLimit: MetricConfig{Enabled: false}, - K8sContainerMemoryRequest: MetricConfig{Enabled: false}, - K8sContainerReady: MetricConfig{Enabled: false}, - K8sContainerRestarts: MetricConfig{Enabled: false}, - K8sContainerStorageLimit: MetricConfig{Enabled: false}, - K8sContainerStorageRequest: MetricConfig{Enabled: false}, - K8sCronjobActiveJobs: MetricConfig{Enabled: false}, - K8sDaemonsetCurrentScheduledNodes: MetricConfig{Enabled: false}, - K8sDaemonsetDesiredScheduledNodes: MetricConfig{Enabled: false}, - K8sDaemonsetMisscheduledNodes: MetricConfig{Enabled: false}, - K8sDaemonsetReadyNodes: MetricConfig{Enabled: false}, - K8sDeploymentAvailable: MetricConfig{Enabled: false}, - K8sDeploymentDesired: MetricConfig{Enabled: false}, - K8sHpaCurrentReplicas: MetricConfig{Enabled: false}, - K8sHpaDesiredReplicas: MetricConfig{Enabled: false}, - K8sHpaMaxReplicas: MetricConfig{Enabled: false}, - K8sHpaMinReplicas: MetricConfig{Enabled: false}, - K8sJobActivePods: MetricConfig{Enabled: false}, - K8sJobDesiredSuccessfulPods: MetricConfig{Enabled: false}, - K8sJobFailedPods: MetricConfig{Enabled: false}, - K8sJobMaxParallelPods: MetricConfig{Enabled: false}, - K8sJobSuccessfulPods: MetricConfig{Enabled: false}, - K8sNamespacePhase: MetricConfig{Enabled: false}, - K8sNodeCondition: MetricConfig{Enabled: false}, - K8sPodPhase: MetricConfig{Enabled: false}, - K8sPodStatusReason: MetricConfig{Enabled: false}, - K8sReplicasetAvailable: MetricConfig{Enabled: false}, - K8sReplicasetDesired: MetricConfig{Enabled: false}, - K8sReplicationControllerAvailable: MetricConfig{Enabled: false}, - K8sReplicationControllerDesired: MetricConfig{Enabled: false}, - K8sResourceQuotaHardLimit: MetricConfig{Enabled: false}, - K8sResourceQuotaUsed: MetricConfig{Enabled: false}, - K8sStatefulsetCurrentPods: MetricConfig{Enabled: false}, - K8sStatefulsetDesiredPods: MetricConfig{Enabled: false}, - K8sStatefulsetReadyPods: MetricConfig{Enabled: false}, - K8sStatefulsetUpdatedPods: MetricConfig{Enabled: false}, - OpenshiftAppliedclusterquotaLimit: MetricConfig{Enabled: false}, - OpenshiftAppliedclusterquotaUsed: MetricConfig{Enabled: false}, - OpenshiftClusterquotaLimit: MetricConfig{Enabled: false}, - OpenshiftClusterquotaUsed: MetricConfig{Enabled: false}, + K8sContainerCPULimit: MetricConfig{Enabled: false}, + K8sContainerCPURequest: MetricConfig{Enabled: false}, + K8sContainerEphemeralstorageLimit: MetricConfig{Enabled: false}, + K8sContainerEphemeralstorageRequest: MetricConfig{Enabled: false}, + K8sContainerMemoryLimit: MetricConfig{Enabled: false}, + K8sContainerMemoryRequest: MetricConfig{Enabled: false}, + K8sContainerReady: MetricConfig{Enabled: false}, + K8sContainerRestarts: MetricConfig{Enabled: false}, + K8sContainerStorageLimit: MetricConfig{Enabled: false}, + K8sContainerStorageRequest: MetricConfig{Enabled: false}, + K8sCronjobActiveJobs: MetricConfig{Enabled: false}, + K8sDaemonsetCurrentScheduledNodes: MetricConfig{Enabled: false}, + K8sDaemonsetDesiredScheduledNodes: MetricConfig{Enabled: false}, + K8sDaemonsetMisscheduledNodes: MetricConfig{Enabled: false}, + K8sDaemonsetReadyNodes: MetricConfig{Enabled: false}, + K8sDeploymentAvailable: MetricConfig{Enabled: false}, + K8sDeploymentDesired: MetricConfig{Enabled: false}, + K8sHierarchicalResourceQuotaHardLimit: MetricConfig{Enabled: false}, + K8sHierarchicalResourceQuotaUsed: MetricConfig{Enabled: false}, + K8sHpaCurrentReplicas: MetricConfig{Enabled: false}, + K8sHpaDesiredReplicas: MetricConfig{Enabled: false}, + K8sHpaMaxReplicas: MetricConfig{Enabled: false}, + K8sHpaMinReplicas: MetricConfig{Enabled: false}, + K8sJobActivePods: MetricConfig{Enabled: false}, + K8sJobDesiredSuccessfulPods: MetricConfig{Enabled: false}, + K8sJobFailedPods: MetricConfig{Enabled: false}, + K8sJobMaxParallelPods: MetricConfig{Enabled: false}, + K8sJobSuccessfulPods: MetricConfig{Enabled: false}, + K8sNamespacePhase: MetricConfig{Enabled: false}, + K8sNodeCondition: MetricConfig{Enabled: false}, + K8sPodPhase: MetricConfig{Enabled: false}, + K8sPodStatusReason: MetricConfig{Enabled: false}, + K8sReplicasetAvailable: MetricConfig{Enabled: false}, + K8sReplicasetDesired: MetricConfig{Enabled: false}, + K8sReplicationControllerAvailable: MetricConfig{Enabled: false}, + K8sReplicationControllerDesired: MetricConfig{Enabled: false}, + K8sResourceQuotaHardLimit: MetricConfig{Enabled: false}, + K8sResourceQuotaUsed: MetricConfig{Enabled: false}, + K8sStatefulsetCurrentPods: MetricConfig{Enabled: false}, + K8sStatefulsetDesiredPods: MetricConfig{Enabled: false}, + K8sStatefulsetReadyPods: MetricConfig{Enabled: false}, + K8sStatefulsetUpdatedPods: MetricConfig{Enabled: false}, + OpenshiftAppliedclusterquotaLimit: MetricConfig{Enabled: false}, + OpenshiftAppliedclusterquotaUsed: MetricConfig{Enabled: false}, + OpenshiftClusterquotaLimit: MetricConfig{Enabled: false}, + OpenshiftClusterquotaUsed: MetricConfig{Enabled: false}, }, ResourceAttributes: ResourceAttributesConfig{ - ContainerID: ResourceAttributeConfig{Enabled: false}, - ContainerImageName: ResourceAttributeConfig{Enabled: false}, - ContainerImageTag: ResourceAttributeConfig{Enabled: false}, - K8sContainerName: ResourceAttributeConfig{Enabled: false}, - K8sCronjobName: ResourceAttributeConfig{Enabled: false}, - K8sCronjobUID: ResourceAttributeConfig{Enabled: false}, - K8sDaemonsetName: ResourceAttributeConfig{Enabled: false}, - K8sDaemonsetUID: ResourceAttributeConfig{Enabled: false}, - K8sDeploymentName: ResourceAttributeConfig{Enabled: false}, - K8sDeploymentUID: ResourceAttributeConfig{Enabled: false}, - K8sHpaName: ResourceAttributeConfig{Enabled: false}, - K8sHpaUID: ResourceAttributeConfig{Enabled: false}, - K8sJobName: ResourceAttributeConfig{Enabled: false}, - K8sJobUID: ResourceAttributeConfig{Enabled: false}, - K8sKubeletVersion: ResourceAttributeConfig{Enabled: false}, - K8sKubeproxyVersion: ResourceAttributeConfig{Enabled: false}, - K8sNamespaceName: ResourceAttributeConfig{Enabled: false}, - K8sNamespaceUID: ResourceAttributeConfig{Enabled: false}, - K8sNodeName: ResourceAttributeConfig{Enabled: false}, - K8sNodeUID: ResourceAttributeConfig{Enabled: false}, - K8sPodName: ResourceAttributeConfig{Enabled: false}, - K8sPodQosClass: ResourceAttributeConfig{Enabled: false}, - K8sPodUID: ResourceAttributeConfig{Enabled: false}, - K8sReplicasetName: ResourceAttributeConfig{Enabled: false}, - K8sReplicasetUID: ResourceAttributeConfig{Enabled: false}, - K8sReplicationcontrollerName: ResourceAttributeConfig{Enabled: false}, - K8sReplicationcontrollerUID: ResourceAttributeConfig{Enabled: false}, - K8sResourcequotaName: ResourceAttributeConfig{Enabled: false}, - K8sResourcequotaUID: ResourceAttributeConfig{Enabled: false}, - K8sStatefulsetName: ResourceAttributeConfig{Enabled: false}, - K8sStatefulsetUID: ResourceAttributeConfig{Enabled: false}, - OpenshiftClusterquotaName: ResourceAttributeConfig{Enabled: false}, - OpenshiftClusterquotaUID: ResourceAttributeConfig{Enabled: false}, + ContainerID: ResourceAttributeConfig{Enabled: false}, + ContainerImageName: ResourceAttributeConfig{Enabled: false}, + ContainerImageTag: ResourceAttributeConfig{Enabled: false}, + K8sContainerName: ResourceAttributeConfig{Enabled: false}, + K8sCronjobName: ResourceAttributeConfig{Enabled: false}, + K8sCronjobUID: ResourceAttributeConfig{Enabled: false}, + K8sDaemonsetName: ResourceAttributeConfig{Enabled: false}, + K8sDaemonsetUID: ResourceAttributeConfig{Enabled: false}, + K8sDeploymentName: ResourceAttributeConfig{Enabled: false}, + K8sDeploymentUID: ResourceAttributeConfig{Enabled: false}, + K8sHierarchicalresourcequotaName: ResourceAttributeConfig{Enabled: false}, + K8sHierarchicalresourcequotaUID: ResourceAttributeConfig{Enabled: false}, + K8sHpaName: ResourceAttributeConfig{Enabled: false}, + K8sHpaUID: ResourceAttributeConfig{Enabled: false}, + K8sJobName: ResourceAttributeConfig{Enabled: false}, + K8sJobUID: ResourceAttributeConfig{Enabled: false}, + K8sKubeletVersion: ResourceAttributeConfig{Enabled: false}, + K8sKubeproxyVersion: ResourceAttributeConfig{Enabled: false}, + K8sNamespaceName: ResourceAttributeConfig{Enabled: false}, + K8sNamespaceUID: ResourceAttributeConfig{Enabled: false}, + K8sNodeName: ResourceAttributeConfig{Enabled: false}, + K8sNodeUID: ResourceAttributeConfig{Enabled: false}, + K8sPodName: ResourceAttributeConfig{Enabled: false}, + K8sPodQosClass: ResourceAttributeConfig{Enabled: false}, + K8sPodUID: ResourceAttributeConfig{Enabled: false}, + K8sReplicasetName: ResourceAttributeConfig{Enabled: false}, + K8sReplicasetUID: ResourceAttributeConfig{Enabled: false}, + K8sReplicationcontrollerName: ResourceAttributeConfig{Enabled: false}, + K8sReplicationcontrollerUID: ResourceAttributeConfig{Enabled: false}, + K8sResourcequotaName: ResourceAttributeConfig{Enabled: false}, + K8sResourcequotaUID: ResourceAttributeConfig{Enabled: false}, + K8sStatefulsetName: ResourceAttributeConfig{Enabled: false}, + K8sStatefulsetUID: ResourceAttributeConfig{Enabled: false}, + OpenshiftClusterquotaName: ResourceAttributeConfig{Enabled: false}, + OpenshiftClusterquotaUID: ResourceAttributeConfig{Enabled: false}, }, }, }, @@ -227,77 +235,81 @@ func TestResourceAttributesConfig(t *testing.T) { { name: "all_set", want: ResourceAttributesConfig{ - ContainerID: ResourceAttributeConfig{Enabled: true}, - ContainerImageName: ResourceAttributeConfig{Enabled: true}, - ContainerImageTag: ResourceAttributeConfig{Enabled: true}, - K8sContainerName: ResourceAttributeConfig{Enabled: true}, - K8sCronjobName: ResourceAttributeConfig{Enabled: true}, - K8sCronjobUID: ResourceAttributeConfig{Enabled: true}, - K8sDaemonsetName: ResourceAttributeConfig{Enabled: true}, - K8sDaemonsetUID: ResourceAttributeConfig{Enabled: true}, - K8sDeploymentName: ResourceAttributeConfig{Enabled: true}, - K8sDeploymentUID: ResourceAttributeConfig{Enabled: true}, - K8sHpaName: ResourceAttributeConfig{Enabled: true}, - K8sHpaUID: ResourceAttributeConfig{Enabled: true}, - K8sJobName: ResourceAttributeConfig{Enabled: true}, - K8sJobUID: ResourceAttributeConfig{Enabled: true}, - K8sKubeletVersion: ResourceAttributeConfig{Enabled: true}, - K8sKubeproxyVersion: ResourceAttributeConfig{Enabled: true}, - K8sNamespaceName: ResourceAttributeConfig{Enabled: true}, - K8sNamespaceUID: ResourceAttributeConfig{Enabled: true}, - K8sNodeName: ResourceAttributeConfig{Enabled: true}, - K8sNodeUID: ResourceAttributeConfig{Enabled: true}, - K8sPodName: ResourceAttributeConfig{Enabled: true}, - K8sPodQosClass: ResourceAttributeConfig{Enabled: true}, - K8sPodUID: ResourceAttributeConfig{Enabled: true}, - K8sReplicasetName: ResourceAttributeConfig{Enabled: true}, - K8sReplicasetUID: ResourceAttributeConfig{Enabled: true}, - K8sReplicationcontrollerName: ResourceAttributeConfig{Enabled: true}, - K8sReplicationcontrollerUID: ResourceAttributeConfig{Enabled: true}, - K8sResourcequotaName: ResourceAttributeConfig{Enabled: true}, - K8sResourcequotaUID: ResourceAttributeConfig{Enabled: true}, - K8sStatefulsetName: ResourceAttributeConfig{Enabled: true}, - K8sStatefulsetUID: ResourceAttributeConfig{Enabled: true}, - OpenshiftClusterquotaName: ResourceAttributeConfig{Enabled: true}, - OpenshiftClusterquotaUID: ResourceAttributeConfig{Enabled: true}, + ContainerID: ResourceAttributeConfig{Enabled: true}, + ContainerImageName: ResourceAttributeConfig{Enabled: true}, + ContainerImageTag: ResourceAttributeConfig{Enabled: true}, + K8sContainerName: ResourceAttributeConfig{Enabled: true}, + K8sCronjobName: ResourceAttributeConfig{Enabled: true}, + K8sCronjobUID: ResourceAttributeConfig{Enabled: true}, + K8sDaemonsetName: ResourceAttributeConfig{Enabled: true}, + K8sDaemonsetUID: ResourceAttributeConfig{Enabled: true}, + K8sDeploymentName: ResourceAttributeConfig{Enabled: true}, + K8sDeploymentUID: ResourceAttributeConfig{Enabled: true}, + K8sHierarchicalresourcequotaName: ResourceAttributeConfig{Enabled: true}, + K8sHierarchicalresourcequotaUID: ResourceAttributeConfig{Enabled: true}, + K8sHpaName: ResourceAttributeConfig{Enabled: true}, + K8sHpaUID: ResourceAttributeConfig{Enabled: true}, + K8sJobName: ResourceAttributeConfig{Enabled: true}, + K8sJobUID: ResourceAttributeConfig{Enabled: true}, + K8sKubeletVersion: ResourceAttributeConfig{Enabled: true}, + K8sKubeproxyVersion: ResourceAttributeConfig{Enabled: true}, + K8sNamespaceName: ResourceAttributeConfig{Enabled: true}, + K8sNamespaceUID: ResourceAttributeConfig{Enabled: true}, + K8sNodeName: ResourceAttributeConfig{Enabled: true}, + K8sNodeUID: ResourceAttributeConfig{Enabled: true}, + K8sPodName: ResourceAttributeConfig{Enabled: true}, + K8sPodQosClass: ResourceAttributeConfig{Enabled: true}, + K8sPodUID: ResourceAttributeConfig{Enabled: true}, + K8sReplicasetName: ResourceAttributeConfig{Enabled: true}, + K8sReplicasetUID: ResourceAttributeConfig{Enabled: true}, + K8sReplicationcontrollerName: ResourceAttributeConfig{Enabled: true}, + K8sReplicationcontrollerUID: ResourceAttributeConfig{Enabled: true}, + K8sResourcequotaName: ResourceAttributeConfig{Enabled: true}, + K8sResourcequotaUID: ResourceAttributeConfig{Enabled: true}, + K8sStatefulsetName: ResourceAttributeConfig{Enabled: true}, + K8sStatefulsetUID: ResourceAttributeConfig{Enabled: true}, + OpenshiftClusterquotaName: ResourceAttributeConfig{Enabled: true}, + OpenshiftClusterquotaUID: ResourceAttributeConfig{Enabled: true}, }, }, { name: "none_set", want: ResourceAttributesConfig{ - ContainerID: ResourceAttributeConfig{Enabled: false}, - ContainerImageName: ResourceAttributeConfig{Enabled: false}, - ContainerImageTag: ResourceAttributeConfig{Enabled: false}, - K8sContainerName: ResourceAttributeConfig{Enabled: false}, - K8sCronjobName: ResourceAttributeConfig{Enabled: false}, - K8sCronjobUID: ResourceAttributeConfig{Enabled: false}, - K8sDaemonsetName: ResourceAttributeConfig{Enabled: false}, - K8sDaemonsetUID: ResourceAttributeConfig{Enabled: false}, - K8sDeploymentName: ResourceAttributeConfig{Enabled: false}, - K8sDeploymentUID: ResourceAttributeConfig{Enabled: false}, - K8sHpaName: ResourceAttributeConfig{Enabled: false}, - K8sHpaUID: ResourceAttributeConfig{Enabled: false}, - K8sJobName: ResourceAttributeConfig{Enabled: false}, - K8sJobUID: ResourceAttributeConfig{Enabled: false}, - K8sKubeletVersion: ResourceAttributeConfig{Enabled: false}, - K8sKubeproxyVersion: ResourceAttributeConfig{Enabled: false}, - K8sNamespaceName: ResourceAttributeConfig{Enabled: false}, - K8sNamespaceUID: ResourceAttributeConfig{Enabled: false}, - K8sNodeName: ResourceAttributeConfig{Enabled: false}, - K8sNodeUID: ResourceAttributeConfig{Enabled: false}, - K8sPodName: ResourceAttributeConfig{Enabled: false}, - K8sPodQosClass: ResourceAttributeConfig{Enabled: false}, - K8sPodUID: ResourceAttributeConfig{Enabled: false}, - K8sReplicasetName: ResourceAttributeConfig{Enabled: false}, - K8sReplicasetUID: ResourceAttributeConfig{Enabled: false}, - K8sReplicationcontrollerName: ResourceAttributeConfig{Enabled: false}, - K8sReplicationcontrollerUID: ResourceAttributeConfig{Enabled: false}, - K8sResourcequotaName: ResourceAttributeConfig{Enabled: false}, - K8sResourcequotaUID: ResourceAttributeConfig{Enabled: false}, - K8sStatefulsetName: ResourceAttributeConfig{Enabled: false}, - K8sStatefulsetUID: ResourceAttributeConfig{Enabled: false}, - OpenshiftClusterquotaName: ResourceAttributeConfig{Enabled: false}, - OpenshiftClusterquotaUID: ResourceAttributeConfig{Enabled: false}, + ContainerID: ResourceAttributeConfig{Enabled: false}, + ContainerImageName: ResourceAttributeConfig{Enabled: false}, + ContainerImageTag: ResourceAttributeConfig{Enabled: false}, + K8sContainerName: ResourceAttributeConfig{Enabled: false}, + K8sCronjobName: ResourceAttributeConfig{Enabled: false}, + K8sCronjobUID: ResourceAttributeConfig{Enabled: false}, + K8sDaemonsetName: ResourceAttributeConfig{Enabled: false}, + K8sDaemonsetUID: ResourceAttributeConfig{Enabled: false}, + K8sDeploymentName: ResourceAttributeConfig{Enabled: false}, + K8sDeploymentUID: ResourceAttributeConfig{Enabled: false}, + K8sHierarchicalresourcequotaName: ResourceAttributeConfig{Enabled: false}, + K8sHierarchicalresourcequotaUID: ResourceAttributeConfig{Enabled: false}, + K8sHpaName: ResourceAttributeConfig{Enabled: false}, + K8sHpaUID: ResourceAttributeConfig{Enabled: false}, + K8sJobName: ResourceAttributeConfig{Enabled: false}, + K8sJobUID: ResourceAttributeConfig{Enabled: false}, + K8sKubeletVersion: ResourceAttributeConfig{Enabled: false}, + K8sKubeproxyVersion: ResourceAttributeConfig{Enabled: false}, + K8sNamespaceName: ResourceAttributeConfig{Enabled: false}, + K8sNamespaceUID: ResourceAttributeConfig{Enabled: false}, + K8sNodeName: ResourceAttributeConfig{Enabled: false}, + K8sNodeUID: ResourceAttributeConfig{Enabled: false}, + K8sPodName: ResourceAttributeConfig{Enabled: false}, + K8sPodQosClass: ResourceAttributeConfig{Enabled: false}, + K8sPodUID: ResourceAttributeConfig{Enabled: false}, + K8sReplicasetName: ResourceAttributeConfig{Enabled: false}, + K8sReplicasetUID: ResourceAttributeConfig{Enabled: false}, + K8sReplicationcontrollerName: ResourceAttributeConfig{Enabled: false}, + K8sReplicationcontrollerUID: ResourceAttributeConfig{Enabled: false}, + K8sResourcequotaName: ResourceAttributeConfig{Enabled: false}, + K8sResourcequotaUID: ResourceAttributeConfig{Enabled: false}, + K8sStatefulsetName: ResourceAttributeConfig{Enabled: false}, + K8sStatefulsetUID: ResourceAttributeConfig{Enabled: false}, + OpenshiftClusterquotaName: ResourceAttributeConfig{Enabled: false}, + OpenshiftClusterquotaUID: ResourceAttributeConfig{Enabled: false}, }, }, } diff --git a/receiver/k8sclusterreceiver/internal/metadata/generated_metrics.go b/receiver/k8sclusterreceiver/internal/metadata/generated_metrics.go index 3d1bf97bcc37..fc744b327ed0 100644 --- a/receiver/k8sclusterreceiver/internal/metadata/generated_metrics.go +++ b/receiver/k8sclusterreceiver/internal/metadata/generated_metrics.go @@ -845,6 +845,108 @@ func newMetricK8sDeploymentDesired(cfg MetricConfig) metricK8sDeploymentDesired return m } +type metricK8sHierarchicalResourceQuotaHardLimit 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.hierarchical_resource_quota.hard_limit metric with initial data. +func (m *metricK8sHierarchicalResourceQuotaHardLimit) init() { + m.data.SetName("k8s.hierarchical_resource_quota.hard_limit") + m.data.SetDescription("The upper limit for a particular resource in a specific namespace. Will only be sent if a quota is specified. CPU requests/limits will be sent as millicores") + m.data.SetUnit("{resource}") + m.data.SetEmptyGauge() + m.data.Gauge().DataPoints().EnsureCapacity(m.capacity) +} + +func (m *metricK8sHierarchicalResourceQuotaHardLimit) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val int64, resourceAttributeValue string) { + if !m.config.Enabled { + return + } + dp := m.data.Gauge().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetIntValue(val) + dp.Attributes().PutStr("resource", resourceAttributeValue) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricK8sHierarchicalResourceQuotaHardLimit) 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 *metricK8sHierarchicalResourceQuotaHardLimit) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricK8sHierarchicalResourceQuotaHardLimit(cfg MetricConfig) metricK8sHierarchicalResourceQuotaHardLimit { + m := metricK8sHierarchicalResourceQuotaHardLimit{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +type metricK8sHierarchicalResourceQuotaUsed 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.hierarchical_resource_quota.used metric with initial data. +func (m *metricK8sHierarchicalResourceQuotaUsed) init() { + m.data.SetName("k8s.hierarchical_resource_quota.used") + m.data.SetDescription("The usage for a particular resource in a specific namespace. Will only be sent if a quota is specified. CPU requests/limits will be sent as millicores") + m.data.SetUnit("{resource}") + m.data.SetEmptyGauge() + m.data.Gauge().DataPoints().EnsureCapacity(m.capacity) +} + +func (m *metricK8sHierarchicalResourceQuotaUsed) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val int64, resourceAttributeValue string) { + if !m.config.Enabled { + return + } + dp := m.data.Gauge().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetIntValue(val) + dp.Attributes().PutStr("resource", resourceAttributeValue) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricK8sHierarchicalResourceQuotaUsed) 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 *metricK8sHierarchicalResourceQuotaUsed) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricK8sHierarchicalResourceQuotaUsed(cfg MetricConfig) metricK8sHierarchicalResourceQuotaUsed { + m := metricK8sHierarchicalResourceQuotaUsed{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + type metricK8sHpaCurrentReplicas struct { data pmetric.Metric // data buffer for generated metric. config MetricConfig // metric config provided by user. @@ -2187,55 +2289,57 @@ func newMetricOpenshiftClusterquotaUsed(cfg MetricConfig) metricOpenshiftCluster // 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. - metricK8sContainerCPULimit metricK8sContainerCPULimit - metricK8sContainerCPURequest metricK8sContainerCPURequest - metricK8sContainerEphemeralstorageLimit metricK8sContainerEphemeralstorageLimit - metricK8sContainerEphemeralstorageRequest metricK8sContainerEphemeralstorageRequest - metricK8sContainerMemoryLimit metricK8sContainerMemoryLimit - metricK8sContainerMemoryRequest metricK8sContainerMemoryRequest - metricK8sContainerReady metricK8sContainerReady - metricK8sContainerRestarts metricK8sContainerRestarts - metricK8sContainerStorageLimit metricK8sContainerStorageLimit - metricK8sContainerStorageRequest metricK8sContainerStorageRequest - metricK8sCronjobActiveJobs metricK8sCronjobActiveJobs - metricK8sDaemonsetCurrentScheduledNodes metricK8sDaemonsetCurrentScheduledNodes - metricK8sDaemonsetDesiredScheduledNodes metricK8sDaemonsetDesiredScheduledNodes - metricK8sDaemonsetMisscheduledNodes metricK8sDaemonsetMisscheduledNodes - metricK8sDaemonsetReadyNodes metricK8sDaemonsetReadyNodes - metricK8sDeploymentAvailable metricK8sDeploymentAvailable - metricK8sDeploymentDesired metricK8sDeploymentDesired - metricK8sHpaCurrentReplicas metricK8sHpaCurrentReplicas - metricK8sHpaDesiredReplicas metricK8sHpaDesiredReplicas - metricK8sHpaMaxReplicas metricK8sHpaMaxReplicas - metricK8sHpaMinReplicas metricK8sHpaMinReplicas - metricK8sJobActivePods metricK8sJobActivePods - metricK8sJobDesiredSuccessfulPods metricK8sJobDesiredSuccessfulPods - metricK8sJobFailedPods metricK8sJobFailedPods - metricK8sJobMaxParallelPods metricK8sJobMaxParallelPods - metricK8sJobSuccessfulPods metricK8sJobSuccessfulPods - metricK8sNamespacePhase metricK8sNamespacePhase - metricK8sNodeCondition metricK8sNodeCondition - metricK8sPodPhase metricK8sPodPhase - metricK8sPodStatusReason metricK8sPodStatusReason - metricK8sReplicasetAvailable metricK8sReplicasetAvailable - metricK8sReplicasetDesired metricK8sReplicasetDesired - metricK8sReplicationControllerAvailable metricK8sReplicationControllerAvailable - metricK8sReplicationControllerDesired metricK8sReplicationControllerDesired - metricK8sResourceQuotaHardLimit metricK8sResourceQuotaHardLimit - metricK8sResourceQuotaUsed metricK8sResourceQuotaUsed - metricK8sStatefulsetCurrentPods metricK8sStatefulsetCurrentPods - metricK8sStatefulsetDesiredPods metricK8sStatefulsetDesiredPods - metricK8sStatefulsetReadyPods metricK8sStatefulsetReadyPods - metricK8sStatefulsetUpdatedPods metricK8sStatefulsetUpdatedPods - metricOpenshiftAppliedclusterquotaLimit metricOpenshiftAppliedclusterquotaLimit - metricOpenshiftAppliedclusterquotaUsed metricOpenshiftAppliedclusterquotaUsed - metricOpenshiftClusterquotaLimit metricOpenshiftClusterquotaLimit - metricOpenshiftClusterquotaUsed metricOpenshiftClusterquotaUsed + 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. + metricK8sContainerCPULimit metricK8sContainerCPULimit + metricK8sContainerCPURequest metricK8sContainerCPURequest + metricK8sContainerEphemeralstorageLimit metricK8sContainerEphemeralstorageLimit + metricK8sContainerEphemeralstorageRequest metricK8sContainerEphemeralstorageRequest + metricK8sContainerMemoryLimit metricK8sContainerMemoryLimit + metricK8sContainerMemoryRequest metricK8sContainerMemoryRequest + metricK8sContainerReady metricK8sContainerReady + metricK8sContainerRestarts metricK8sContainerRestarts + metricK8sContainerStorageLimit metricK8sContainerStorageLimit + metricK8sContainerStorageRequest metricK8sContainerStorageRequest + metricK8sCronjobActiveJobs metricK8sCronjobActiveJobs + metricK8sDaemonsetCurrentScheduledNodes metricK8sDaemonsetCurrentScheduledNodes + metricK8sDaemonsetDesiredScheduledNodes metricK8sDaemonsetDesiredScheduledNodes + metricK8sDaemonsetMisscheduledNodes metricK8sDaemonsetMisscheduledNodes + metricK8sDaemonsetReadyNodes metricK8sDaemonsetReadyNodes + metricK8sDeploymentAvailable metricK8sDeploymentAvailable + metricK8sDeploymentDesired metricK8sDeploymentDesired + metricK8sHierarchicalResourceQuotaHardLimit metricK8sHierarchicalResourceQuotaHardLimit + metricK8sHierarchicalResourceQuotaUsed metricK8sHierarchicalResourceQuotaUsed + metricK8sHpaCurrentReplicas metricK8sHpaCurrentReplicas + metricK8sHpaDesiredReplicas metricK8sHpaDesiredReplicas + metricK8sHpaMaxReplicas metricK8sHpaMaxReplicas + metricK8sHpaMinReplicas metricK8sHpaMinReplicas + metricK8sJobActivePods metricK8sJobActivePods + metricK8sJobDesiredSuccessfulPods metricK8sJobDesiredSuccessfulPods + metricK8sJobFailedPods metricK8sJobFailedPods + metricK8sJobMaxParallelPods metricK8sJobMaxParallelPods + metricK8sJobSuccessfulPods metricK8sJobSuccessfulPods + metricK8sNamespacePhase metricK8sNamespacePhase + metricK8sNodeCondition metricK8sNodeCondition + metricK8sPodPhase metricK8sPodPhase + metricK8sPodStatusReason metricK8sPodStatusReason + metricK8sReplicasetAvailable metricK8sReplicasetAvailable + metricK8sReplicasetDesired metricK8sReplicasetDesired + metricK8sReplicationControllerAvailable metricK8sReplicationControllerAvailable + metricK8sReplicationControllerDesired metricK8sReplicationControllerDesired + metricK8sResourceQuotaHardLimit metricK8sResourceQuotaHardLimit + metricK8sResourceQuotaUsed metricK8sResourceQuotaUsed + metricK8sStatefulsetCurrentPods metricK8sStatefulsetCurrentPods + metricK8sStatefulsetDesiredPods metricK8sStatefulsetDesiredPods + metricK8sStatefulsetReadyPods metricK8sStatefulsetReadyPods + metricK8sStatefulsetUpdatedPods metricK8sStatefulsetUpdatedPods + metricOpenshiftAppliedclusterquotaLimit metricOpenshiftAppliedclusterquotaLimit + metricOpenshiftAppliedclusterquotaUsed metricOpenshiftAppliedclusterquotaUsed + metricOpenshiftClusterquotaLimit metricOpenshiftClusterquotaLimit + metricOpenshiftClusterquotaUsed metricOpenshiftClusterquotaUsed } // metricBuilderOption applies changes to default metrics builder. @@ -2257,47 +2361,49 @@ func NewMetricsBuilder(mbc MetricsBuilderConfig, settings receiver.CreateSetting metricK8sContainerCPULimit: newMetricK8sContainerCPULimit(mbc.Metrics.K8sContainerCPULimit), metricK8sContainerCPURequest: newMetricK8sContainerCPURequest(mbc.Metrics.K8sContainerCPURequest), metricK8sContainerEphemeralstorageLimit: newMetricK8sContainerEphemeralstorageLimit(mbc.Metrics.K8sContainerEphemeralstorageLimit), - metricK8sContainerEphemeralstorageRequest: newMetricK8sContainerEphemeralstorageRequest(mbc.Metrics.K8sContainerEphemeralstorageRequest), - metricK8sContainerMemoryLimit: newMetricK8sContainerMemoryLimit(mbc.Metrics.K8sContainerMemoryLimit), - metricK8sContainerMemoryRequest: newMetricK8sContainerMemoryRequest(mbc.Metrics.K8sContainerMemoryRequest), - metricK8sContainerReady: newMetricK8sContainerReady(mbc.Metrics.K8sContainerReady), - metricK8sContainerRestarts: newMetricK8sContainerRestarts(mbc.Metrics.K8sContainerRestarts), - metricK8sContainerStorageLimit: newMetricK8sContainerStorageLimit(mbc.Metrics.K8sContainerStorageLimit), - metricK8sContainerStorageRequest: newMetricK8sContainerStorageRequest(mbc.Metrics.K8sContainerStorageRequest), - metricK8sCronjobActiveJobs: newMetricK8sCronjobActiveJobs(mbc.Metrics.K8sCronjobActiveJobs), - metricK8sDaemonsetCurrentScheduledNodes: newMetricK8sDaemonsetCurrentScheduledNodes(mbc.Metrics.K8sDaemonsetCurrentScheduledNodes), - metricK8sDaemonsetDesiredScheduledNodes: newMetricK8sDaemonsetDesiredScheduledNodes(mbc.Metrics.K8sDaemonsetDesiredScheduledNodes), - metricK8sDaemonsetMisscheduledNodes: newMetricK8sDaemonsetMisscheduledNodes(mbc.Metrics.K8sDaemonsetMisscheduledNodes), - metricK8sDaemonsetReadyNodes: newMetricK8sDaemonsetReadyNodes(mbc.Metrics.K8sDaemonsetReadyNodes), - metricK8sDeploymentAvailable: newMetricK8sDeploymentAvailable(mbc.Metrics.K8sDeploymentAvailable), - metricK8sDeploymentDesired: newMetricK8sDeploymentDesired(mbc.Metrics.K8sDeploymentDesired), - metricK8sHpaCurrentReplicas: newMetricK8sHpaCurrentReplicas(mbc.Metrics.K8sHpaCurrentReplicas), - metricK8sHpaDesiredReplicas: newMetricK8sHpaDesiredReplicas(mbc.Metrics.K8sHpaDesiredReplicas), - metricK8sHpaMaxReplicas: newMetricK8sHpaMaxReplicas(mbc.Metrics.K8sHpaMaxReplicas), - metricK8sHpaMinReplicas: newMetricK8sHpaMinReplicas(mbc.Metrics.K8sHpaMinReplicas), - metricK8sJobActivePods: newMetricK8sJobActivePods(mbc.Metrics.K8sJobActivePods), - metricK8sJobDesiredSuccessfulPods: newMetricK8sJobDesiredSuccessfulPods(mbc.Metrics.K8sJobDesiredSuccessfulPods), - metricK8sJobFailedPods: newMetricK8sJobFailedPods(mbc.Metrics.K8sJobFailedPods), - metricK8sJobMaxParallelPods: newMetricK8sJobMaxParallelPods(mbc.Metrics.K8sJobMaxParallelPods), - metricK8sJobSuccessfulPods: newMetricK8sJobSuccessfulPods(mbc.Metrics.K8sJobSuccessfulPods), - metricK8sNamespacePhase: newMetricK8sNamespacePhase(mbc.Metrics.K8sNamespacePhase), - metricK8sNodeCondition: newMetricK8sNodeCondition(mbc.Metrics.K8sNodeCondition), - metricK8sPodPhase: newMetricK8sPodPhase(mbc.Metrics.K8sPodPhase), - metricK8sPodStatusReason: newMetricK8sPodStatusReason(mbc.Metrics.K8sPodStatusReason), - metricK8sReplicasetAvailable: newMetricK8sReplicasetAvailable(mbc.Metrics.K8sReplicasetAvailable), - metricK8sReplicasetDesired: newMetricK8sReplicasetDesired(mbc.Metrics.K8sReplicasetDesired), - metricK8sReplicationControllerAvailable: newMetricK8sReplicationControllerAvailable(mbc.Metrics.K8sReplicationControllerAvailable), - metricK8sReplicationControllerDesired: newMetricK8sReplicationControllerDesired(mbc.Metrics.K8sReplicationControllerDesired), - metricK8sResourceQuotaHardLimit: newMetricK8sResourceQuotaHardLimit(mbc.Metrics.K8sResourceQuotaHardLimit), - metricK8sResourceQuotaUsed: newMetricK8sResourceQuotaUsed(mbc.Metrics.K8sResourceQuotaUsed), - metricK8sStatefulsetCurrentPods: newMetricK8sStatefulsetCurrentPods(mbc.Metrics.K8sStatefulsetCurrentPods), - metricK8sStatefulsetDesiredPods: newMetricK8sStatefulsetDesiredPods(mbc.Metrics.K8sStatefulsetDesiredPods), - metricK8sStatefulsetReadyPods: newMetricK8sStatefulsetReadyPods(mbc.Metrics.K8sStatefulsetReadyPods), - metricK8sStatefulsetUpdatedPods: newMetricK8sStatefulsetUpdatedPods(mbc.Metrics.K8sStatefulsetUpdatedPods), - metricOpenshiftAppliedclusterquotaLimit: newMetricOpenshiftAppliedclusterquotaLimit(mbc.Metrics.OpenshiftAppliedclusterquotaLimit), - metricOpenshiftAppliedclusterquotaUsed: newMetricOpenshiftAppliedclusterquotaUsed(mbc.Metrics.OpenshiftAppliedclusterquotaUsed), - metricOpenshiftClusterquotaLimit: newMetricOpenshiftClusterquotaLimit(mbc.Metrics.OpenshiftClusterquotaLimit), - metricOpenshiftClusterquotaUsed: newMetricOpenshiftClusterquotaUsed(mbc.Metrics.OpenshiftClusterquotaUsed), + metricK8sContainerEphemeralstorageRequest: newMetricK8sContainerEphemeralstorageRequest(mbc.Metrics.K8sContainerEphemeralstorageRequest), + metricK8sContainerMemoryLimit: newMetricK8sContainerMemoryLimit(mbc.Metrics.K8sContainerMemoryLimit), + metricK8sContainerMemoryRequest: newMetricK8sContainerMemoryRequest(mbc.Metrics.K8sContainerMemoryRequest), + metricK8sContainerReady: newMetricK8sContainerReady(mbc.Metrics.K8sContainerReady), + metricK8sContainerRestarts: newMetricK8sContainerRestarts(mbc.Metrics.K8sContainerRestarts), + metricK8sContainerStorageLimit: newMetricK8sContainerStorageLimit(mbc.Metrics.K8sContainerStorageLimit), + metricK8sContainerStorageRequest: newMetricK8sContainerStorageRequest(mbc.Metrics.K8sContainerStorageRequest), + metricK8sCronjobActiveJobs: newMetricK8sCronjobActiveJobs(mbc.Metrics.K8sCronjobActiveJobs), + metricK8sDaemonsetCurrentScheduledNodes: newMetricK8sDaemonsetCurrentScheduledNodes(mbc.Metrics.K8sDaemonsetCurrentScheduledNodes), + metricK8sDaemonsetDesiredScheduledNodes: newMetricK8sDaemonsetDesiredScheduledNodes(mbc.Metrics.K8sDaemonsetDesiredScheduledNodes), + metricK8sDaemonsetMisscheduledNodes: newMetricK8sDaemonsetMisscheduledNodes(mbc.Metrics.K8sDaemonsetMisscheduledNodes), + metricK8sDaemonsetReadyNodes: newMetricK8sDaemonsetReadyNodes(mbc.Metrics.K8sDaemonsetReadyNodes), + metricK8sDeploymentAvailable: newMetricK8sDeploymentAvailable(mbc.Metrics.K8sDeploymentAvailable), + metricK8sDeploymentDesired: newMetricK8sDeploymentDesired(mbc.Metrics.K8sDeploymentDesired), + metricK8sHierarchicalResourceQuotaHardLimit: newMetricK8sHierarchicalResourceQuotaHardLimit(mbc.Metrics.K8sHierarchicalResourceQuotaHardLimit), + metricK8sHierarchicalResourceQuotaUsed: newMetricK8sHierarchicalResourceQuotaUsed(mbc.Metrics.K8sHierarchicalResourceQuotaUsed), + metricK8sHpaCurrentReplicas: newMetricK8sHpaCurrentReplicas(mbc.Metrics.K8sHpaCurrentReplicas), + metricK8sHpaDesiredReplicas: newMetricK8sHpaDesiredReplicas(mbc.Metrics.K8sHpaDesiredReplicas), + metricK8sHpaMaxReplicas: newMetricK8sHpaMaxReplicas(mbc.Metrics.K8sHpaMaxReplicas), + metricK8sHpaMinReplicas: newMetricK8sHpaMinReplicas(mbc.Metrics.K8sHpaMinReplicas), + metricK8sJobActivePods: newMetricK8sJobActivePods(mbc.Metrics.K8sJobActivePods), + metricK8sJobDesiredSuccessfulPods: newMetricK8sJobDesiredSuccessfulPods(mbc.Metrics.K8sJobDesiredSuccessfulPods), + metricK8sJobFailedPods: newMetricK8sJobFailedPods(mbc.Metrics.K8sJobFailedPods), + metricK8sJobMaxParallelPods: newMetricK8sJobMaxParallelPods(mbc.Metrics.K8sJobMaxParallelPods), + metricK8sJobSuccessfulPods: newMetricK8sJobSuccessfulPods(mbc.Metrics.K8sJobSuccessfulPods), + metricK8sNamespacePhase: newMetricK8sNamespacePhase(mbc.Metrics.K8sNamespacePhase), + metricK8sNodeCondition: newMetricK8sNodeCondition(mbc.Metrics.K8sNodeCondition), + metricK8sPodPhase: newMetricK8sPodPhase(mbc.Metrics.K8sPodPhase), + metricK8sPodStatusReason: newMetricK8sPodStatusReason(mbc.Metrics.K8sPodStatusReason), + metricK8sReplicasetAvailable: newMetricK8sReplicasetAvailable(mbc.Metrics.K8sReplicasetAvailable), + metricK8sReplicasetDesired: newMetricK8sReplicasetDesired(mbc.Metrics.K8sReplicasetDesired), + metricK8sReplicationControllerAvailable: newMetricK8sReplicationControllerAvailable(mbc.Metrics.K8sReplicationControllerAvailable), + metricK8sReplicationControllerDesired: newMetricK8sReplicationControllerDesired(mbc.Metrics.K8sReplicationControllerDesired), + metricK8sResourceQuotaHardLimit: newMetricK8sResourceQuotaHardLimit(mbc.Metrics.K8sResourceQuotaHardLimit), + metricK8sResourceQuotaUsed: newMetricK8sResourceQuotaUsed(mbc.Metrics.K8sResourceQuotaUsed), + metricK8sStatefulsetCurrentPods: newMetricK8sStatefulsetCurrentPods(mbc.Metrics.K8sStatefulsetCurrentPods), + metricK8sStatefulsetDesiredPods: newMetricK8sStatefulsetDesiredPods(mbc.Metrics.K8sStatefulsetDesiredPods), + metricK8sStatefulsetReadyPods: newMetricK8sStatefulsetReadyPods(mbc.Metrics.K8sStatefulsetReadyPods), + metricK8sStatefulsetUpdatedPods: newMetricK8sStatefulsetUpdatedPods(mbc.Metrics.K8sStatefulsetUpdatedPods), + metricOpenshiftAppliedclusterquotaLimit: newMetricOpenshiftAppliedclusterquotaLimit(mbc.Metrics.OpenshiftAppliedclusterquotaLimit), + metricOpenshiftAppliedclusterquotaUsed: newMetricOpenshiftAppliedclusterquotaUsed(mbc.Metrics.OpenshiftAppliedclusterquotaUsed), + metricOpenshiftClusterquotaLimit: newMetricOpenshiftClusterquotaLimit(mbc.Metrics.OpenshiftClusterquotaLimit), + metricOpenshiftClusterquotaUsed: newMetricOpenshiftClusterquotaUsed(mbc.Metrics.OpenshiftClusterquotaUsed), } for _, op := range options { op(mb) @@ -2377,6 +2483,8 @@ func (mb *MetricsBuilder) EmitForResource(rmo ...ResourceMetricsOption) { mb.metricK8sDaemonsetReadyNodes.emit(ils.Metrics()) mb.metricK8sDeploymentAvailable.emit(ils.Metrics()) mb.metricK8sDeploymentDesired.emit(ils.Metrics()) + mb.metricK8sHierarchicalResourceQuotaHardLimit.emit(ils.Metrics()) + mb.metricK8sHierarchicalResourceQuotaUsed.emit(ils.Metrics()) mb.metricK8sHpaCurrentReplicas.emit(ils.Metrics()) mb.metricK8sHpaDesiredReplicas.emit(ils.Metrics()) mb.metricK8sHpaMaxReplicas.emit(ils.Metrics()) @@ -2509,6 +2617,16 @@ func (mb *MetricsBuilder) RecordK8sDeploymentDesiredDataPoint(ts pcommon.Timesta mb.metricK8sDeploymentDesired.recordDataPoint(mb.startTime, ts, val) } +// RecordK8sHierarchicalResourceQuotaHardLimitDataPoint adds a data point to k8s.hierarchical_resource_quota.hard_limit metric. +func (mb *MetricsBuilder) RecordK8sHierarchicalResourceQuotaHardLimitDataPoint(ts pcommon.Timestamp, val int64, resourceAttributeValue string) { + mb.metricK8sHierarchicalResourceQuotaHardLimit.recordDataPoint(mb.startTime, ts, val, resourceAttributeValue) +} + +// RecordK8sHierarchicalResourceQuotaUsedDataPoint adds a data point to k8s.hierarchical_resource_quota.used metric. +func (mb *MetricsBuilder) RecordK8sHierarchicalResourceQuotaUsedDataPoint(ts pcommon.Timestamp, val int64, resourceAttributeValue string) { + mb.metricK8sHierarchicalResourceQuotaUsed.recordDataPoint(mb.startTime, ts, val, resourceAttributeValue) +} + // RecordK8sHpaCurrentReplicasDataPoint adds a data point to k8s.hpa.current_replicas metric. func (mb *MetricsBuilder) RecordK8sHpaCurrentReplicasDataPoint(ts pcommon.Timestamp, val int64) { mb.metricK8sHpaCurrentReplicas.recordDataPoint(mb.startTime, ts, val) diff --git a/receiver/k8sclusterreceiver/internal/metadata/generated_metrics_test.go b/receiver/k8sclusterreceiver/internal/metadata/generated_metrics_test.go index 1883a0be42fa..fc55e353e2b2 100644 --- a/receiver/k8sclusterreceiver/internal/metadata/generated_metrics_test.go +++ b/receiver/k8sclusterreceiver/internal/metadata/generated_metrics_test.go @@ -123,6 +123,14 @@ func TestMetricsBuilder(t *testing.T) { allMetricsCount++ mb.RecordK8sDeploymentDesiredDataPoint(ts, 1) + defaultMetricsCount++ + allMetricsCount++ + mb.RecordK8sHierarchicalResourceQuotaHardLimitDataPoint(ts, 1, "resource-val") + + defaultMetricsCount++ + allMetricsCount++ + mb.RecordK8sHierarchicalResourceQuotaUsedDataPoint(ts, 1, "resource-val") + defaultMetricsCount++ allMetricsCount++ mb.RecordK8sHpaCurrentReplicasDataPoint(ts, 1) @@ -240,6 +248,8 @@ func TestMetricsBuilder(t *testing.T) { rb.SetK8sDaemonsetUID("k8s.daemonset.uid-val") rb.SetK8sDeploymentName("k8s.deployment.name-val") rb.SetK8sDeploymentUID("k8s.deployment.uid-val") + rb.SetK8sHierarchicalresourcequotaName("k8s.hierarchicalresourcequota.name-val") + rb.SetK8sHierarchicalresourcequotaUID("k8s.hierarchicalresourcequota.uid-val") rb.SetK8sHpaName("k8s.hpa.name-val") rb.SetK8sHpaUID("k8s.hpa.uid-val") rb.SetK8sJobName("k8s.job.name-val") @@ -489,6 +499,36 @@ 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.hierarchical_resource_quota.hard_limit": + assert.False(t, validatedMetrics["k8s.hierarchical_resource_quota.hard_limit"], "Found a duplicate in the metrics slice: k8s.hierarchical_resource_quota.hard_limit") + validatedMetrics["k8s.hierarchical_resource_quota.hard_limit"] = true + assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len()) + assert.Equal(t, "The upper limit for a particular resource in a specific namespace. Will only be sent if a quota is specified. CPU requests/limits will be sent as millicores", ms.At(i).Description()) + assert.Equal(t, "{resource}", 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.NumberDataPointValueTypeInt, dp.ValueType()) + assert.Equal(t, int64(1), dp.IntValue()) + attrVal, ok := dp.Attributes().Get("resource") + assert.True(t, ok) + assert.EqualValues(t, "resource-val", attrVal.Str()) + case "k8s.hierarchical_resource_quota.used": + assert.False(t, validatedMetrics["k8s.hierarchical_resource_quota.used"], "Found a duplicate in the metrics slice: k8s.hierarchical_resource_quota.used") + validatedMetrics["k8s.hierarchical_resource_quota.used"] = true + assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len()) + assert.Equal(t, "The usage for a particular resource in a specific namespace. Will only be sent if a quota is specified. CPU requests/limits will be sent as millicores", ms.At(i).Description()) + assert.Equal(t, "{resource}", 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.NumberDataPointValueTypeInt, dp.ValueType()) + assert.Equal(t, int64(1), dp.IntValue()) + attrVal, ok := dp.Attributes().Get("resource") + assert.True(t, ok) + assert.EqualValues(t, "resource-val", attrVal.Str()) case "k8s.hpa.current_replicas": assert.False(t, validatedMetrics["k8s.hpa.current_replicas"], "Found a duplicate in the metrics slice: k8s.hpa.current_replicas") validatedMetrics["k8s.hpa.current_replicas"] = true diff --git a/receiver/k8sclusterreceiver/internal/metadata/generated_resource.go b/receiver/k8sclusterreceiver/internal/metadata/generated_resource.go index ff2df65ff6e4..0c8744be7f3a 100644 --- a/receiver/k8sclusterreceiver/internal/metadata/generated_resource.go +++ b/receiver/k8sclusterreceiver/internal/metadata/generated_resource.go @@ -91,6 +91,20 @@ func (rb *ResourceBuilder) SetK8sDeploymentUID(val string) { } } +// SetK8sHierarchicalresourcequotaName sets provided value as "k8s.hierarchicalresourcequota.name" attribute. +func (rb *ResourceBuilder) SetK8sHierarchicalresourcequotaName(val string) { + if rb.config.K8sHierarchicalresourcequotaName.Enabled { + rb.res.Attributes().PutStr("k8s.hierarchicalresourcequota.name", val) + } +} + +// SetK8sHierarchicalresourcequotaUID sets provided value as "k8s.hierarchicalresourcequota.uid" attribute. +func (rb *ResourceBuilder) SetK8sHierarchicalresourcequotaUID(val string) { + if rb.config.K8sHierarchicalresourcequotaUID.Enabled { + rb.res.Attributes().PutStr("k8s.hierarchicalresourcequota.uid", val) + } +} + // SetK8sHpaName sets provided value as "k8s.hpa.name" attribute. func (rb *ResourceBuilder) SetK8sHpaName(val string) { if rb.config.K8sHpaName.Enabled { diff --git a/receiver/k8sclusterreceiver/internal/metadata/generated_resource_test.go b/receiver/k8sclusterreceiver/internal/metadata/generated_resource_test.go index 5eb06be19048..f68c4202b317 100644 --- a/receiver/k8sclusterreceiver/internal/metadata/generated_resource_test.go +++ b/receiver/k8sclusterreceiver/internal/metadata/generated_resource_test.go @@ -23,6 +23,8 @@ func TestResourceBuilder(t *testing.T) { rb.SetK8sDaemonsetUID("k8s.daemonset.uid-val") rb.SetK8sDeploymentName("k8s.deployment.name-val") rb.SetK8sDeploymentUID("k8s.deployment.uid-val") + rb.SetK8sHierarchicalresourcequotaName("k8s.hierarchicalresourcequota.name-val") + rb.SetK8sHierarchicalresourcequotaUID("k8s.hierarchicalresourcequota.uid-val") rb.SetK8sHpaName("k8s.hpa.name-val") rb.SetK8sHpaUID("k8s.hpa.uid-val") rb.SetK8sJobName("k8s.job.name-val") @@ -52,9 +54,9 @@ func TestResourceBuilder(t *testing.T) { switch test { case "default": - assert.Equal(t, 30, res.Attributes().Len()) + assert.Equal(t, 32, res.Attributes().Len()) case "all_set": - assert.Equal(t, 33, res.Attributes().Len()) + assert.Equal(t, 35, res.Attributes().Len()) case "none_set": assert.Equal(t, 0, res.Attributes().Len()) return @@ -112,6 +114,16 @@ func TestResourceBuilder(t *testing.T) { if ok { assert.EqualValues(t, "k8s.deployment.uid-val", val.Str()) } + val, ok = res.Attributes().Get("k8s.hierarchicalresourcequota.name") + assert.True(t, ok) + if ok { + assert.EqualValues(t, "k8s.hierarchicalresourcequota.name-val", val.Str()) + } + val, ok = res.Attributes().Get("k8s.hierarchicalresourcequota.uid") + assert.True(t, ok) + if ok { + assert.EqualValues(t, "k8s.hierarchicalresourcequota.uid-val", val.Str()) + } val, ok = res.Attributes().Get("k8s.hpa.name") assert.True(t, ok) if ok { diff --git a/receiver/k8sclusterreceiver/internal/metadata/testdata/config.yaml b/receiver/k8sclusterreceiver/internal/metadata/testdata/config.yaml index 11f9f2c95cb4..1e448c5187c5 100644 --- a/receiver/k8sclusterreceiver/internal/metadata/testdata/config.yaml +++ b/receiver/k8sclusterreceiver/internal/metadata/testdata/config.yaml @@ -35,6 +35,10 @@ all_set: enabled: true k8s.deployment.desired: enabled: true + k8s.hierarchical_resource_quota.hard_limit: + enabled: true + k8s.hierarchical_resource_quota.used: + enabled: true k8s.hpa.current_replicas: enabled: true k8s.hpa.desired_replicas: @@ -110,6 +114,10 @@ all_set: enabled: true k8s.deployment.uid: enabled: true + k8s.hierarchicalresourcequota.name: + enabled: true + k8s.hierarchicalresourcequota.uid: + enabled: true k8s.hpa.name: enabled: true k8s.hpa.uid: @@ -192,6 +200,10 @@ none_set: enabled: false k8s.deployment.desired: enabled: false + k8s.hierarchical_resource_quota.hard_limit: + enabled: false + k8s.hierarchical_resource_quota.used: + enabled: false k8s.hpa.current_replicas: enabled: false k8s.hpa.desired_replicas: @@ -267,6 +279,10 @@ none_set: enabled: false k8s.deployment.uid: enabled: false + k8s.hierarchicalresourcequota.name: + enabled: false + k8s.hierarchicalresourcequota.uid: + enabled: false k8s.hpa.name: enabled: false k8s.hpa.uid: diff --git a/receiver/k8sclusterreceiver/internal/testutils/objects.go b/receiver/k8sclusterreceiver/internal/testutils/objects.go index f94b2a90bfbf..bd59b48d8ca3 100644 --- a/receiver/k8sclusterreceiver/internal/testutils/objects.go +++ b/receiver/k8sclusterreceiver/internal/testutils/objects.go @@ -11,6 +11,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/types" ) @@ -397,3 +398,27 @@ func NewCronJob(id string) *batchv1.CronJob { }, } } + +func NewHierarchicalResourceQuota(id string) *unstructured.Unstructured { + return &unstructured.Unstructured{ + Object: map[string]interface{}{ + "metadata": map[string]interface{}{ + "name": "test-hierarchicalresourcequota-" + id, + "uid": types.UID("test-resourcequota-" + id + "-uid"), + "namespace": "test-namespace", + "labels": map[string]string{ + "foo": "bar", + "foo1": "", + }, + }, + "status": map[string]interface{}{ + "hard": map[string]interface{}{ + "requests.cpu": "2", + }, + "used": map[string]interface{}{ + "requests.cpu": "1", + }, + }, + }, + } +} diff --git a/receiver/k8sclusterreceiver/metadata.yaml b/receiver/k8sclusterreceiver/metadata.yaml index 5ce43876497a..f1d7489a0893 100644 --- a/receiver/k8sclusterreceiver/metadata.yaml +++ b/receiver/k8sclusterreceiver/metadata.yaml @@ -177,6 +177,16 @@ resource_attributes: type: string enabled: true + k8s.hierarchicalresourcequota.uid: + description: The k8s HierarchicalResourceQuota uid. + type: string + enabled: true + + k8s.hierarchicalresourcequota.name: + description: The k8s HierarchicalresourceQuota name. + type: string + enabled: true + attributes: k8s.namespace.name: description: The k8s namespace name. @@ -495,3 +505,19 @@ metrics: # k8s.node.allocatable_* metrics (k8s.node.allocatable_cpu, k8s.node.allocatable_memory, etc) are controlled # by allocatable_types_to_report config option. By default, none of them are reported. + k8s.hierarchical_resource_quota.hard_limit: + enabled: true + description: The upper limit for a particular resource in a specific namespace. Will only be sent if a quota is specified. CPU requests/limits will be sent as millicores + unit: "{resource}" + gauge: + value_type: int + attributes: + - resource + k8s.hierarchical_resource_quota.used: + enabled: true + description: The usage for a particular resource in a specific namespace. Will only be sent if a quota is specified. CPU requests/limits will be sent as millicores + unit: "{resource}" + gauge: + value_type: int + attributes: + - resource \ No newline at end of file diff --git a/receiver/k8sclusterreceiver/watcher.go b/receiver/k8sclusterreceiver/watcher.go index 5ac39e548281..2bb55a72b0d6 100644 --- a/receiver/k8sclusterreceiver/watcher.go +++ b/receiver/k8sclusterreceiver/watcher.go @@ -17,13 +17,20 @@ import ( "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/receiver" "go.uber.org/zap" + appsv1 "k8s.io/api/apps/v1" autoscalingv2 "k8s.io/api/autoscaling/v2" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/informers" + + "k8s.io/client-go/dynamic" + "k8s.io/client-go/dynamic/dynamicinformer" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/cache" @@ -33,6 +40,7 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/demonset" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/deployment" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/gvk" + "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/gvr" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/hpa" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/jobs" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/metadata" @@ -49,8 +57,20 @@ type sharedInformer interface { WaitForCacheSync(<-chan struct{}) map[reflect.Type]bool } +type dynamicSharedInformerFactory struct { + dynamicinformer.DynamicSharedInformerFactory +} + +func (df *dynamicSharedInformerFactory) WaitForCacheSync(channel <-chan struct{}) map[reflect.Type]bool { + cache := df.DynamicSharedInformerFactory.WaitForCacheSync(channel) + return map[reflect.Type]bool{ + reflect.TypeOf(&unstructured.Unstructured{}): cache[gvr.HierarchicalResourceQuota], + } +} + type resourceWatcher struct { client kubernetes.Interface + dynamicClient dynamic.Interface osQuotaClient quotaclientset.Interface informerFactories []sharedInformer metadataStore *metadata.Store @@ -64,6 +84,7 @@ type resourceWatcher struct { // For mocking. makeClient func(apiConf k8sconfig.APIConfig) (kubernetes.Interface, error) + makeDynamicClient func(apiConf k8sconfig.APIConfig) (dynamic.Interface, error) makeOpenShiftQuotaClient func(apiConf k8sconfig.APIConfig) (quotaclientset.Interface, error) } @@ -79,6 +100,7 @@ func newResourceWatcher(set receiver.CreateSettings, cfg *Config, metadataStore initialTimeout: defaultInitialSyncTimeout, config: cfg, makeClient: k8sconfig.MakeClient, + makeDynamicClient: k8sconfig.MakeDynamicClient, makeOpenShiftQuotaClient: k8sconfig.MakeOpenShiftQuotaClient, } } @@ -86,10 +108,16 @@ func newResourceWatcher(set receiver.CreateSettings, cfg *Config, metadataStore func (rw *resourceWatcher) initialize() error { client, err := rw.makeClient(rw.config.APIConfig) if err != nil { - return fmt.Errorf("Failed to create Kubernnetes client: %w", err) + return fmt.Errorf("Failed to create Kubernetes client: %w", err) } rw.client = client + dynamicClient, err := rw.makeDynamicClient(rw.config.APIConfig) + if err != nil { + return fmt.Errorf("Failed to create Kubernetes client: %w", err) + } + rw.dynamicClient = dynamicClient + if rw.config.Distribution == distributionOpenShift { rw.osQuotaClient, err = rw.makeOpenShiftQuotaClient(rw.config.APIConfig) if err != nil { @@ -127,7 +155,6 @@ func (rw *resourceWatcher) prepareSharedInformerFactory() error { "CronJob": {gvk.CronJob}, "HorizontalPodAutoscaler": {gvk.HorizontalPodAutoscaler}, } - for kind, gvks := range supportedKinds { anySupported := false for _, gvk := range gvks { @@ -146,6 +173,13 @@ func (rw *resourceWatcher) prepareSharedInformerFactory() error { } } + dynamicFactory := dynamicinformer.NewDynamicSharedInformerFactory(rw.dynamicClient, rw.config.MetadataCollectionInterval) + dynamicInformer := dynamicFactory.ForResource(gvr.HierarchicalResourceQuota) + rw.setupInformer(gvk.HierarchicalResourceQuota, dynamicInformer.Informer()) + rw.informerFactories = append(rw.informerFactories, &(dynamicSharedInformerFactory{ + DynamicSharedInformerFactory: dynamicFactory, + })) + if rw.osQuotaClient != nil { quotaFactory := quotainformersv1.NewSharedInformerFactory(rw.osQuotaClient, 0) rw.setupInformer(gvk.ClusterResourceQuota, quotaFactory.Quota().V1().ClusterResourceQuotas().Informer())