Skip to content

Commit 26d6821

Browse files
authored
Distro 1.6.8 hotfix: pin OT 1.31.1/0.52b1 (#40529)
* hotfix: pin OT 1.31/0.52b0 * update versions and changelog * expand range * comment * revert 1.6.7 changes
1 parent f79d1c7 commit 26d6821

File tree

4 files changed

+68
-37
lines changed

4 files changed

+68
-37
lines changed

sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md

+4-6
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,18 @@
22

33
## 1.6.8 (Unreleased)
44

5-
### Features Added
6-
7-
### Breaking Changes
8-
95
### Bugs Fixed
106

7+
- Pin OTel before breaking change.
8+
([#40529](https://github.com/Azure/azure-sdk-for-python/pull/40529))
9+
1110
### Other Changes
1211

1312
## 1.6.7 (2025-04-10)
1413

1514
### Bugs Fixed
1615

17-
- Adapt to OpenTelemetry dependency resolver change.
18-
([#40463](https://github.com/Azure/azure-sdk-for-python/pull/40463))
16+
### Other Changes
1917

2018
## 1.6.6 (2025-04-07)
2119

sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py

+37-12
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
# Licensed under the MIT License. See License in the project root for
44
# license information.
55
# --------------------------------------------------------------------------
6+
from functools import cached_property
67
from logging import getLogger, Formatter
78
from typing import Dict, List, cast
89

910
from opentelemetry._events import _set_event_logger_provider
1011
from opentelemetry._logs import set_logger_provider
1112
from opentelemetry.instrumentation.dependencies import (
12-
DependencyConflictError,
13+
get_dist_dependency_conflicts,
1314
)
1415
from opentelemetry.instrumentation.instrumentor import ( # type: ignore
1516
BaseInstrumentor,
@@ -25,8 +26,11 @@
2526
from opentelemetry.sdk.trace import TracerProvider
2627
from opentelemetry.sdk.trace.export import BatchSpanProcessor
2728
from opentelemetry.trace import set_tracer_provider
28-
from opentelemetry.util._importlib_metadata import entry_points
29-
29+
from opentelemetry.util._importlib_metadata import (
30+
EntryPoint,
31+
distributions,
32+
entry_points,
33+
)
3034

3135
from azure.core.settings import settings
3236
from azure.core.tracing.ext.opentelemetry_span import OpenTelemetrySpan
@@ -207,8 +211,25 @@ def _setup_live_metrics(configurations):
207211
enable_live_metrics(**configurations)
208212

209213

214+
class _EntryPointDistFinder:
215+
@cached_property
216+
def _mapping(self):
217+
return {self._key_for(ep): dist for dist in distributions() for ep in dist.entry_points}
218+
219+
def dist_for(self, entry_point: EntryPoint):
220+
dist = getattr(entry_point, "dist", None)
221+
if dist:
222+
return dist
223+
224+
return self._mapping.get(self._key_for(entry_point))
225+
226+
@staticmethod
227+
def _key_for(entry_point: EntryPoint):
228+
return f"{entry_point.group}:{entry_point.name}:{entry_point.value}"
229+
230+
210231
def _setup_instrumentations(configurations: Dict[str, ConfigurationValue]):
211-
# entry_point_finder = _EntryPointDistFinder()
232+
entry_point_finder = _EntryPointDistFinder()
212233
# use pkg_resources for now until https://github.com/open-telemetry/opentelemetry-python/pull/3168 is merged
213234
for entry_point in entry_points(group="opentelemetry_instrumentor"):
214235
lib_name = entry_point.name
@@ -218,16 +239,20 @@ def _setup_instrumentations(configurations: Dict[str, ConfigurationValue]):
218239
_logger.debug("Instrumentation skipped for library %s", entry_point.name)
219240
continue
220241
try:
242+
# Check if dependent libraries/version are installed
243+
entry_point_dist = entry_point_finder.dist_for(entry_point) # type: ignore
244+
conflict = get_dist_dependency_conflicts(entry_point_dist) # type: ignore
245+
if conflict:
246+
_logger.debug(
247+
"Skipping instrumentation %s: %s",
248+
entry_point.name,
249+
conflict,
250+
)
251+
continue
221252
# Load the instrumentor via entrypoint
222253
instrumentor: BaseInstrumentor = entry_point.load()
223-
instrumentor().instrument(raise_exception_on_conflict=True)
224-
except DependencyConflictError as exc:
225-
_logger.debug(
226-
"Skipping instrumentation %s: %s",
227-
entry_point.name,
228-
exc.conflict,
229-
)
230-
continue
254+
# tell instrumentation to not run dep checks again as we already did it above
255+
instrumentor().instrument(skip_dep_check=True)
231256
except Exception as ex: # pylint: disable=broad-except
232257
_logger.warning(
233258
"Exception occurred when instrumenting: %s.",

sdk/monitor/azure-monitor-opentelemetry/setup.py

+9-8
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,16 @@
8484
"azure-core<2.0.0,>=1.28.0",
8585
"azure-core-tracing-opentelemetry~=1.0.0b11",
8686
"azure-monitor-opentelemetry-exporter~=1.0.0b31",
87-
"opentelemetry-instrumentation-django~=0.53b0",
88-
"opentelemetry-instrumentation-fastapi~=0.53b0",
89-
"opentelemetry-instrumentation-flask~=0.53b0",
90-
"opentelemetry-instrumentation-psycopg2~=0.53b0",
91-
"opentelemetry-instrumentation-requests~=0.53b0",
92-
"opentelemetry-instrumentation-urllib~=0.53b0",
93-
"opentelemetry-instrumentation-urllib3~=0.53b0",
87+
# TODO: Unpin once breaking change in 1.32.0/0.53b0 is resolved.
88+
"opentelemetry-instrumentation-django<0.53b0,>=0.49b0",
89+
"opentelemetry-instrumentation-fastapi<0.53b0,>=0.49b0",
90+
"opentelemetry-instrumentation-flask<0.53b0,>=0.49b0",
91+
"opentelemetry-instrumentation-psycopg2<0.53b0,>=0.49b0",
92+
"opentelemetry-instrumentation-requests<0.53b0,>=0.49b0",
93+
"opentelemetry-instrumentation-urllib<0.53b0,>=0.49b0",
94+
"opentelemetry-instrumentation-urllib3<0.53b0,>=0.49b0",
9495
"opentelemetry-resource-detector-azure~=0.1.4",
95-
"opentelemetry-sdk~=1.32",
96+
"opentelemetry-sdk<1.32,>=1.28.0",
9697
],
9798
entry_points={
9899
"opentelemetry_distro": [

sdk/monitor/azure-monitor-opentelemetry/tests/test_configure.py

+18-11
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@
1414
import unittest
1515
from unittest.mock import Mock, call, patch
1616

17-
from opentelemetry.instrumentation.dependencies import (
18-
DependencyConflict,
19-
DependencyConflictError,
20-
)
2117
from opentelemetry.sdk._logs import LoggingHandler
2218
from opentelemetry.sdk.resources import Resource
2319

@@ -537,10 +533,12 @@ def test_setup_live_metrics(
537533

538534
@patch("azure.monitor.opentelemetry._configure._ALL_SUPPORTED_INSTRUMENTED_LIBRARIES", ("test_instr2"))
539535
@patch("azure.monitor.opentelemetry._configure._is_instrumentation_enabled")
536+
@patch("azure.monitor.opentelemetry._configure.get_dist_dependency_conflicts")
540537
@patch("azure.monitor.opentelemetry._configure.entry_points")
541538
def test_setup_instrumentations_lib_not_supported(
542539
self,
543540
iter_mock,
541+
dep_mock,
544542
enabled_mock,
545543
):
546544
ep_mock = Mock()
@@ -552,8 +550,10 @@ def test_setup_instrumentations_lib_not_supported(
552550
ep_mock.name = "test_instr1"
553551
ep2_mock.name = "test_instr2"
554552
ep2_mock.load.return_value = instr_class_mock
553+
dep_mock.return_value = None
555554
enabled_mock.return_value = True
556555
_setup_instrumentations({})
556+
dep_mock.assert_called_with(ep2_mock.dist)
557557
ep_mock.load.assert_not_called()
558558
ep2_mock.load.assert_called_once()
559559
instrumentor_mock.instrument.assert_called_once()
@@ -579,10 +579,12 @@ def test_setup_instrumentations_additional_azure(
579579
@patch("azure.monitor.opentelemetry._configure._ALL_SUPPORTED_INSTRUMENTED_LIBRARIES", ("test_instr"))
580580
@patch("azure.monitor.opentelemetry._configure._is_instrumentation_enabled")
581581
@patch("azure.monitor.opentelemetry._configure._logger")
582+
@patch("azure.monitor.opentelemetry._configure.get_dist_dependency_conflicts")
582583
@patch("azure.monitor.opentelemetry._configure.entry_points")
583584
def test_setup_instrumentations_conflict(
584585
self,
585586
iter_mock,
587+
dep_mock,
586588
logger_mock,
587589
enabled_mock,
588590
):
@@ -593,24 +595,23 @@ def test_setup_instrumentations_conflict(
593595
instr_class_mock.return_value = instrumentor_mock
594596
ep_mock.name = "test_instr"
595597
ep_mock.load.return_value = instr_class_mock
596-
instrumentor_mock.instrument.side_effect = DependencyConflictError(
597-
DependencyConflict(
598-
required="test_instr"
599-
)
600-
)
598+
dep_mock.return_value = True
601599
enabled_mock.return_value = True
602600
_setup_instrumentations({})
603-
ep_mock.load.assert_called_once()
604-
instrumentor_mock.instrument.assert_called_once()
601+
dep_mock.assert_called_with(ep_mock.dist)
602+
ep_mock.load.assert_not_called()
603+
instrumentor_mock.instrument.assert_not_called()
605604
logger_mock.debug.assert_called_once()
606605

607606
@patch("azure.monitor.opentelemetry._configure._ALL_SUPPORTED_INSTRUMENTED_LIBRARIES", ("test_instr"))
608607
@patch("azure.monitor.opentelemetry._configure._is_instrumentation_enabled")
609608
@patch("azure.monitor.opentelemetry._configure._logger")
609+
@patch("azure.monitor.opentelemetry._configure.get_dist_dependency_conflicts")
610610
@patch("azure.monitor.opentelemetry._configure.entry_points")
611611
def test_setup_instrumentations_exception(
612612
self,
613613
iter_mock,
614+
dep_mock,
614615
logger_mock,
615616
enabled_mock,
616617
):
@@ -621,8 +622,10 @@ def test_setup_instrumentations_exception(
621622
instr_class_mock.return_value = instrumentor_mock
622623
ep_mock.name = "test_instr"
623624
ep_mock.load.side_effect = Exception()
625+
dep_mock.return_value = None
624626
enabled_mock.return_value = True
625627
_setup_instrumentations({})
628+
dep_mock.assert_called_with(ep_mock.dist)
626629
ep_mock.load.assert_called_once()
627630
instrumentor_mock.instrument.assert_not_called()
628631
logger_mock.warning.assert_called_once()
@@ -632,10 +635,12 @@ def test_setup_instrumentations_exception(
632635
)
633636
@patch("azure.monitor.opentelemetry._configure._is_instrumentation_enabled")
634637
@patch("azure.monitor.opentelemetry._configure._logger")
638+
@patch("azure.monitor.opentelemetry._configure.get_dist_dependency_conflicts")
635639
@patch("azure.monitor.opentelemetry._configure.entry_points")
636640
def test_setup_instrumentations_disabled(
637641
self,
638642
iter_mock,
643+
dep_mock,
639644
logger_mock,
640645
enabled_mock,
641646
):
@@ -648,8 +653,10 @@ def test_setup_instrumentations_disabled(
648653
ep_mock.name = "test_instr1"
649654
ep2_mock.name = "test_instr2"
650655
ep2_mock.load.return_value = instr_class_mock
656+
dep_mock.return_value = None
651657
enabled_mock.side_effect = [False, True]
652658
_setup_instrumentations({})
659+
dep_mock.assert_called_with(ep2_mock.dist)
653660
ep_mock.load.assert_not_called()
654661
ep2_mock.load.assert_called_once()
655662
instrumentor_mock.instrument.assert_called_once()

0 commit comments

Comments
 (0)