diff --git a/CHANGELOG.md b/CHANGELOG.md index 056fe9686b..16f54fea2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,9 +20,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#3423](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3423)) - `opentelemetry-instrumentation-asyncio` Fix duplicate instrumentation ([#3383](https://github.com/open-telemetry/opentelemetry-python-contrib/issues/3383)) - - `opentelemetry-instrumentation-botocore` Add GenAI instrumentation for additional Bedrock models for InvokeModel API ([#3419](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3419)) +- `opentelemetry-instrumentation` don't print duplicated conflict log error message + ([#3432](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3432)) ## Version 1.32.0/0.53b0 (2025-04-10) diff --git a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/instrumentor.py b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/instrumentor.py index dead45fbac..aee0ba2b68 100644 --- a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/instrumentor.py +++ b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/instrumentor.py @@ -111,9 +111,12 @@ def instrument(self, **kwargs: Any): if not skip_dep_check: conflict = self._check_dependency_conflicts() if conflict: - _LOG.error(conflict) + # auto-instrumentation path: don't log conflict as error, instead + # let _load_instrumentors handle the exception if raise_exception_on_conflict: raise DependencyConflictError(conflict) + # manual instrumentation path: log the conflict as error + _LOG.error(conflict) return None # initialize semantic conventions opt-in if needed diff --git a/opentelemetry-instrumentation/tests/test_instrumentor.py b/opentelemetry-instrumentation/tests/test_instrumentor.py index b7e039e797..f5efd25fc7 100644 --- a/opentelemetry-instrumentation/tests/test_instrumentor.py +++ b/opentelemetry-instrumentation/tests/test_instrumentor.py @@ -54,11 +54,12 @@ def test_protect(self): def test_singleton(self): self.assertIs(self.Instrumentor(), self.Instrumentor()) + @patch("opentelemetry.instrumentation.instrumentor._LOG") @patch( "opentelemetry.instrumentation.instrumentor.BaseInstrumentor._check_dependency_conflicts" ) def test_instrument_missing_dependency_raise( - self, mock__check_dependency_conflicts + self, mock__check_dependency_conflicts, mock_logger ): instrumentor = self.Instrumentor() @@ -71,3 +72,19 @@ def test_instrument_missing_dependency_raise( instrumentor.instrument, raise_exception_on_conflict=True, ) + mock_logger.error.assert_not_called() + + @patch("opentelemetry.instrumentation.instrumentor._LOG") + @patch( + "opentelemetry.instrumentation.instrumentor.BaseInstrumentor._check_dependency_conflicts" + ) + def test_instrument_missing_dependency_log_error( + self, mock__check_dependency_conflicts, mock_logger + ): + instrumentor = self.Instrumentor() + conflict = DependencyConflict("missing", "missing") + mock__check_dependency_conflicts.return_value = conflict + self.assertIsNone( + instrumentor.instrument(raise_exception_on_conflict=False) + ) + mock_logger.error.assert_any_call(conflict)