Skip to content

Commit dbadeb5

Browse files
authored
Merge branch 'main' into fix-3415
2 parents 7ef2597 + 9c969f3 commit dbadeb5

File tree

14 files changed

+77
-12
lines changed

14 files changed

+77
-12
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111
1212
## Unreleased
1313

14+
### Added
15+
16+
### Fixed
17+
18+
- `opentelemetry-instrumentation` Catch `ModuleNotFoundError` when the library is not installed
19+
and log as debug instead of exception
20+
([#3423](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3423))
21+
1422
## Version 1.32.0/0.53b0 (2025-04-10)
1523

1624
### Added

instrumentation/opentelemetry-instrumentation-aiohttp-client/test-requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ http_server_mock==1.7
1313
idna==3.7
1414
iniconfig==2.0.0
1515
itsdangerous==2.1.2
16-
Jinja2==3.1.4
16+
Jinja2==3.1.6
1717
MarkupSafe==2.1.5
1818
multidict==6.0.5
1919
packaging==24.0

instrumentation/opentelemetry-instrumentation-boto/test-requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Deprecated==1.2.14
1010
docker==7.0.0
1111
idna==3.7
1212
iniconfig==2.0.0
13-
Jinja2==3.1.4
13+
Jinja2==3.1.6
1414
jmespath==1.0.1
1515
MarkupSafe==2.1.5
1616
moto==2.3.2

instrumentation/opentelemetry-instrumentation-botocore/test-requirements-0.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Deprecated==1.2.14
1010
docker==7.0.0
1111
idna==3.7
1212
iniconfig==2.0.0
13-
Jinja2==3.1.4
13+
Jinja2==3.1.6
1414
jmespath==1.0.1
1515
MarkupSafe==2.1.5
1616
moto==5.0.9

instrumentation/opentelemetry-instrumentation-botocore/test-requirements-1.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Deprecated==1.2.14
1010
docker==7.0.0
1111
idna==3.7
1212
iniconfig==2.0.0
13-
Jinja2==3.1.4
13+
Jinja2==3.1.6
1414
jmespath==1.0.1
1515
MarkupSafe==2.1.5
1616
moto==5.0.9

instrumentation/opentelemetry-instrumentation-click/test-requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Deprecated==1.2.14
55
Flask==3.0.2
66
iniconfig==2.0.0
77
itsdangerous==2.1.2
8-
Jinja2==3.1.4
8+
Jinja2==3.1.6
99
MarkupSafe==2.1.2
1010
packaging==24.0
1111
pluggy==1.5.0

instrumentation/opentelemetry-instrumentation-flask/test-requirements-0.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Deprecated==1.2.14
44
Flask==2.1.3
55
iniconfig==2.0.0
66
itsdangerous==2.1.2
7-
Jinja2==3.1.4
7+
Jinja2==3.1.6
88
MarkupSafe==2.1.2
99
packaging==24.0
1010
pluggy==1.5.0

instrumentation/opentelemetry-instrumentation-flask/test-requirements-1.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Deprecated==1.2.14
44
Flask==2.2.0
55
iniconfig==2.0.0
66
itsdangerous==2.1.2
7-
Jinja2==3.1.4
7+
Jinja2==3.1.6
88
MarkupSafe==2.1.2
99
packaging==24.0
1010
pluggy==1.5.0

instrumentation/opentelemetry-instrumentation-flask/test-requirements-2.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Deprecated==1.2.14
55
Flask==3.0.2
66
iniconfig==2.0.0
77
itsdangerous==2.1.2
8-
Jinja2==3.1.4
8+
Jinja2==3.1.6
99
MarkupSafe==2.1.2
1010
packaging==24.0
1111
pluggy==1.5.0

instrumentation/opentelemetry-instrumentation-jinja2/test-requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
asgiref==3.8.1
22
Deprecated==1.2.14
33
iniconfig==2.0.0
4-
Jinja2==3.1.4
4+
Jinja2==3.1.6
55
MarkupSafe==2.0.1
66
packaging==24.0
77
pluggy==1.5.0

instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ def get(self):
7272
7373
.. code-block:: python
7474
75+
from opentelemetry.instrumentation.tornado import TornadoInstrumentor
76+
7577
# will be called for each incoming request to Tornado
7678
# web server. `handler` is an instance of
7779
# `tornado.web.RequestHandler`.
@@ -94,7 +96,7 @@ def client_response_hook(span, future):
9496
TornadoInstrumentor().instrument(
9597
server_request_hook=server_request_hook,
9698
client_request_hook=client_request_hook,
97-
client_response_hook=client_response_hook
99+
client_response_hook=client_response_hook,
98100
)
99101
100102
Capture HTTP request and response headers

instrumentation/opentelemetry-instrumentation-tornado/test-requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ http_server_mock==1.7
99
idna==3.7
1010
iniconfig==2.0.0
1111
itsdangerous==2.1.2
12-
Jinja2==3.1.4
12+
Jinja2==3.1.6
1313
MarkupSafe==2.1.5
1414
packaging==24.0
1515
pluggy==1.5.0

opentelemetry-instrumentation/src/opentelemetry/instrumentation/auto_instrumentation/_load.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ def _load_instrumentors(distro):
8282
exc.conflict,
8383
)
8484
continue
85+
except ModuleNotFoundError as exc:
86+
# ModuleNotFoundError is raised when the library is not installed
87+
# and the instrumentation is not required to be loaded.
88+
# See https://github.com/open-telemetry/opentelemetry-python-contrib/issues/3421
89+
_logger.debug(
90+
"Skipping instrumentation %s: %s", entry_point.name, exc.msg
91+
)
92+
continue
8593
except ImportError:
8694
# in scenarios using the kubernetes operator to do autoinstrumentation some
8795
# instrumentors (usually requiring binary extensions) may fail to load

opentelemetry-instrumentation/tests/auto_instrumentation/test_load.py

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,11 +326,12 @@ def test_load_instrumentors_dep_conflict(self, iter_mock, mock_logger): # pylin
326326
]
327327
)
328328

329+
@patch("opentelemetry.instrumentation.auto_instrumentation._load._logger")
329330
@patch(
330331
"opentelemetry.instrumentation.auto_instrumentation._load.entry_points"
331332
)
332333
def test_load_instrumentors_import_error_does_not_stop_everything(
333-
self, iter_mock
334+
self, iter_mock, mock_logger
334335
):
335336
ep_mock1 = Mock(name="instr1")
336337
ep_mock2 = Mock(name="instr2")
@@ -354,6 +355,12 @@ def test_load_instrumentors_import_error_does_not_stop_everything(
354355
]
355356
)
356357
self.assertEqual(distro_mock.load_instrumentor.call_count, 2)
358+
mock_logger.exception.assert_any_call(
359+
"Importing of %s failed, skipping it",
360+
ep_mock1.name,
361+
)
362+
363+
mock_logger.debug.assert_any_call("Instrumented %s", ep_mock2.name)
357364

358365
@patch(
359366
"opentelemetry.instrumentation.auto_instrumentation._load.entry_points"
@@ -382,6 +389,46 @@ def test_load_instrumentors_raises_exception(self, iter_mock):
382389
)
383390
self.assertEqual(distro_mock.load_instrumentor.call_count, 1)
384391

392+
@patch("opentelemetry.instrumentation.auto_instrumentation._load._logger")
393+
@patch(
394+
"opentelemetry.instrumentation.auto_instrumentation._load.entry_points"
395+
)
396+
def test_load_instrumentors_module_not_found_error(
397+
self, iter_mock, mock_logger
398+
):
399+
ep_mock1 = Mock()
400+
ep_mock1.name = "instr1"
401+
402+
ep_mock2 = Mock()
403+
ep_mock2.name = "instr2"
404+
405+
distro_mock = Mock()
406+
407+
distro_mock.load_instrumentor.side_effect = [
408+
ModuleNotFoundError("No module named 'fake_module'"),
409+
None,
410+
]
411+
412+
iter_mock.side_effect = [(), (ep_mock1, ep_mock2), ()]
413+
414+
_load._load_instrumentors(distro_mock)
415+
416+
distro_mock.load_instrumentor.assert_has_calls(
417+
[
418+
call(ep_mock1, raise_exception_on_conflict=True),
419+
call(ep_mock2, raise_exception_on_conflict=True),
420+
]
421+
)
422+
self.assertEqual(distro_mock.load_instrumentor.call_count, 2)
423+
424+
mock_logger.debug.assert_any_call(
425+
"Skipping instrumentation %s: %s",
426+
"instr1",
427+
"No module named 'fake_module'",
428+
)
429+
430+
mock_logger.debug.assert_any_call("Instrumented %s", ep_mock2.name)
431+
385432
def test_load_instrumentors_no_entry_point_mocks(self):
386433
distro_mock = Mock()
387434
_load._load_instrumentors(distro_mock)

0 commit comments

Comments
 (0)