From 1ef8c760a2f8da3fd61c6970d115d7b7c4c6cfc9 Mon Sep 17 00:00:00 2001 From: Leighton Chen Date: Thu, 12 Dec 2024 13:35:54 -0800 Subject: [PATCH] change --- azure_functions_worker/constants.py | 12 ++++-- azure_functions_worker/dispatcher.py | 39 ++++++++++--------- .../utils/app_setting_manager.py | 4 +- tests/unittests/test_opentelemetry.py | 24 ++++++++---- 4 files changed, 48 insertions(+), 31 deletions(-) diff --git a/azure_functions_worker/constants.py b/azure_functions_worker/constants.py index 362b4ab7..8b5d9e62 100644 --- a/azure_functions_worker/constants.py +++ b/azure_functions_worker/constants.py @@ -83,14 +83,18 @@ # Appsetting to turn on OpenTelemetry support/features # A value of "true" enables the setting, defaults to "false" -# Includes turning on Azure monitor distro to send telemetry to AppInsights PYTHON_ENABLE_OPENTELEMETRY = "PYTHON_ENABLE_OPENTELEMETRY" PYTHON_ENABLE_OPENTELEMETRY_DEFAULT = "false" +# Appsetting to turn on ApplicationInsights support/features +# A value of "true" enables the setting, defaults to "false" +PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY = "PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY" +PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY_DEFAULT = "false" + # Appsetting to specify root logger name of logger to collect telemetry for -# Used by Azure monitor distro -PYTHON_AZURE_MONITOR_LOGGER_NAME = "PYTHON_AZURE_MONITOR_LOGGER_NAME" -PYTHON_AZURE_MONITOR_LOGGER_NAME_DEFAULT = "" +# Used by Azure monitor distro (Application Insights) +PYTHON_APPLICATIONINSIGHTS_LOGGER_NAME = "PYTHON_APPLICATIONINSIGHTS_LOGGER_NAME" +PYTHON_APPLICATIONINSIGHTS_LOGGER_NAME_DEFAULT = "" # Appsetting to specify AppInsights connection string APPLICATIONINSIGHTS_CONNECTION_STRING = "APPLICATIONINSIGHTS_CONNECTION_STRING" diff --git a/azure_functions_worker/dispatcher.py b/azure_functions_worker/dispatcher.py index 5b566904..84bf79f3 100644 --- a/azure_functions_worker/dispatcher.py +++ b/azure_functions_worker/dispatcher.py @@ -26,12 +26,12 @@ APPLICATIONINSIGHTS_CONNECTION_STRING, HTTP_URI, METADATA_PROPERTIES_WORKER_INDEXED, - PYTHON_AZURE_MONITOR_LOGGER_NAME, - PYTHON_AZURE_MONITOR_LOGGER_NAME_DEFAULT, + PYTHON_APPLICATIONINSIGHTS_LOGGER_NAME, + PYTHON_APPLICATIONINSIGHTS_LOGGER_NAME_DEFAULT, PYTHON_ENABLE_DEBUG_LOGGING, PYTHON_ENABLE_INIT_INDEXING, - PYTHON_ENABLE_OPENTELEMETRY, - PYTHON_ENABLE_OPENTELEMETRY_DEFAULT, + PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY, + PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY_DEFAULT, PYTHON_LANGUAGE_RUNTIME, PYTHON_ROLLBACK_CWD_PATH, PYTHON_SCRIPT_FILE_NAME, @@ -103,8 +103,10 @@ def __init__(self, loop: BaseEventLoop, host: str, port: int, self._function_metadata_result = None self._function_metadata_exception = None - # Used for checking if open telemetry is enabled + # Used for checking if appinsights is enabled self._azure_monitor_available = False + # Used for checking if open telemetry is enabled + self._otel_libs_available = False self._context_api = None self._trace_context_propagator = None @@ -318,8 +320,8 @@ def initialize_azure_monitor(self): setting=APPLICATIONINSIGHTS_CONNECTION_STRING ), logger_name=get_app_setting( - setting=PYTHON_AZURE_MONITOR_LOGGER_NAME, - default_value=PYTHON_AZURE_MONITOR_LOGGER_NAME_DEFAULT + setting=PYTHON_APPLICATIONINSIGHTS_LOGGER_NAME, + default_value=PYTHON_APPLICATIONINSIGHTS_LOGGER_NAME_DEFAULT ), ) self._azure_monitor_available = True @@ -381,15 +383,16 @@ async def _handle__worker_init_request(self, request): constants.RPC_HTTP_TRIGGER_METADATA_REMOVED: _TRUE, constants.SHARED_MEMORY_DATA_TRANSFER: _TRUE, } + opentelemetry_app_setting = get_app_setting( - setting=PYTHON_ENABLE_OPENTELEMETRY, - default_value=PYTHON_ENABLE_OPENTELEMETRY_DEFAULT, + setting=PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY, + default_value=PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY_DEFAULT, ) if opentelemetry_app_setting and opentelemetry_app_setting.lower() == "true": self.initialize_azure_monitor() - if self._azure_monitor_available: - capabilities[constants.WORKER_OPEN_TELEMETRY_ENABLED] = _TRUE + if self._azure_monitor_available or self._otel_libs_available: + capabilities[constants.WORKER_OPEN_TELEMETRY_ENABLED] = _TRUE if DependencyManager.should_load_cx_dependencies(): DependencyManager.prioritize_customer_dependencies() @@ -665,7 +668,7 @@ async def _handle__invocation_request(self, request): args[name] = bindings.Out() if fi.is_async: - if self._azure_monitor_available: + if self._azure_monitor_available or self._otel_libs_available: self.configure_opentelemetry(fi_context) call_result = \ @@ -783,13 +786,13 @@ async def _handle__function_environment_reload_request(self, request): capabilities = {} if get_app_setting( - setting=PYTHON_ENABLE_OPENTELEMETRY, - default_value=PYTHON_ENABLE_OPENTELEMETRY_DEFAULT): + setting=PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY, + default_value=PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY_DEFAULT): self.initialize_azure_monitor() - if self._azure_monitor_available: - capabilities[constants.WORKER_OPEN_TELEMETRY_ENABLED] = ( - _TRUE) + if self._azure_monitor_available or self._otel_libs_available: + capabilities[constants.WORKER_OPEN_TELEMETRY_ENABLED] = ( + _TRUE) if is_envvar_true(PYTHON_ENABLE_INIT_INDEXING): try: @@ -999,7 +1002,7 @@ def _run_sync_func(self, invocation_id, context, func, params): # invocation_id from ThreadPoolExecutor's threads. context.thread_local_storage.invocation_id = invocation_id try: - if self._azure_monitor_available: + if self._azure_monitor_available or self._otel_libs_available: self.configure_opentelemetry(context) return ExtensionManager.get_sync_invocation_wrapper(context, func)(params) diff --git a/azure_functions_worker/utils/app_setting_manager.py b/azure_functions_worker/utils/app_setting_manager.py index 3d8ccbb4..ee43ccd6 100644 --- a/azure_functions_worker/utils/app_setting_manager.py +++ b/azure_functions_worker/utils/app_setting_manager.py @@ -7,6 +7,7 @@ FUNCTIONS_WORKER_SHARED_MEMORY_DATA_TRANSFER_ENABLED, PYTHON_ENABLE_DEBUG_LOGGING, PYTHON_ENABLE_INIT_INDEXING, + PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY, PYTHON_ENABLE_OPENTELEMETRY, PYTHON_ENABLE_WORKER_EXTENSIONS, PYTHON_ENABLE_WORKER_EXTENSIONS_DEFAULT, @@ -29,7 +30,8 @@ def get_python_appsetting_state(): FUNCTIONS_WORKER_SHARED_MEMORY_DATA_TRANSFER_ENABLED, PYTHON_SCRIPT_FILE_NAME, PYTHON_ENABLE_INIT_INDEXING, - PYTHON_ENABLE_OPENTELEMETRY] + PYTHON_ENABLE_OPENTELEMETRY, + PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY] app_setting_states = "".join( f"{app_setting}: {current_vars[app_setting]} | " diff --git a/tests/unittests/test_opentelemetry.py b/tests/unittests/test_opentelemetry.py index e32c426d..883406ea 100644 --- a/tests/unittests/test_opentelemetry.py +++ b/tests/unittests/test_opentelemetry.py @@ -23,8 +23,9 @@ def test_update_opentelemetry_status_import_error(self): # Patch the built-in import mechanism with patch('builtins.__import__', side_effect=ImportError): self.dispatcher.update_opentelemetry_status() - # Verify that otel_libs_available is set to False due to ImportError - self.assertFalse(self.dispatcher._azure_monitor_available) + # Verify that context variables are None due to ImportError + self.assertIsNone(self.dispatcher._context_api) + self.assertIsNone(self.dispatcher._trace_context_propagator) @patch('builtins.__import__') def test_update_opentelemetry_status_success( @@ -54,12 +55,12 @@ def test_initialize_azure_monitor_import_error( with patch('builtins.__import__', side_effect=ImportError): self.dispatcher.initialize_azure_monitor() mock_update_ot.assert_called_once() - # Verify that otel_libs_available is set to False due to ImportError + # Verify that azure_monitor_available is set to False due to ImportError self.assertFalse(self.dispatcher._azure_monitor_available) - @patch.dict(os.environ, {'PYTHON_ENABLE_OPENTELEMETRY': 'true'}) + @patch.dict(os.environ, {'PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY': 'true'}) @patch('builtins.__import__') - def test_init_request_otel_capability_enabled_app_setting( + def test_init_request_initialize_azure_monitor_enabled_app_setting( self, mock_imports, ): @@ -78,13 +79,15 @@ def test_init_request_otel_capability_enabled_app_setting( self.assertEqual(init_response.worker_init_response.result.status, protos.StatusResult.Success) + # Verify azure_monitor_available is set to True + self.assertTrue(self.dispatcher._azure_monitor_available) # Verify that WorkerOpenTelemetryEnabled capability is set to _TRUE capabilities = init_response.worker_init_response.capabilities self.assertIn("WorkerOpenTelemetryEnabled", capabilities) self.assertEqual(capabilities["WorkerOpenTelemetryEnabled"], "true") @patch("azure_functions_worker.dispatcher.Dispatcher.initialize_azure_monitor") - def test_init_request_otel_capability_default_app_setting( + def test_init_request_initialize_azure_monitor_default_app_setting( self, mock_initialize_azmon, ): @@ -103,15 +106,18 @@ def test_init_request_otel_capability_default_app_setting( protos.StatusResult.Success) # Azure monitor initialized not called + # Since default behavior is not enabled mock_initialize_azmon.assert_not_called() + # Verify azure_monitor_available is set to False + self.assertFalse(self.dispatcher._azure_monitor_available) # Verify that WorkerOpenTelemetryEnabled capability is not set capabilities = init_response.worker_init_response.capabilities self.assertNotIn("WorkerOpenTelemetryEnabled", capabilities) - @patch.dict(os.environ, {'PYTHON_ENABLE_OPENTELEMETRY': 'false'}) + @patch.dict(os.environ, {'PYTHON_APPLICATIONINSIGHTS_ENABLE_TELEMETRY': 'false'}) @patch("azure_functions_worker.dispatcher.Dispatcher.initialize_azure_monitor") - def test_init_request_otel_capability_disabled_app_setting( + def test_init_request_initialize_azure_monitor_disabled_app_setting( self, mock_initialize_azmon, ): @@ -132,6 +138,8 @@ def test_init_request_otel_capability_disabled_app_setting( # Azure monitor initialized not called mock_initialize_azmon.assert_not_called() + # Verify azure_monitor_available is set to False + self.assertFalse(self.dispatcher._azure_monitor_available) # Verify that WorkerOpenTelemetryEnabled capability is not set capabilities = init_response.worker_init_response.capabilities self.assertNotIn("WorkerOpenTelemetryEnabled", capabilities)