diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md b/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md index f69f31d87593..c152174f20d2 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md @@ -23,6 +23,8 @@ ([#39886](https://github.com/Azure/azure-sdk-for-python/pull/39886)) - Populate `client_Ip` on `customEvent` telemetry ([#39923](https://github.com/Azure/azure-sdk-for-python/pull/39923)) +- Update AKS check to use KUBERNETES_SERVICE_HOST + ([#39941](https://github.com/Azure/azure-sdk-for-python/pull/39941)) ### Bugs Fixed diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_constants.py b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_constants.py index a82881e22406..6b4004042915 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_constants.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_constants.py @@ -24,6 +24,7 @@ _FUNCTIONS_WORKER_RUNTIME = "FUNCTIONS_WORKER_RUNTIME" _PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY = "PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY" _AKS_ARM_NAMESPACE_ID = "AKS_ARM_NAMESPACE_ID" +_KUBERNETES_SERVICE_HOST = "KUBERNETES_SERVICE_HOST" # Network 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 e1a4fc791e9a..790bca6b420a 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 @@ -23,8 +23,9 @@ from azure.monitor.opentelemetry.exporter._constants import ( _AKS_ARM_NAMESPACE_ID, _DEFAULT_AAD_SCOPE, - _INSTRUMENTATIONS_BIT_MAP, _FUNCTIONS_WORKER_RUNTIME, + _INSTRUMENTATIONS_BIT_MAP, + _KUBERNETES_SERVICE_HOST, _PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY, _WEBSITE_SITE_NAME, ) @@ -63,7 +64,7 @@ def _is_on_functions(): def _is_on_aks(): - return _AKS_ARM_NAMESPACE_ID in environ + return _AKS_ARM_NAMESPACE_ID in environ or _KUBERNETES_SERVICE_HOST in environ # Attach @@ -74,6 +75,8 @@ def _is_attach_enabled(): return isdir("/agents/python/") if _is_on_functions(): return environ.get(_PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY) == "true" + if _is_on_aks(): + return _AKS_ARM_NAMESPACE_ID in environ return False diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/statsbeat/_statsbeat_metrics.py b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/statsbeat/_statsbeat_metrics.py index db84e01b062e..47647565c22e 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/statsbeat/_statsbeat_metrics.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/statsbeat/_statsbeat_metrics.py @@ -18,6 +18,7 @@ from azure.monitor.opentelemetry.exporter._constants import ( _ATTACH_METRIC_NAME, _FEATURE_METRIC_NAME, + _KUBERNETES_SERVICE_HOST, _REQ_DURATION_NAME, _REQ_EXCEPTION_NAME, _REQ_FAILURE_NAME, @@ -187,7 +188,10 @@ def _get_attach_metric(self, options: CallbackOptions) -> Iterable[Observation]: elif _utils._is_on_aks(): # AKS rp = _RP_Names.AKS.value - rpId = os.environ.get(_AKS_ARM_NAMESPACE_ID, "") + if _AKS_ARM_NAMESPACE_ID in os.environ: + rpId = os.environ.get(_AKS_ARM_NAMESPACE_ID, "") + else: + rpId = os.environ.get(_KUBERNETES_SERVICE_HOST , "") elif self._vm_retry and self._get_azure_compute_metadata(): # VM rp = _RP_Names.VM.value diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/statsbeat/test_statsbeat.py b/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/statsbeat/test_statsbeat.py index 3c472c554d76..eff9d23365ce 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/statsbeat/test_statsbeat.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/statsbeat/test_statsbeat.py @@ -447,9 +447,10 @@ def test_get_attach_metric_functions(self, metadata_mock): os.environ, { "AKS_ARM_NAMESPACE_ID": "namespace_id", + "KUBERNETES_SERVICE_HOST": "TEST_KUBERNETES_SERVICE_HOST", }, ) - def test_get_attach_metric_aks(self): + def test_get_attach_metric_aks_attach(self): attributes = dict(_StatsbeatMetrics._COMMON_ATTRIBUTES) self.assertEqual(attributes["rp"], _RP_Names.UNKNOWN.value) attributes["rp"] = _RP_Names.AKS.value @@ -460,6 +461,24 @@ def test_get_attach_metric_aks(self): self.assertEqual(obs.attributes, attributes) self.assertEqual(_StatsbeatMetrics._COMMON_ATTRIBUTES["rp"], _RP_Names.AKS.value) + # pylint: disable=protected-access + @mock.patch.dict( + os.environ, + { + "KUBERNETES_SERVICE_HOST": "TEST_KUBERNETES_SERVICE_HOST", + }, + ) + def test_get_attach_metric_aks_manual(self): + attributes = dict(_StatsbeatMetrics._COMMON_ATTRIBUTES) + self.assertEqual(attributes["rp"], _RP_Names.UNKNOWN.value) + attributes["rp"] = _RP_Names.AKS.value + attributes["rpId"] = "TEST_KUBERNETES_SERVICE_HOST" + observations = self._metric._get_attach_metric(options=None) + for obs in observations: + self.assertEqual(obs.value, 1) + self.assertEqual(obs.attributes, attributes) + self.assertEqual(_StatsbeatMetrics._COMMON_ATTRIBUTES["rp"], _RP_Names.AKS.value) + @mock.patch( "azure.monitor.opentelemetry.exporter.statsbeat._statsbeat_metrics._StatsbeatMetrics._get_azure_compute_metadata" ) 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 1617e945ee6b..a34d8b66c643 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/test_utils.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/test_utils.py @@ -29,6 +29,8 @@ TEST_TIMESTAMP = "TEST_TIMESTAMP" TEST_TIME = "TEST_TIME" TEST_WEBSITE_SITE_NAME = "TEST_WEBSITE_SITE_NAME" +TEST_KUBERNETES_SERVICE_HOST = "TEST_KUBERNETES_SERVICE_HOST" +TEST_AKS_ARM_NAMESPACE_ID = "TEST_AKS_ARM_NAMESPACE_ID" class TestUtils(unittest.TestCase): @@ -105,37 +107,37 @@ def test_create_telemetry_item(self, mock_ns_to_iso_str): @patch("azure.monitor.opentelemetry.exporter._utils._is_attach_enabled", return_value=False) @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="") - def test_get_sdk_version_prefix(self, mock_system, mock_getenv): + def test_get_sdk_version_prefix(self, mock_system, mock_isdir): result = _utils._get_sdk_version_prefix() self.assertEqual(result, "uum_") @patch("azure.monitor.opentelemetry.exporter._utils._is_attach_enabled", return_value=False) @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="Linux") - def test_get_sdk_version_prefix_linux(self, mock_system, mock_getenv): + def test_get_sdk_version_prefix_linux(self, mock_system, mock_isdir): result = _utils._get_sdk_version_prefix() self.assertEqual(result, "ulm_") @patch("azure.monitor.opentelemetry.exporter._utils._is_attach_enabled", return_value=False) @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="Windows") - def test_get_sdk_version_prefix_windows(self, mock_system, mock_getenv): + def test_get_sdk_version_prefix_windows(self, mock_system, mock_isdir): result = _utils._get_sdk_version_prefix() self.assertEqual(result, "uwm_") @patch("azure.monitor.opentelemetry.exporter._utils._is_attach_enabled", return_value=True) @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="") - def test_get_sdk_version_prefix_attach(self, mock_system, mock_getenv): + def test_get_sdk_version_prefix_attach(self, mock_system, mock_isdir): result = _utils._get_sdk_version_prefix() self.assertEqual(result, "uui_") @patch("azure.monitor.opentelemetry.exporter._utils._is_attach_enabled", return_value=True) @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="Linux") - def test_get_sdk_version_prefix_attach_linux(self, mock_system, mock_getenv): + def test_get_sdk_version_prefix_attach_linux(self, mock_system, mock_isdir): result = _utils._get_sdk_version_prefix() self.assertEqual(result, "uli_") @patch("azure.monitor.opentelemetry.exporter._utils._is_attach_enabled", return_value=True) @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="Windows") - def test_get_sdk_version_prefix_attach_windows(self, mock_system, mock_getenv): + def test_get_sdk_version_prefix_attach_windows(self, mock_system, mock_isdir): result = _utils._get_sdk_version_prefix() self.assertEqual(result, "uwi_") @@ -146,7 +148,7 @@ def test_get_sdk_version_prefix_attach_windows(self, mock_system, mock_getenv): ) @patch("azure.monitor.opentelemetry.exporter._utils.isdir", return_value=False) @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="") - def test_get_sdk_version_prefix_app_service(self, mock_system, mock_getenv): + def test_get_sdk_version_prefix_app_service(self, mock_system, mock_isdir): result = _utils._get_sdk_version_prefix() self.assertEqual(result, "aum_") @@ -155,7 +157,7 @@ def test_get_sdk_version_prefix_app_service(self, mock_system, mock_getenv): ) @patch("azure.monitor.opentelemetry.exporter._utils.isdir", return_value=False) @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="Linux") - def test_get_sdk_version_prefix_app_service_linux(self, mock_system, mock_getenv): + def test_get_sdk_version_prefix_app_service_linux(self, mock_system, mock_isdir): result = _utils._get_sdk_version_prefix() self.assertEqual(result, "alm_") @@ -164,7 +166,7 @@ def test_get_sdk_version_prefix_app_service_linux(self, mock_system, mock_getenv ) @patch("azure.monitor.opentelemetry.exporter._utils.isdir", return_value=False) @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="Windows") - def test_get_sdk_version_prefix_app_service_windows(self, mock_system, mock_getenv): + def test_get_sdk_version_prefix_app_service_windows(self, mock_system, mock_isdir): result = _utils._get_sdk_version_prefix() self.assertEqual(result, "awm_") @@ -173,7 +175,7 @@ def test_get_sdk_version_prefix_app_service_windows(self, mock_system, mock_gete ) @patch("azure.monitor.opentelemetry.exporter._utils.isdir", return_value=True) @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="") - def test_get_sdk_version_prefix_app_service_attach(self, mock_system, mock_getenv): + def test_get_sdk_version_prefix_app_service_attach(self, mock_system, mock_isdir): result = _utils._get_sdk_version_prefix() self.assertEqual(result, "aui_") @@ -182,7 +184,7 @@ def test_get_sdk_version_prefix_app_service_attach(self, mock_system, mock_geten ) @patch("azure.monitor.opentelemetry.exporter._utils.isdir", return_value=True) @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="Linux") - def test_get_sdk_version_prefix_app_service_linux_attach(self, mock_system, mock_getenv): + def test_get_sdk_version_prefix_app_service_linux_attach(self, mock_system, mock_isdir): result = _utils._get_sdk_version_prefix() self.assertEqual(result, "ali_") @@ -191,7 +193,7 @@ def test_get_sdk_version_prefix_app_service_linux_attach(self, mock_system, mock ) @patch("azure.monitor.opentelemetry.exporter._utils.isdir", return_value=True) @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="Windows") - def test_get_sdk_version_prefix_app_service_windows_attach(self, mock_system, mock_getenv): + def test_get_sdk_version_prefix_app_service_windows_attach(self, mock_system, mock_isdir): result = _utils._get_sdk_version_prefix() self.assertEqual(result, "awi_") @@ -202,9 +204,8 @@ def test_get_sdk_version_prefix_app_service_windows_attach(self, mock_system, mo {"FUNCTIONS_WORKER_RUNTIME": TEST_WEBSITE_SITE_NAME}, clear=True, ) - @patch("azure.monitor.opentelemetry.exporter._utils._is_attach_enabled", return_value=False) @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="") - def test_get_sdk_version_prefix_function(self, mock_system, mock_getenv): + def test_get_sdk_version_prefix_function(self, mock_system): result = _utils._get_sdk_version_prefix() self.assertEqual(result, "fum_") @@ -213,9 +214,8 @@ def test_get_sdk_version_prefix_function(self, mock_system, mock_getenv): {"FUNCTIONS_WORKER_RUNTIME": TEST_WEBSITE_SITE_NAME}, clear=True, ) - @patch("azure.monitor.opentelemetry.exporter._utils._is_attach_enabled", return_value=False) @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="Linux") - def test_get_sdk_version_prefix_function_linux(self, mock_system, mock_getenv): + def test_get_sdk_version_prefix_function_linux(self, mock_system): result = _utils._get_sdk_version_prefix() self.assertEqual(result, "flm_") @@ -224,45 +224,124 @@ def test_get_sdk_version_prefix_function_linux(self, mock_system, mock_getenv): {"FUNCTIONS_WORKER_RUNTIME": TEST_WEBSITE_SITE_NAME}, clear=True, ) - @patch("azure.monitor.opentelemetry.exporter._utils._is_attach_enabled", return_value=False) @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="Windows") - def test_get_sdk_version_prefix_function_windows(self, mock_system, mock_getenv): + def test_get_sdk_version_prefix_function_windows(self, mock_system): result = _utils._get_sdk_version_prefix() self.assertEqual(result, "fwm_") @patch.dict( "azure.monitor.opentelemetry.exporter._utils.environ", - {"FUNCTIONS_WORKER_RUNTIME": TEST_WEBSITE_SITE_NAME}, + { + "FUNCTIONS_WORKER_RUNTIME": TEST_WEBSITE_SITE_NAME, + "PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY": "true", + }, clear=True, ) - @patch("azure.monitor.opentelemetry.exporter._utils._is_attach_enabled", return_value=True) @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="") - def test_get_sdk_version_prefix_function_attach(self, mock_system, mock_getenv): + def test_get_sdk_version_prefix_function_attach(self, mock_system): result = _utils._get_sdk_version_prefix() self.assertEqual(result, "fui_") @patch.dict( "azure.monitor.opentelemetry.exporter._utils.environ", - {"FUNCTIONS_WORKER_RUNTIME": TEST_WEBSITE_SITE_NAME}, + { + "FUNCTIONS_WORKER_RUNTIME": TEST_WEBSITE_SITE_NAME, + "PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY": "true", + }, clear=True, ) - @patch("azure.monitor.opentelemetry.exporter._utils._is_attach_enabled", return_value=True) @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="Linux") - def test_get_sdk_version_prefix_function_linux_attach(self, mock_system, mock_getenv): + def test_get_sdk_version_prefix_function_linux_attach(self, mock_system): result = _utils._get_sdk_version_prefix() self.assertEqual(result, "fli_") @patch.dict( "azure.monitor.opentelemetry.exporter._utils.environ", - {"FUNCTIONS_WORKER_RUNTIME": TEST_WEBSITE_SITE_NAME}, + { + "FUNCTIONS_WORKER_RUNTIME": TEST_WEBSITE_SITE_NAME, + "PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY": "true", + }, clear=True, ) - @patch("azure.monitor.opentelemetry.exporter._utils._is_attach_enabled", return_value=True) @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="Windows") - def test_get_sdk_version_prefix_function_windows_attach(self, mock_system, mock_getenv): + def test_get_sdk_version_prefix_function_windows_attach(self, mock_system): result = _utils._get_sdk_version_prefix() self.assertEqual(result, "fwi_") + # AKS SDK Version Prefix + + @patch.dict( + "azure.monitor.opentelemetry.exporter._utils.environ", + { + "KUBERNETES_SERVICE_HOST": TEST_KUBERNETES_SERVICE_HOST, + }, + clear=True, + ) + @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="") + def test_get_sdk_version_prefix_aks(self, mock_system): + result = _utils._get_sdk_version_prefix() + self.assertEqual(result, "kum_") + + @patch.dict( + "azure.monitor.opentelemetry.exporter._utils.environ", + { + "KUBERNETES_SERVICE_HOST": TEST_KUBERNETES_SERVICE_HOST, + }, + clear=True, + ) + @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="Linux") + def test_get_sdk_version_prefix_aks_linux(self, mock_system): + result = _utils._get_sdk_version_prefix() + self.assertEqual(result, "klm_") + + @patch.dict( + "azure.monitor.opentelemetry.exporter._utils.environ", + { + "KUBERNETES_SERVICE_HOST": TEST_KUBERNETES_SERVICE_HOST, + }, + clear=True, + ) + @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="Windows") + def test_get_sdk_version_prefix_aks_windows(self, mock_system): + result = _utils._get_sdk_version_prefix() + self.assertEqual(result, "kwm_") + + @patch.dict( + "azure.monitor.opentelemetry.exporter._utils.environ", + { + "AKS_ARM_NAMESPACE_ID": TEST_AKS_ARM_NAMESPACE_ID, + }, + clear=True, + ) + @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="") + def test_get_sdk_version_prefix_aks_attach(self, mock_system): + result = _utils._get_sdk_version_prefix() + self.assertEqual(result, "kui_") + + @patch.dict( + "azure.monitor.opentelemetry.exporter._utils.environ", + { + "AKS_ARM_NAMESPACE_ID": TEST_AKS_ARM_NAMESPACE_ID, + }, + clear=True, + ) + @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="Linux") + def test_get_sdk_version_prefix_aks_linux_attach(self, mock_system): + result = _utils._get_sdk_version_prefix() + self.assertEqual(result, "kli_") + + @patch.dict( + "azure.monitor.opentelemetry.exporter._utils.environ", + { + "AKS_ARM_NAMESPACE_ID": TEST_AKS_ARM_NAMESPACE_ID, + }, + clear=True, + ) + @patch("azure.monitor.opentelemetry.exporter._utils.platform.system", return_value="Windows") + def test_get_sdk_version_prefix_aks_windows_attach(self, mock_system): + result = _utils._get_sdk_version_prefix() + self.assertEqual(result, "kwi_") + # Attach @patch( @@ -288,7 +367,22 @@ def test_attach_app_service_disabled(self, mock_isdir): @patch.dict("azure.monitor.opentelemetry.exporter._utils.environ", {}, clear=True) def test_attach_off_app_service_with_agent(self, mock_isdir): # This is not an expected scenario and just tests the default - self.assertEqual(_utils._is_attach_enabled(), False) + self.assertFalse(_utils._is_attach_enabled()) + + @patch.dict("azure.monitor.opentelemetry.exporter._utils.environ", { + "KUBERNETES_SERVICE_HOST": TEST_KUBERNETES_SERVICE_HOST, + "AKS_ARM_NAMESPACE_ID": TEST_AKS_ARM_NAMESPACE_ID, + }, clear=True) + def test_attach_aks(self): + # This is not an expected scenario and just tests the default + self.assertTrue(_utils._is_attach_enabled()) + + @patch.dict("azure.monitor.opentelemetry.exporter._utils.environ", { + "KUBERNETES_SERVICE_HOST": TEST_KUBERNETES_SERVICE_HOST, + }, clear=True) + def test_aks_no_attach(self): + # This is not an expected scenario and just tests the default + self.assertFalse(_utils._is_attach_enabled()) # Synthetic