diff --git a/.changelog/4530.changed b/.changelog/4530.changed new file mode 100644 index 0000000000..2fbf3f4c87 Binary files /dev/null and b/.changelog/4530.changed differ diff --git a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap.py b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap.py index 2959789b7c..321b85f8f0 100644 --- a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap.py +++ b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap.py @@ -31,24 +31,26 @@ def _syscall(func): - def wrapper(package=None): + def wrapper(packages=None): try: - if package: - return func(package) - return func() + if packages is None: + return func() + if not packages: + return None + return func(packages) except SubprocessError as exp: cmd = getattr(exp, "cmd", None) if cmd: msg = f'Error calling system command "{" ".join(cmd)}"' - if package: - msg = f'{msg} for package "{package}"' + if packages: + msg = f'{msg} for packages "{", ".join(packages)}"' raise RuntimeError(msg) return wrapper @_syscall -def _sys_pip_install(package): +def _sys_pip_install(packages): # explicit upgrade strategy to override potential pip config try: check_call( @@ -60,7 +62,7 @@ def _sys_pip_install(package): "-U", "--upgrade-strategy", "only-if-needed", - package, + *packages, ] ) except CalledProcessError as error: @@ -123,8 +125,9 @@ def _run_requirements(default_instrumentations, libraries): def _run_install(default_instrumentations, libraries): - for lib in _find_installed_libraries(default_instrumentations, libraries): - _sys_pip_install(lib) + libs = list(_find_installed_libraries(default_instrumentations, libraries)) + if libs: + _sys_pip_install(libs) _pip_check(libraries) @@ -167,8 +170,7 @@ def run( if default_instrumentations is None: default_instrumentations = gen_default_instrumentations - cmd = { - action_install: _run_install, - action_requirements: _run_requirements, - }[args.action] - cmd(default_instrumentations, libraries) + if args.action == action_install: + _run_install(default_instrumentations, libraries) + else: + _run_requirements(default_instrumentations, libraries) diff --git a/opentelemetry-instrumentation/tests/test_bootstrap.py b/opentelemetry-instrumentation/tests/test_bootstrap.py index 5f4820d10e..65bb2a8504 100644 --- a/opentelemetry-instrumentation/tests/test_bootstrap.py +++ b/opentelemetry-instrumentation/tests/test_bootstrap.py @@ -5,7 +5,7 @@ from io import StringIO from random import sample from unittest import TestCase -from unittest.mock import call, patch +from unittest.mock import patch from opentelemetry.instrumentation import bootstrap from opentelemetry.instrumentation.bootstrap_gen import ( @@ -31,7 +31,6 @@ def setUpClass(cls): [lib["instrumentation"] for lib in libraries], 0.6 ) - # treat 50% of sampled packages as pre-installed cls.installed_instrumentations = sample_packages( cls.installed_libraries, 0.5 ) @@ -78,9 +77,8 @@ def test_run_cmd_print(self): def test_run_cmd_install(self): self.pkg_patcher.start() bootstrap.run() - self.mock_pip_install.assert_has_calls( - [call(i) for i in self.installed_libraries], - any_order=True, + self.mock_pip_install.assert_called_once_with( + self.installed_libraries, ) self.mock_pip_check.assert_called_once() self.pkg_patcher.stop() @@ -88,9 +86,8 @@ def test_run_cmd_install(self): @patch("sys.argv", ["bootstrap", "-a", "install"]) def test_can_override_available_libraries(self): bootstrap.run(libraries=[]) - self.mock_pip_install.assert_has_calls( - [call(i) for i in default_instrumentations], - any_order=True, + self.mock_pip_install.assert_called_once_with( + list(default_instrumentations), ) self.mock_pip_check.assert_called_once() @@ -101,8 +98,5 @@ def test_can_override_available_default_instrumentations(self): return_value=True, ): bootstrap.run(default_instrumentations=[]) - self.mock_pip_install.assert_has_calls( - [call(i) for i in self.installed_libraries], - any_order=True, - ) + self.mock_pip_install.assert_called_once() self.mock_pip_check.assert_called_once()