diff --git a/sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md b/sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md index d0e3cb2ba25e..85c8b994e394 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md +++ b/sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md @@ -1,14 +1,11 @@ # Release History -## 1.6.7 (Unreleased) - -### Features Added - -### Breaking Changes +## 1.6.7 (2025-04-10) ### Bugs Fixed -### Other Changes +- Adapt to OpenTelemetry dependency resolver change. + ([#40463](https://github.com/Azure/azure-sdk-for-python/pull/40463)) ## 1.6.6 (2025-04-07) diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py index ae14fdda2788..f1a48d0a63b5 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py +++ b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py @@ -3,14 +3,13 @@ # Licensed under the MIT License. See License in the project root for # license information. # -------------------------------------------------------------------------- -from functools import cached_property from logging import getLogger, Formatter from typing import Dict, List, cast from opentelemetry._events import _set_event_logger_provider from opentelemetry._logs import set_logger_provider from opentelemetry.instrumentation.dependencies import ( - get_dist_dependency_conflicts, + DependencyConflictError, ) from opentelemetry.instrumentation.instrumentor import ( # type: ignore BaseInstrumentor, @@ -26,11 +25,8 @@ from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.trace import set_tracer_provider -from opentelemetry.util._importlib_metadata import ( - EntryPoint, - distributions, - entry_points, -) +from opentelemetry.util._importlib_metadata import entry_points + from azure.core.settings import settings from azure.core.tracing.ext.opentelemetry_span import OpenTelemetrySpan @@ -211,25 +207,8 @@ def _setup_live_metrics(configurations): enable_live_metrics(**configurations) -class _EntryPointDistFinder: - @cached_property - def _mapping(self): - return {self._key_for(ep): dist for dist in distributions() for ep in dist.entry_points} - - def dist_for(self, entry_point: EntryPoint): - dist = getattr(entry_point, "dist", None) - if dist: - return dist - - return self._mapping.get(self._key_for(entry_point)) - - @staticmethod - def _key_for(entry_point: EntryPoint): - return f"{entry_point.group}:{entry_point.name}:{entry_point.value}" - - def _setup_instrumentations(configurations: Dict[str, ConfigurationValue]): - entry_point_finder = _EntryPointDistFinder() + # entry_point_finder = _EntryPointDistFinder() # use pkg_resources for now until https://github.com/open-telemetry/opentelemetry-python/pull/3168 is merged for entry_point in entry_points(group="opentelemetry_instrumentor"): lib_name = entry_point.name @@ -239,20 +218,16 @@ def _setup_instrumentations(configurations: Dict[str, ConfigurationValue]): _logger.debug("Instrumentation skipped for library %s", entry_point.name) continue try: - # Check if dependent libraries/version are installed - entry_point_dist = entry_point_finder.dist_for(entry_point) # type: ignore - conflict = get_dist_dependency_conflicts(entry_point_dist) # type: ignore - if conflict: - _logger.debug( - "Skipping instrumentation %s: %s", - entry_point.name, - conflict, - ) - continue # Load the instrumentor via entrypoint instrumentor: BaseInstrumentor = entry_point.load() - # tell instrumentation to not run dep checks again as we already did it above - instrumentor().instrument(skip_dep_check=True) + instrumentor().instrument(raise_exception_on_conflict=True) + except DependencyConflictError as exc: + _logger.debug( + "Skipping instrumentation %s: %s", + entry_point.name, + exc.conflict, + ) + continue except Exception as ex: # pylint: disable=broad-except _logger.warning( "Exception occurred when instrumenting: %s.", diff --git a/sdk/monitor/azure-monitor-opentelemetry/setup.py b/sdk/monitor/azure-monitor-opentelemetry/setup.py index 4898d3be5a20..9e519edaf9cc 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/setup.py +++ b/sdk/monitor/azure-monitor-opentelemetry/setup.py @@ -84,15 +84,15 @@ "azure-core<2.0.0,>=1.28.0", "azure-core-tracing-opentelemetry~=1.0.0b11", "azure-monitor-opentelemetry-exporter~=1.0.0b31", - "opentelemetry-instrumentation-django~=0.49b0", - "opentelemetry-instrumentation-fastapi~=0.49b0", - "opentelemetry-instrumentation-flask~=0.49b0", - "opentelemetry-instrumentation-psycopg2~=0.49b0", - "opentelemetry-instrumentation-requests~=0.49b0", - "opentelemetry-instrumentation-urllib~=0.49b0", - "opentelemetry-instrumentation-urllib3~=0.49b0", + "opentelemetry-instrumentation-django~=0.53b0", + "opentelemetry-instrumentation-fastapi~=0.53b0", + "opentelemetry-instrumentation-flask~=0.53b0", + "opentelemetry-instrumentation-psycopg2~=0.53b0", + "opentelemetry-instrumentation-requests~=0.53b0", + "opentelemetry-instrumentation-urllib~=0.53b0", + "opentelemetry-instrumentation-urllib3~=0.53b0", "opentelemetry-resource-detector-azure~=0.1.4", - "opentelemetry-sdk~=1.28", + "opentelemetry-sdk~=1.32", ], entry_points={ "opentelemetry_distro": [ diff --git a/sdk/monitor/azure-monitor-opentelemetry/tests/test_configure.py b/sdk/monitor/azure-monitor-opentelemetry/tests/test_configure.py index a6cb1dae37ea..7db014acd841 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/tests/test_configure.py +++ b/sdk/monitor/azure-monitor-opentelemetry/tests/test_configure.py @@ -14,6 +14,10 @@ import unittest from unittest.mock import Mock, call, patch +from opentelemetry.instrumentation.dependencies import ( + DependencyConflict, + DependencyConflictError, +) from opentelemetry.sdk._logs import LoggingHandler from opentelemetry.sdk.resources import Resource @@ -533,12 +537,10 @@ def test_setup_live_metrics( @patch("azure.monitor.opentelemetry._configure._ALL_SUPPORTED_INSTRUMENTED_LIBRARIES", ("test_instr2")) @patch("azure.monitor.opentelemetry._configure._is_instrumentation_enabled") - @patch("azure.monitor.opentelemetry._configure.get_dist_dependency_conflicts") @patch("azure.monitor.opentelemetry._configure.entry_points") def test_setup_instrumentations_lib_not_supported( self, iter_mock, - dep_mock, enabled_mock, ): ep_mock = Mock() @@ -550,10 +552,8 @@ def test_setup_instrumentations_lib_not_supported( ep_mock.name = "test_instr1" ep2_mock.name = "test_instr2" ep2_mock.load.return_value = instr_class_mock - dep_mock.return_value = None enabled_mock.return_value = True _setup_instrumentations({}) - dep_mock.assert_called_with(ep2_mock.dist) ep_mock.load.assert_not_called() ep2_mock.load.assert_called_once() instrumentor_mock.instrument.assert_called_once() @@ -579,12 +579,10 @@ def test_setup_instrumentations_additional_azure( @patch("azure.monitor.opentelemetry._configure._ALL_SUPPORTED_INSTRUMENTED_LIBRARIES", ("test_instr")) @patch("azure.monitor.opentelemetry._configure._is_instrumentation_enabled") @patch("azure.monitor.opentelemetry._configure._logger") - @patch("azure.monitor.opentelemetry._configure.get_dist_dependency_conflicts") @patch("azure.monitor.opentelemetry._configure.entry_points") def test_setup_instrumentations_conflict( self, iter_mock, - dep_mock, logger_mock, enabled_mock, ): @@ -595,23 +593,24 @@ def test_setup_instrumentations_conflict( instr_class_mock.return_value = instrumentor_mock ep_mock.name = "test_instr" ep_mock.load.return_value = instr_class_mock - dep_mock.return_value = True + instrumentor_mock.instrument.side_effect = DependencyConflictError( + DependencyConflict( + required="test_instr" + ) + ) enabled_mock.return_value = True _setup_instrumentations({}) - dep_mock.assert_called_with(ep_mock.dist) - ep_mock.load.assert_not_called() - instrumentor_mock.instrument.assert_not_called() + ep_mock.load.assert_called_once() + instrumentor_mock.instrument.assert_called_once() logger_mock.debug.assert_called_once() @patch("azure.monitor.opentelemetry._configure._ALL_SUPPORTED_INSTRUMENTED_LIBRARIES", ("test_instr")) @patch("azure.monitor.opentelemetry._configure._is_instrumentation_enabled") @patch("azure.monitor.opentelemetry._configure._logger") - @patch("azure.monitor.opentelemetry._configure.get_dist_dependency_conflicts") @patch("azure.monitor.opentelemetry._configure.entry_points") def test_setup_instrumentations_exception( self, iter_mock, - dep_mock, logger_mock, enabled_mock, ): @@ -622,10 +621,8 @@ def test_setup_instrumentations_exception( instr_class_mock.return_value = instrumentor_mock ep_mock.name = "test_instr" ep_mock.load.side_effect = Exception() - dep_mock.return_value = None enabled_mock.return_value = True _setup_instrumentations({}) - dep_mock.assert_called_with(ep_mock.dist) ep_mock.load.assert_called_once() instrumentor_mock.instrument.assert_not_called() logger_mock.warning.assert_called_once() @@ -635,12 +632,10 @@ def test_setup_instrumentations_exception( ) @patch("azure.monitor.opentelemetry._configure._is_instrumentation_enabled") @patch("azure.monitor.opentelemetry._configure._logger") - @patch("azure.monitor.opentelemetry._configure.get_dist_dependency_conflicts") @patch("azure.monitor.opentelemetry._configure.entry_points") def test_setup_instrumentations_disabled( self, iter_mock, - dep_mock, logger_mock, enabled_mock, ): @@ -653,10 +648,8 @@ def test_setup_instrumentations_disabled( ep_mock.name = "test_instr1" ep2_mock.name = "test_instr2" ep2_mock.load.return_value = instr_class_mock - dep_mock.return_value = None enabled_mock.side_effect = [False, True] _setup_instrumentations({}) - dep_mock.assert_called_with(ep2_mock.dist) ep_mock.load.assert_not_called() ep2_mock.load.assert_called_once() instrumentor_mock.instrument.assert_called_once()