diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md b/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md index a304408ab63c..0c40b701207c 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md @@ -7,6 +7,8 @@ ### Breaking Changes ### Bugs Fixed +- Kubernetes pod name takes precedence when populating `cloud_RoleInstance` + ([#45884](https://github.com/Azure/azure-sdk-for-python/pull/45884)) ### Other Changes diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_utils.py b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_utils.py index a01120e5a8fa..56bbecb76fe0 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_utils.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_utils.py @@ -297,12 +297,12 @@ def _get_cloud_role(resource: Resource) -> str: def _get_cloud_role_instance(resource: Resource) -> str: - service_instance_id = resource.attributes.get(ResourceAttributes.SERVICE_INSTANCE_ID) - if service_instance_id: - return service_instance_id # type: ignore k8s_pod_name = resource.attributes.get(ResourceAttributes.K8S_POD_NAME) if k8s_pod_name: return k8s_pod_name # type: ignore + service_instance_id = resource.attributes.get(ResourceAttributes.SERVICE_INSTANCE_ID) + if service_instance_id: + return service_instance_id # type: ignore return platform.node() # hostname default diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/test_utils.py b/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/test_utils.py index 984c056014dd..9fa97b201edb 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/test_utils.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/test_utils.py @@ -316,9 +316,49 @@ def test_populate_part_a_fields_aks_with_service(self): tags = _utils._populate_part_a_fields(resource) self.assertIsNotNone(tags) self.assertEqual(tags.get("ai.cloud.role"), "testServiceName") + self.assertEqual(tags.get("ai.cloud.roleInstance"), "testPodName") + self.assertEqual(tags.get("ai.internal.nodeName"), tags.get("ai.cloud.roleInstance")) + + def test_populate_part_a_fields_uses_service_instance_id_when_pod_name_empty(self): + resource = Resource( + { + "service.name": "testServiceName", + "service.instance.id": "testServiceInstanceId", + "k8s.deployment.name": "testDeploymentName", + "k8s.replicaset.name": "testReplicaSetName", + "k8s.statefulset.name": "testStatefulSetName", + "k8s.job.name": "testJobName", + "k8s.cronjob.name": "testCronJobName", + "k8s.daemonset.name": "testDaemonSetName", + "k8s.pod.name": "", + } + ) + tags = _utils._populate_part_a_fields(resource) + self.assertIsNotNone(tags) + self.assertEqual(tags.get("ai.cloud.role"), "testServiceName") self.assertEqual(tags.get("ai.cloud.roleInstance"), "testServiceInstanceId") self.assertEqual(tags.get("ai.internal.nodeName"), tags.get("ai.cloud.roleInstance")) + def test_populate_part_a_fields_falls_back_to_hostname_when_pod_and_instance_id_empty(self): + resource = Resource( + { + "service.name": "testServiceName", + "service.instance.id": "", + "k8s.deployment.name": "testDeploymentName", + "k8s.replicaset.name": "testReplicaSetName", + "k8s.statefulset.name": "testStatefulSetName", + "k8s.job.name": "testJobName", + "k8s.cronjob.name": "testCronJobName", + "k8s.daemonset.name": "testDaemonSetName", + "k8s.pod.name": "", + } + ) + tags = _utils._populate_part_a_fields(resource) + self.assertIsNotNone(tags) + self.assertEqual(tags.get("ai.cloud.role"), "testServiceName") + self.assertEqual(tags.get("ai.cloud.roleInstance"), platform.node()) + self.assertEqual(tags.get("ai.internal.nodeName"), tags.get("ai.cloud.roleInstance")) + # Default service.name fields should be ignored when kubernetes values are present def test_populate_part_a_fields_aks_with_unknown_service(self): resource = Resource(