diff --git a/.chloggen/kubeletstats_featuregate_metrics.yaml b/.chloggen/kubeletstats_featuregate_metrics.yaml new file mode 100644 index 000000000000..9c1fed91a6b1 --- /dev/null +++ b/.chloggen/kubeletstats_featuregate_metrics.yaml @@ -0,0 +1,27 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: enhancement + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: kubeletstats + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Introduce feature gate for deprecation of container.cpu.utilization, k8s.pod.cpu.utilization and k8s.node.cpu.utilization metrics + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [35139] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: + +# If your change doesn't affect end users or the exported elements of any package, +# you should instead start your pull request title with [chore] or use the "Skip Changelog" label. +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [user] diff --git a/receiver/kubeletstatsreceiver/README.md b/receiver/kubeletstatsreceiver/README.md index a250ba5dff37..65596786d9a0 100644 --- a/receiver/kubeletstatsreceiver/README.md +++ b/receiver/kubeletstatsreceiver/README.md @@ -285,3 +285,23 @@ rules: resources: ["nodes/proxy"] verbs: ["get"] ``` + +### Warning about metrics' deprecation + +The following metrics will be renamed in a future version: +- `k8s.node.cpu.utilization` (renamed to `k8s.node.cpu.usage`) +- `k8s.pod.cpu.utilization` (renamed to `k8s.pod.cpu.usage`) +- `container.cpu.utilization` (renamed to `container.cpu.usage`) + +The above metrics show usage counted in CPUs and it's not a percentage of used resources. +These metrics were previously incorrectly named using the utilization term. + +#### `receiver.kubeletstats.enableCPUUsageMetrics` feature gate + +- alpha: when enabled it makes the `.cpu.usage` metrics enabled by default, disabling the `.cpu.utilization` metrics +- beta: `.cpu.usage` metrics are enabled by default and any configuration enabling the deprecated `.cpu.utilization` metrics will be failing. Explicitly disabling the feature gate provides the old (deprecated) behavior. +- stable: `.cpu.usage` metrics are enabled by default and the deprecated metrics are completely removed. +- removed three releases after stable. + +More information about the deprecation plan and +the background reasoning can be found at https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/27885. \ No newline at end of file diff --git a/receiver/kubeletstatsreceiver/factory.go b/receiver/kubeletstatsreceiver/factory.go index d5ed491f5a65..bc831b11a760 100644 --- a/receiver/kubeletstatsreceiver/factory.go +++ b/receiver/kubeletstatsreceiver/factory.go @@ -9,6 +9,7 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/featuregate" "go.opentelemetry.io/collector/receiver" "go.opentelemetry.io/collector/receiver/scraperhelper" "go.uber.org/zap" @@ -20,7 +21,16 @@ import ( ) const ( - metricGroupsConfig = "metric_groups" + metricGroupsConfig = "metric_groups" + enableCPUUsageMetricsFeatureFlag = "receiver.kubeletstats.enableCPUUsageMetrics" +) + +var enableCPUUsageMetrics = featuregate.GlobalRegistry().MustRegister( + enableCPUUsageMetricsFeatureFlag, + featuregate.StageAlpha, + featuregate.WithRegisterDescription("When enabled the container.cpu.utilization, k8s.pod.cpu.utilization and k8s.node.cpu.utilization metrics will be replaced by the container.cpu.usage, k8s.pod.cpu.usage and k8s.node.cpu.usage"), + featuregate.WithRegisterFromVersion("v0.110.0"), + featuregate.WithRegisterReferenceURL("https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/27885"), ) var defaultMetricGroups = []kubelet.MetricGroup{ @@ -68,6 +78,31 @@ func createMetricsReceiver( return nil, err } + if enableCPUUsageMetrics.IsEnabled() { + if cfg.MetricsBuilderConfig.Metrics.ContainerCPUUtilization.Enabled { + cfg.MetricsBuilderConfig.Metrics.ContainerCPUUtilization.Enabled = false + cfg.MetricsBuilderConfig.Metrics.ContainerCPUUsage.Enabled = true + } + if cfg.MetricsBuilderConfig.Metrics.K8sPodCPUUtilization.Enabled { + cfg.MetricsBuilderConfig.Metrics.K8sPodCPUUtilization.Enabled = false + cfg.MetricsBuilderConfig.Metrics.K8sPodCPUUsage.Enabled = true + } + if cfg.MetricsBuilderConfig.Metrics.K8sNodeCPUUtilization.Enabled { + cfg.MetricsBuilderConfig.Metrics.K8sNodeCPUUtilization.Enabled = false + cfg.MetricsBuilderConfig.Metrics.K8sNodeCPUUsage.Enabled = true + } + } else { + if cfg.MetricsBuilderConfig.Metrics.ContainerCPUUtilization.Enabled { + set.Logger.Warn("The default metric container.cpu.utilization is being replaced by the container.cpu.usage metric. Switch now by enabling the receiver.kubeletstats.enableCPUUsageMetrics feature gate.") + } + if cfg.MetricsBuilderConfig.Metrics.K8sPodCPUUtilization.Enabled { + set.Logger.Warn("The default metric k8s.pod.cpu.utilization is being replaced by the k8s.pod.cpu.usage metric. Switch now by enabling the receiver.kubeletstats.enableCPUUsageMetrics feature gate.") + } + if cfg.MetricsBuilderConfig.Metrics.K8sNodeCPUUtilization.Enabled { + set.Logger.Warn("The default metric k8s.node.cpu.utilization is being replaced by the k8s.node.cpu.usage metric. Switch now by enabling the receiver.kubeletstats.enableCPUUsageMetrics feature gate.") + } + } + scrp, err := newKubletScraper(rest, set, rOptions, cfg.MetricsBuilderConfig, cfg.NodeName) if err != nil { return nil, err diff --git a/receiver/kubeletstatsreceiver/go.mod b/receiver/kubeletstatsreceiver/go.mod index 03b1346bda82..874dc66b9ac8 100644 --- a/receiver/kubeletstatsreceiver/go.mod +++ b/receiver/kubeletstatsreceiver/go.mod @@ -17,6 +17,7 @@ require ( go.opentelemetry.io/collector/confmap v1.16.0 go.opentelemetry.io/collector/consumer v0.110.0 go.opentelemetry.io/collector/consumer/consumertest v0.110.0 + go.opentelemetry.io/collector/featuregate v1.16.0 go.opentelemetry.io/collector/filter v0.110.0 go.opentelemetry.io/collector/pdata v1.16.0 go.opentelemetry.io/collector/pipeline v0.110.0 @@ -56,6 +57,7 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/gofuzz v1.2.0 // indirect + github.com/hashicorp/go-version v1.7.0 // indirect github.com/imdario/mergo v0.3.11 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect diff --git a/receiver/kubeletstatsreceiver/go.sum b/receiver/kubeletstatsreceiver/go.sum index afc2c26a24e7..aca29ff33744 100644 --- a/receiver/kubeletstatsreceiver/go.sum +++ b/receiver/kubeletstatsreceiver/go.sum @@ -173,6 +173,8 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -337,6 +339,8 @@ go.opentelemetry.io/collector/extension v0.110.0 h1:AYFk57W25f7xOo3I6pV0rWNWVtOL go.opentelemetry.io/collector/extension v0.110.0/go.mod h1:zD/pw9o83SFyn/DCbBdBcH0eUPyGtYgpMSAOqotFYRc= go.opentelemetry.io/collector/extension/auth v0.110.0 h1:9SHC2sF/KR99LciHABDXRIsXLiujzIjTJpWHO0V8Bqg= go.opentelemetry.io/collector/extension/auth v0.110.0/go.mod h1:NjpHds6mjeT8Zn2KJVxZtV9c59AoIr6RlBha1RpmScQ= +go.opentelemetry.io/collector/featuregate v1.16.0 h1:mNA/ga+5FErnbJ/47KsGsF+CWqgQSOxTIseo6WuMcsc= +go.opentelemetry.io/collector/featuregate v1.16.0/go.mod h1:47xrISO71vJ83LSMm8+yIDsUbKktUp48Ovt7RR6VbRs= go.opentelemetry.io/collector/filter v0.110.0 h1:yepvSd82x8gQwFaEb49AS2wOWdJxWVC+RCY5J+JMxgY= go.opentelemetry.io/collector/filter v0.110.0/go.mod h1:cYdCpDj9WtHZkLtPCMsOWH9QFU686j8K93n2jO+mdjw= go.opentelemetry.io/collector/internal/globalsignal v0.110.0 h1:S6bfFEiek8vJeXAbciWS7W8UR6ZrVJB3ftNyFTMHQaY= diff --git a/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics.go b/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics.go index 7fc1c918ac0c..32883ff709d9 100644 --- a/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics.go +++ b/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics.go @@ -3102,10 +3102,10 @@ func WithStartTime(startTime pcommon.Timestamp) MetricBuilderOption { func NewMetricsBuilder(mbc MetricsBuilderConfig, settings receiver.Settings, options ...MetricBuilderOption) *MetricsBuilder { if mbc.Metrics.ContainerCPUUtilization.Enabled { - settings.Logger.Warn("[WARNING] `container.cpu.utilization` should not be enabled: WARNING: This metric will be disabled in a future release. Use metric container.cpu.usage instead.") + settings.Logger.Warn("[WARNING] `container.cpu.utilization` should not be enabled: This metric will be disabled in a future release. Use metric container.cpu.usage instead.") } if mbc.Metrics.K8sNodeCPUUtilization.Enabled { - settings.Logger.Warn("[WARNING] `k8s.node.cpu.utilization` should not be enabled: WARNING: This metric will be disabled in a future release. Use metric k8s.node.cpu.usage instead.") + settings.Logger.Warn("[WARNING] `k8s.node.cpu.utilization` should not be enabled: This metric will be disabled in a future release. Use metric k8s.node.cpu.usage instead.") } if mbc.Metrics.K8sPodCPUUtilization.Enabled { settings.Logger.Warn("[WARNING] `k8s.pod.cpu.utilization` should not be enabled: This metric will be disabled in a future release. Use metric k8s.pod.cpu.usage instead.") diff --git a/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics_test.go b/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics_test.go index 1f4325186b76..6a0606a51e85 100644 --- a/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics_test.go +++ b/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics_test.go @@ -63,11 +63,11 @@ func TestMetricsBuilder(t *testing.T) { expectedWarnings := 0 if tt.metricsSet == testDataSetDefault || tt.metricsSet == testDataSetAll { - assert.Equal(t, "[WARNING] `container.cpu.utilization` should not be enabled: WARNING: This metric will be disabled in a future release. Use metric container.cpu.usage instead.", observedLogs.All()[expectedWarnings].Message) + assert.Equal(t, "[WARNING] `container.cpu.utilization` should not be enabled: This metric will be disabled in a future release. Use metric container.cpu.usage instead.", observedLogs.All()[expectedWarnings].Message) expectedWarnings++ } if tt.metricsSet == testDataSetDefault || tt.metricsSet == testDataSetAll { - assert.Equal(t, "[WARNING] `k8s.node.cpu.utilization` should not be enabled: WARNING: This metric will be disabled in a future release. Use metric k8s.node.cpu.usage instead.", observedLogs.All()[expectedWarnings].Message) + assert.Equal(t, "[WARNING] `k8s.node.cpu.utilization` should not be enabled: This metric will be disabled in a future release. Use metric k8s.node.cpu.usage instead.", observedLogs.All()[expectedWarnings].Message) expectedWarnings++ } if tt.metricsSet == testDataSetDefault || tt.metricsSet == testDataSetAll { diff --git a/receiver/kubeletstatsreceiver/metadata.yaml b/receiver/kubeletstatsreceiver/metadata.yaml index 67b7c362221a..5f093e30ba7c 100644 --- a/receiver/kubeletstatsreceiver/metadata.yaml +++ b/receiver/kubeletstatsreceiver/metadata.yaml @@ -92,7 +92,7 @@ metrics: enabled: true description: "Node CPU utilization" warnings: - if_enabled: "WARNING: This metric will be disabled in a future release. Use metric k8s.node.cpu.usage instead." + if_enabled: "This metric will be disabled in a future release. Use metric k8s.node.cpu.usage instead." unit: "1" gauge: value_type: double @@ -364,7 +364,7 @@ metrics: enabled: true description: "Container CPU utilization" warnings: - if_enabled: "WARNING: This metric will be disabled in a future release. Use metric container.cpu.usage instead." + if_enabled: "This metric will be disabled in a future release. Use metric container.cpu.usage instead." unit: "1" gauge: value_type: double