diff --git a/processor/awsapplicationsignalsprocessor/internal/resolver/kubernetes.go b/processor/awsapplicationsignalsprocessor/internal/resolver/kubernetes.go index 5ff1eec7f15b..260d3b1f986f 100644 --- a/processor/awsapplicationsignalsprocessor/internal/resolver/kubernetes.go +++ b/processor/awsapplicationsignalsprocessor/internal/resolver/kubernetes.go @@ -593,13 +593,16 @@ func newKubernetesResourceAttributesResolver(platformCode, clusterName string) * } } -// Attempt to get the `k8s.cluster.name“ attribute that should be populated from resourcedetectionprocessor. +// Attempt to get the `k8s.cluster.name` attribute that should be populated from resourcedetectionprocessor. // If that attribute doesn't exist (e.g. resourcedetectionprocessor is not used or fails to get the k8s attributes), // fallback to the processor's configured clusterName (which is "UNKNOWN" if not specified). func (h *kubernetesResourceAttributesResolver) getResourceDetectorClusterName(resourceAttributes pcommon.Map) string { clusterName := h.clusterName - if val, ok := resourceAttributes.Get(attr.ResourceDetectionClusterName); ok { + // Also check for empty string from `k8s.cluster.name` attribute, since resource detection could fail + // and upstream will populate this attribute with an empty string + // https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/v0.114.0/processor/resourcedetectionprocessor/internal/aws/eks/detector.go#L137-L176 + if val, ok := resourceAttributes.Get(attr.ResourceDetectionClusterName); ok && val.Str() != "" { clusterName = val.Str() } diff --git a/processor/awsapplicationsignalsprocessor/internal/resolver/kubernetes_test.go b/processor/awsapplicationsignalsprocessor/internal/resolver/kubernetes_test.go index 4ea02503c409..6cbe06ca8df8 100644 --- a/processor/awsapplicationsignalsprocessor/internal/resolver/kubernetes_test.go +++ b/processor/awsapplicationsignalsprocessor/internal/resolver/kubernetes_test.go @@ -894,6 +894,16 @@ func TestK8sResourceAttributesResolverOnEKS(t *testing.T) { common.AttributeEKSClusterName: "DetectedClusterName", }, }, + { + "testEmptyClusterNameFromDetector", + map[string]string{ + attr.ResourceDetectionClusterName: "", + }, + map[string]string{ + attr.AWSLocalEnvironment: "eks:test-cluster/test-namespace-3", + common.AttributeEKSClusterName: "test-cluster", + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -912,7 +922,7 @@ func TestK8sResourceAttributesResolverOnEKS(t *testing.T) { assert.Equal(t, val, getStrAttr(attributes, key, t), fmt.Sprintf("expected %s for key %s", val, key)) } - if _, ok := resourceAttributes.Get(attr.ResourceDetectionClusterName); ok { + if val, ok := resourceAttributes.Get(attr.ResourceDetectionClusterName); ok && val.Str() != "" { assert.Equal(t, "/aws/containerinsights/DetectedClusterName/application", getStrAttr(resourceAttributes, semconv.AttributeAWSLogGroupNames, t)) } else { assert.Equal(t, "/aws/containerinsights/test-cluster/application", getStrAttr(resourceAttributes, semconv.AttributeAWSLogGroupNames, t)) @@ -926,10 +936,13 @@ func TestGetResourceDetectorClusterName(t *testing.T) { resourceDetectorAttributes := pcommon.NewMap() resourceDetectorClusterName := resolver.getResourceDetectorClusterName(resourceDetectorAttributes) - resourceDetectorAttributes.PutStr(attr.ResourceDetectionClusterName, "DetectedClusterName") assert.Equal(t, resourceDetectorClusterName, "test-cluster") + resourceDetectorAttributes.PutStr(attr.ResourceDetectionClusterName, "DetectedClusterName") resourceDetectorClusterName = resolver.getResourceDetectorClusterName(resourceDetectorAttributes) assert.Equal(t, resourceDetectorClusterName, "DetectedClusterName") + resourceDetectorAttributes.PutStr(attr.ResourceDetectionClusterName, "") + resourceDetectorClusterName = resolver.getResourceDetectorClusterName(resourceDetectorAttributes) + assert.Equal(t, resourceDetectorClusterName, "test-cluster") } func TestK8sResourceAttributesResolverOnK8S(t *testing.T) {