1616
1717import unittest
1818from timeit import default_timer
19- from unittest .mock import Mock , patch
19+ from unittest .mock import Mock , call , patch
2020
2121import fastapi
2222from fastapi .middleware .httpsredirect import HTTPSRedirectMiddleware
3737from opentelemetry .instrumentation .auto_instrumentation ._load import (
3838 _load_instrumentors ,
3939)
40+ from opentelemetry .instrumentation .dependencies import (
41+ DependencyConflict ,
42+ DependencyConflictError ,
43+ )
4044from opentelemetry .sdk .metrics .export import (
4145 HistogramDataPoint ,
4246 NumberDataPoint ,
5458from opentelemetry .semconv .trace import SpanAttributes
5559from opentelemetry .test .globals_test import reset_trace_globals
5660from opentelemetry .test .test_base import TestBase
57- from opentelemetry .util ._importlib_metadata import (
58- PackageNotFoundError ,
59- entry_points ,
60- )
61+ from opentelemetry .util ._importlib_metadata import entry_points
6162from opentelemetry .util .http import (
6263 OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS ,
6364 OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST ,
@@ -1031,26 +1032,6 @@ def client_response_hook(send_span, scope, message):
10311032 )
10321033
10331034
1034- def mock_version_with_fastapi (* args , ** kwargs ):
1035- req_name = args [0 ]
1036- if req_name == "fastapi" :
1037- # TODO: Value now matters
1038- return "0.58"
1039- raise PackageNotFoundError ()
1040-
1041-
1042- def mock_version_with_old_fastapi (* args , ** kwargs ):
1043- req_name = args [0 ]
1044- if req_name == "fastapi" :
1045- # TODO: Value now matters
1046- return "0.57"
1047- raise PackageNotFoundError ()
1048-
1049-
1050- def mock_version_without_fastapi (* args , ** kwargs ):
1051- raise PackageNotFoundError ()
1052-
1053-
10541035class TestAutoInstrumentation (TestBaseAutoFastAPI ):
10551036 """Test the auto-instrumented variant
10561037
@@ -1062,31 +1043,65 @@ def test_entry_point_exists(self):
10621043 (ep ,) = entry_points (group = "opentelemetry_instrumentor" )
10631044 self .assertEqual (ep .name , "fastapi" )
10641045
1065- @patch ("opentelemetry.instrumentation.dependencies.version" )
1066- def test_instruments_with_fastapi_installed (self , mock_version ):
1067- mock_version .side_effect = mock_version_with_fastapi
1046+ @staticmethod
1047+ def _instrumentation_loaded_successfully_call ():
1048+ return call ("Instrumented %s" , "fastapi" )
1049+
1050+ @staticmethod
1051+ def _instrumentation_failed_to_load_call (dependency_conflict ):
1052+ return call (
1053+ "Skipping instrumentation %s: %s" , "fastapi" , dependency_conflict
1054+ )
1055+
1056+ @patch ("opentelemetry.instrumentation.auto_instrumentation._load._logger" )
1057+ def test_instruments_with_fastapi_installed (self , mock_logger ):
10681058 mock_distro = Mock ()
1059+ mock_distro .load_instrumentor .return_value = None
10691060 _load_instrumentors (mock_distro )
1070- mock_version .assert_called_once_with ("fastapi" )
10711061 self .assertEqual (len (mock_distro .load_instrumentor .call_args_list ), 1 )
10721062 (ep ,) = mock_distro .load_instrumentor .call_args .args
10731063 self .assertEqual (ep .name , "fastapi" )
1064+ mock_logger .debug .assert_has_calls (
1065+ [self ._instrumentation_loaded_successfully_call ()]
1066+ )
10741067
1075- @patch ("opentelemetry.instrumentation.dependencies.version " )
1076- def test_instruments_with_old_fastapi_installed (self , mock_version ): # pylint: disable=no-self-use
1077- mock_version . side_effect = mock_version_with_old_fastapi
1068+ @patch ("opentelemetry.instrumentation.auto_instrumentation._load._logger " )
1069+ def test_instruments_with_old_fastapi_installed (self , mock_logger ): # pylint: disable=no-self-use
1070+ dependency_conflict = DependencyConflict ( "0.58" , "0.57" )
10781071 mock_distro = Mock ()
1072+ mock_distro .load_instrumentor .side_effect = DependencyConflictError (
1073+ dependency_conflict
1074+ )
10791075 _load_instrumentors (mock_distro )
1080- mock_version .assert_called_once_with ("fastapi" )
1081- mock_distro .load_instrumentor .assert_not_called ()
1076+ self .assertEqual (len (mock_distro .load_instrumentor .call_args_list ), 1 )
1077+ (ep ,) = mock_distro .load_instrumentor .call_args .args
1078+ self .assertEqual (ep .name , "fastapi" )
1079+ assert (
1080+ self ._instrumentation_loaded_successfully_call ()
1081+ not in mock_logger .debug .call_args_list
1082+ )
1083+ mock_logger .debug .assert_has_calls (
1084+ [self ._instrumentation_failed_to_load_call (dependency_conflict )]
1085+ )
10821086
1083- @patch ("opentelemetry.instrumentation.dependencies.version " )
1084- def test_instruments_without_fastapi_installed (self , mock_version ): # pylint: disable=no-self-use
1085- mock_version . side_effect = mock_version_without_fastapi
1087+ @patch ("opentelemetry.instrumentation.auto_instrumentation._load._logger " )
1088+ def test_instruments_without_fastapi_installed (self , mock_logger ): # pylint: disable=no-self-use
1089+ dependency_conflict = DependencyConflict ( "0.58" , None )
10861090 mock_distro = Mock ()
1091+ mock_distro .load_instrumentor .side_effect = DependencyConflictError (
1092+ dependency_conflict
1093+ )
10871094 _load_instrumentors (mock_distro )
1088- mock_version .assert_called_once_with ("fastapi" )
1089- mock_distro .load_instrumentor .assert_not_called ()
1095+ self .assertEqual (len (mock_distro .load_instrumentor .call_args_list ), 1 )
1096+ (ep ,) = mock_distro .load_instrumentor .call_args .args
1097+ self .assertEqual (ep .name , "fastapi" )
1098+ assert (
1099+ self ._instrumentation_loaded_successfully_call ()
1100+ not in mock_logger .debug .call_args_list
1101+ )
1102+ mock_logger .debug .assert_has_calls (
1103+ [self ._instrumentation_failed_to_load_call (dependency_conflict )]
1104+ )
10901105
10911106 def _create_app (self ):
10921107 # instrumentation is handled by the instrument call
0 commit comments