From 3b3901fd3aad77b25ca1a62c87cb964aedb38e66 Mon Sep 17 00:00:00 2001 From: Petru Anica-Popa Date: Mon, 5 Oct 2026 13:10:00 +0000 Subject: [PATCH 1/4] test(otel): cover removal of deprecated and doubled collector attributes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regression guards for the removal of deprecated semantic-convention and duplicated raw Prometheus attributes from the Container Insights pipelines, made in the paired helm-charts and cloudwatch-agent changes. TestDeprecatedSemconvAttributesRemoved asserts net.host.name, net.host.port and http.scheme are absent at resource scope across the Prometheus-scraped and kube-state-metrics name sets, and that url.scheme is still present. The url.scheme assertion is the point: before transform/cw_k8s_ci_v0_drop_deprecated_semconv existed, the karpenter and keda promote transforms deleted url.scheme — the current name — and kept http.scheme, the deprecated one. This fails if that inversion returns. TestRawLabelsNotBilledTwice asserts the raw Prometheus labels are gone from resource scope on cadvisor and kube-state-metrics. The datapoint copies, which are the ones dashboards read, must survive and are already covered by TestCadvisorHasRawPromotedKeys and the TestKSM_*_HasRaw*Label family, so this test only checks the resource side. --- test/otel/standard/labels_common_test.go | 82 ++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/test/otel/standard/labels_common_test.go b/test/otel/standard/labels_common_test.go index a6ab05541..36f107986 100644 --- a/test/otel/standard/labels_common_test.go +++ b/test/otel/standard/labels_common_test.go @@ -672,3 +672,85 @@ func TestScrapeMetadataFiltered(t *testing.T) { }) } } + +// --------------------------------------------------------------------------- +// TestDeprecatedSemconvAttributesRemoved — the deprecated semconv attributes go, +// their current-spelling twins stay. url.scheme is asserted present on purpose: +// karpenter/keda used to delete it and keep http.scheme, which was backwards. +// --------------------------------------------------------------------------- + +func TestDeprecatedSemconvAttributesRemoved(t *testing.T) { + deprecated := []string{"net.host.name", "net.host.port", "http.scheme"} + + names := prometheusScrapedNames() + names = append(names, metricNames(allKSMMetricDefs)...) + + for _, metricName := range names { + t.Run(metricName, func(t *testing.T) { + results, err := queryCache.Get(context.Background(), metricName) + require.NoError(t, err, "querying %s", metricName) + require.NotEmpty(t, results, "%s not available", metricName) + sawURLScheme := false + for _, r := range results { + for _, key := range deprecated { + _, present := r.Labels.Resource[key] + require.False(t, present, + "%s still carries deprecated resource attribute %q", metricName, key) + } + if r.Labels.Resource["url.scheme"] != "" { + sawURLScheme = true + } + } + require.True(t, sawURLScheme, + "%s has no url.scheme on any series — the current-spelling attribute must survive", metricName) + }) + } +} + +// --------------------------------------------------------------------------- +// TestRawLabelsNotBilledTwice — the raw Prometheus labels must exist only at +// datapoint scope, not at resource scope too. The datapoint side is covered by +// TestCadvisorHasRawPromotedKeys and the TestKSM_*_HasRaw*Label family. +// --------------------------------------------------------------------------- + +func TestRawLabelsNotBilledTwice(t *testing.T) { + cases := []struct { + pipeline string + names []string + rawKeys []string + }{ + { + pipeline: "cadvisor", + names: cadvisorMetricNamesList, + rawKeys: []string{"pod", "namespace", "container"}, + }, + { + pipeline: "kube-state-metrics", + names: metricNames(allKSMMetricDefs), + rawKeys: []string{ + "pod", "namespace", "node", "uid", "container", + "owner_name", "owner_kind", "deployment", "daemonset", + "statefulset", "replicaset", "job_name", "cronjob", + }, + }, + } + + for _, c := range cases { + c := c + for _, metricName := range c.names { + t.Run(c.pipeline+"/"+metricName, func(t *testing.T) { + results, err := queryCache.Get(context.Background(), metricName) + require.NoError(t, err, "querying %s", metricName) + require.NotEmpty(t, results, "%s not available", metricName) + for _, r := range results { + for _, key := range c.rawKeys { + _, present := r.Labels.Resource[key] + require.False(t, present, + "%s carries raw label %q at resource scope as well as datapoint scope", + metricName, key) + } + } + }) + } + } +} From 345af43755a3a0747062ef383cc8713d487793a5 Mon Sep 17 00:00:00 2001 From: Petru Anica-Popa Date: Wed, 7 Oct 2026 12:49:58 +0000 Subject: [PATCH 2/4] test(otel): cover the cAdvisor cgroup path removal and the name retention TestCadvisorIdLabelDropped asserts the cgroup path id no longer reaches datapoint scope on any cAdvisor metric. The assertion reads datapoint scope rather than resource scope because id is a raw Prometheus label that groupbyattrs never promotes, which is also why the attribute-limit denylist cannot remove it and a transform at context: datapoint does the work. TestCadvisorNameLabelRetained guards the decision to keep name. Once id is gone, name is the only remaining carrier of the container ID, so a later change that widened the removal to cover both would take the container ID out of the payload entirely. It requires at least one datapoint to still carry name rather than all of them, because node-scope cAdvisor series have no container and so no name. --- test/otel/standard/labels_common_test.go | 41 ++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/otel/standard/labels_common_test.go b/test/otel/standard/labels_common_test.go index 36f107986..5d9e16d82 100644 --- a/test/otel/standard/labels_common_test.go +++ b/test/otel/standard/labels_common_test.go @@ -754,3 +754,44 @@ func TestRawLabelsNotBilledTwice(t *testing.T) { } } } + +// TestCadvisorIdLabelDropped asserts the cgroup path is gone from cAdvisor datapoints. It is +// a datapoint attribute, not a resource one, so the attribute-limit denylist cannot remove it +// and a transform at context: datapoint does the work instead. +func TestCadvisorIdLabelDropped(t *testing.T) { + for _, metricName := range cadvisorMetricNamesList { + t.Run(metricName, func(t *testing.T) { + results, err := queryCache.Get(context.Background(), metricName) + require.NoError(t, err, "querying %s", metricName) + require.NotEmpty(t, results, "%s not available", metricName) + for _, r := range results { + _, present := r.Labels.Datapoint["id"] + require.False(t, present, + "%s still carries the cgroup path id at datapoint scope on node %s", + metricName, r.Labels.Resource["k8s.node.name"]) + } + }) + } +} + +// TestCadvisorNameLabelRetained guards the deliberate decision to keep name. It is the only +// remaining carrier of the container ID once id is dropped, so widening the removal to cover +// both would take the container ID out of the payload entirely. Requires at least one +// datapoint to still carry it rather than all of them, since node-scope cAdvisor series have +// no container and therefore no name. +func TestCadvisorNameLabelRetained(t *testing.T) { + for _, metricName := range cadvisorMetricNamesList { + t.Run(metricName, func(t *testing.T) { + results, err := queryCache.Get(context.Background(), metricName) + require.NoError(t, err, "querying %s", metricName) + require.NotEmpty(t, results, "%s not available", metricName) + for _, r := range results { + if _, present := r.Labels.Datapoint["name"]; present { + return + } + } + t.Fatalf("%s carries name on no datapoint; dropping it alongside id would remove "+ + "the container ID from the payload entirely", metricName) + }) + } +} From 798c135ea532b399a91ba62904d34de44d491c84 Mon Sep 17 00:00:00 2001 From: Petru Anica-Popa Date: Wed, 7 Oct 2026 16:28:55 +0000 Subject: [PATCH 3/4] test(otel): rename TestRawLabelsNotBilledTwice to TestRawLabelsOnlyAtDatapointScope --- test/otel/standard/labels_common_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/otel/standard/labels_common_test.go b/test/otel/standard/labels_common_test.go index 5d9e16d82..5198b27e0 100644 --- a/test/otel/standard/labels_common_test.go +++ b/test/otel/standard/labels_common_test.go @@ -708,12 +708,12 @@ func TestDeprecatedSemconvAttributesRemoved(t *testing.T) { } // --------------------------------------------------------------------------- -// TestRawLabelsNotBilledTwice — the raw Prometheus labels must exist only at +// TestRawLabelsOnlyAtDatapointScope — the raw Prometheus labels must exist only at // datapoint scope, not at resource scope too. The datapoint side is covered by // TestCadvisorHasRawPromotedKeys and the TestKSM_*_HasRaw*Label family. // --------------------------------------------------------------------------- -func TestRawLabelsNotBilledTwice(t *testing.T) { +func TestRawLabelsOnlyAtDatapointScope(t *testing.T) { cases := []struct { pipeline string names []string From 364c9b2405784540bad3232113b05b777f058ac3 Mon Sep 17 00:00:00 2001 From: Petru Anica-Popa Date: Thu, 8 Oct 2026 10:21:23 +0000 Subject: [PATCH 4/4] revert(otel): drop the cAdvisor cgroup path tests --- test/otel/standard/labels_common_test.go | 41 ------------------------ 1 file changed, 41 deletions(-) diff --git a/test/otel/standard/labels_common_test.go b/test/otel/standard/labels_common_test.go index 5198b27e0..c6842273d 100644 --- a/test/otel/standard/labels_common_test.go +++ b/test/otel/standard/labels_common_test.go @@ -754,44 +754,3 @@ func TestRawLabelsOnlyAtDatapointScope(t *testing.T) { } } } - -// TestCadvisorIdLabelDropped asserts the cgroup path is gone from cAdvisor datapoints. It is -// a datapoint attribute, not a resource one, so the attribute-limit denylist cannot remove it -// and a transform at context: datapoint does the work instead. -func TestCadvisorIdLabelDropped(t *testing.T) { - for _, metricName := range cadvisorMetricNamesList { - t.Run(metricName, func(t *testing.T) { - results, err := queryCache.Get(context.Background(), metricName) - require.NoError(t, err, "querying %s", metricName) - require.NotEmpty(t, results, "%s not available", metricName) - for _, r := range results { - _, present := r.Labels.Datapoint["id"] - require.False(t, present, - "%s still carries the cgroup path id at datapoint scope on node %s", - metricName, r.Labels.Resource["k8s.node.name"]) - } - }) - } -} - -// TestCadvisorNameLabelRetained guards the deliberate decision to keep name. It is the only -// remaining carrier of the container ID once id is dropped, so widening the removal to cover -// both would take the container ID out of the payload entirely. Requires at least one -// datapoint to still carry it rather than all of them, since node-scope cAdvisor series have -// no container and therefore no name. -func TestCadvisorNameLabelRetained(t *testing.T) { - for _, metricName := range cadvisorMetricNamesList { - t.Run(metricName, func(t *testing.T) { - results, err := queryCache.Get(context.Background(), metricName) - require.NoError(t, err, "querying %s", metricName) - require.NotEmpty(t, results, "%s not available", metricName) - for _, r := range results { - if _, present := r.Labels.Datapoint["name"]; present { - return - } - } - t.Fatalf("%s carries name on no datapoint; dropping it alongside id would remove "+ - "the container ID from the payload entirely", metricName) - }) - } -}