@@ -193,6 +193,7 @@ async def async_response_hook(span, request, response):
193193import logging
194194import typing
195195from asyncio import iscoroutinefunction
196+ from functools import partial
196197from types import TracebackType
197198
198199import httpx
@@ -731,45 +732,53 @@ def _instrument(self, **kwargs):
731732 ``async_response_hook``: Async``response_hook`` for ``httpx.AsyncClient``
732733 """
733734 tracer_provider = kwargs .get ("tracer_provider" )
734- _request_hook = kwargs .get ("request_hook" )
735- self ._request_hook = _request_hook if callable (_request_hook ) else None
736- _response_hook = kwargs .get ("response_hook" )
737- self ._response_hook = (
738- _response_hook if callable (_response_hook ) else None
739- )
740- _async_request_hook = kwargs .get ("async_request_hook" )
741- self ._async_request_hook = (
742- _async_request_hook
743- if iscoroutinefunction (_async_request_hook )
735+ request_hook = kwargs .get ("request_hook" )
736+ response_hook = kwargs .get ("response_hook" )
737+ async_request_hook = kwargs .get ("async_request_hook" )
738+ async_request_hook = (
739+ async_request_hook
740+ if iscoroutinefunction (async_request_hook )
744741 else None
745742 )
746- _async_response_hook = kwargs .get ("async_response_hook" )
747- self . _async_response_hook = (
748- _async_response_hook
749- if iscoroutinefunction (_async_response_hook )
743+ async_response_hook = kwargs .get ("async_response_hook" )
744+ async_response_hook = (
745+ async_response_hook
746+ if iscoroutinefunction (async_response_hook )
750747 else None
751748 )
752749
753750 _OpenTelemetrySemanticConventionStability ._initialize ()
754- self . _sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability ._get_opentelemetry_stability_opt_in_mode (
751+ sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability ._get_opentelemetry_stability_opt_in_mode (
755752 _OpenTelemetryStabilitySignalType .HTTP ,
756753 )
757- self . _tracer = get_tracer (
754+ tracer = get_tracer (
758755 __name__ ,
759756 instrumenting_library_version = __version__ ,
760757 tracer_provider = tracer_provider ,
761- schema_url = _get_schema_url (self . _sem_conv_opt_in_mode ),
758+ schema_url = _get_schema_url (sem_conv_opt_in_mode ),
762759 )
763760
764761 wrap_function_wrapper (
765762 "httpx" ,
766763 "HTTPTransport.handle_request" ,
767- self ._handle_request_wrapper ,
764+ partial (
765+ self ._handle_request_wrapper ,
766+ tracer = tracer ,
767+ sem_conv_opt_in_mode = sem_conv_opt_in_mode ,
768+ request_hook = request_hook ,
769+ response_hook = response_hook ,
770+ ),
768771 )
769772 wrap_function_wrapper (
770773 "httpx" ,
771774 "AsyncHTTPTransport.handle_async_request" ,
772- self ._handle_async_request_wrapper ,
775+ partial (
776+ self ._handle_async_request_wrapper ,
777+ tracer = tracer ,
778+ sem_conv_opt_in_mode = sem_conv_opt_in_mode ,
779+ async_request_hook = async_request_hook ,
780+ async_response_hook = async_response_hook ,
781+ ),
773782 )
774783
775784 def _uninstrument (self , ** kwargs ):
@@ -778,7 +787,17 @@ def _uninstrument(self, **kwargs):
778787 unwrap (httpx .HTTPTransport , "handle_request" )
779788 unwrap (httpx .AsyncHTTPTransport , "handle_async_request" )
780789
781- def _handle_request_wrapper (self , wrapped , instance , args , kwargs ):
790+ def _handle_request_wrapper (
791+ self ,
792+ wrapped ,
793+ instance ,
794+ args ,
795+ kwargs ,
796+ tracer ,
797+ sem_conv_opt_in_mode ,
798+ request_hook ,
799+ response_hook ,
800+ ):
782801 if not is_http_instrumentation_enabled ():
783802 return wrapped (* args , ** kwargs )
784803
@@ -793,17 +812,17 @@ def _handle_request_wrapper(self, wrapped, instance, args, kwargs):
793812 span_attributes ,
794813 url ,
795814 method_original ,
796- self . _sem_conv_opt_in_mode ,
815+ sem_conv_opt_in_mode ,
797816 )
798817
799818 request_info = RequestInfo (method , url , headers , stream , extensions )
800819
801- with self . _tracer .start_as_current_span (
820+ with tracer .start_as_current_span (
802821 span_name , kind = SpanKind .CLIENT , attributes = span_attributes
803822 ) as span :
804823 exception = None
805- if callable (self . _request_hook ):
806- self . _request_hook (span , request_info )
824+ if callable (request_hook ):
825+ request_hook (span , request_info )
807826
808827 _inject_propagation_headers (headers , args , kwargs )
809828
@@ -824,19 +843,17 @@ def _handle_request_wrapper(self, wrapped, instance, args, kwargs):
824843 span ,
825844 status_code ,
826845 http_version ,
827- self . _sem_conv_opt_in_mode ,
846+ sem_conv_opt_in_mode ,
828847 )
829- if callable (self . _response_hook ):
830- self . _response_hook (
848+ if callable (response_hook ):
849+ response_hook (
831850 span ,
832851 request_info ,
833852 ResponseInfo (status_code , headers , stream , extensions ),
834853 )
835854
836855 if exception :
837- if span .is_recording () and _report_new (
838- self ._sem_conv_opt_in_mode
839- ):
856+ if span .is_recording () and _report_new (sem_conv_opt_in_mode ):
840857 span .set_attribute (
841858 ERROR_TYPE , type (exception ).__qualname__
842859 )
@@ -845,7 +862,15 @@ def _handle_request_wrapper(self, wrapped, instance, args, kwargs):
845862 return response
846863
847864 async def _handle_async_request_wrapper (
848- self , wrapped , instance , args , kwargs
865+ self ,
866+ wrapped ,
867+ instance ,
868+ args ,
869+ kwargs ,
870+ tracer ,
871+ sem_conv_opt_in_mode ,
872+ async_request_hook ,
873+ async_response_hook ,
849874 ):
850875 if not is_http_instrumentation_enabled ():
851876 return await wrapped (* args , ** kwargs )
@@ -861,17 +886,17 @@ async def _handle_async_request_wrapper(
861886 span_attributes ,
862887 url ,
863888 method_original ,
864- self . _sem_conv_opt_in_mode ,
889+ sem_conv_opt_in_mode ,
865890 )
866891
867892 request_info = RequestInfo (method , url , headers , stream , extensions )
868893
869- with self . _tracer .start_as_current_span (
894+ with tracer .start_as_current_span (
870895 span_name , kind = SpanKind .CLIENT , attributes = span_attributes
871896 ) as span :
872897 exception = None
873- if callable (self . _async_request_hook ):
874- await self . _async_request_hook (span , request_info )
898+ if callable (async_request_hook ):
899+ await async_request_hook (span , request_info )
875900
876901 _inject_propagation_headers (headers , args , kwargs )
877902
@@ -892,20 +917,18 @@ async def _handle_async_request_wrapper(
892917 span ,
893918 status_code ,
894919 http_version ,
895- self . _sem_conv_opt_in_mode ,
920+ sem_conv_opt_in_mode ,
896921 )
897922
898- if callable (self . _async_response_hook ):
899- await self . _async_response_hook (
923+ if callable (async_response_hook ):
924+ await async_response_hook (
900925 span ,
901926 request_info ,
902927 ResponseInfo (status_code , headers , stream , extensions ),
903928 )
904929
905930 if exception :
906- if span .is_recording () and _report_new (
907- self ._sem_conv_opt_in_mode
908- ):
931+ if span .is_recording () and _report_new (sem_conv_opt_in_mode ):
909932 span .set_attribute (
910933 ERROR_TYPE , type (exception ).__qualname__
911934 )
@@ -941,59 +964,81 @@ def instrument_client(
941964 )
942965 return
943966
944- # FIXME: sharing state in the instrumentor instance maybe it's not that great, need to pass tracer and semconv to each
945- # instance separately
946967 _OpenTelemetrySemanticConventionStability ._initialize ()
947- self . _sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability ._get_opentelemetry_stability_opt_in_mode (
968+ sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability ._get_opentelemetry_stability_opt_in_mode (
948969 _OpenTelemetryStabilitySignalType .HTTP ,
949970 )
950- self . _tracer = get_tracer (
971+ tracer = get_tracer (
951972 __name__ ,
952973 instrumenting_library_version = __version__ ,
953974 tracer_provider = tracer_provider ,
954- schema_url = _get_schema_url (self . _sem_conv_opt_in_mode ),
975+ schema_url = _get_schema_url (sem_conv_opt_in_mode ),
955976 )
956977
957978 if iscoroutinefunction (request_hook ):
958- self . _async_request_hook = request_hook
959- self . _request_hook = None
979+ async_request_hook = request_hook
980+ request_hook = None
960981 else :
961- self . _request_hook = request_hook
962- self . _async_request_hook = None
982+ request_hook = request_hook
983+ async_request_hook = None
963984
964985 if iscoroutinefunction (response_hook ):
965- self . _async_response_hook = response_hook
966- self . _response_hook = None
986+ async_response_hook = response_hook
987+ response_hook = None
967988 else :
968- self . _response_hook = response_hook
969- self . _async_response_hook = None
989+ response_hook = response_hook
990+ async_response_hook = None
970991
971992 if hasattr (client ._transport , "handle_request" ):
972993 wrap_function_wrapper (
973994 client ._transport ,
974995 "handle_request" ,
975- self ._handle_request_wrapper ,
996+ partial (
997+ self ._handle_request_wrapper ,
998+ tracer = tracer ,
999+ sem_conv_opt_in_mode = sem_conv_opt_in_mode ,
1000+ request_hook = request_hook ,
1001+ response_hook = response_hook ,
1002+ ),
9761003 )
9771004 for transport in client ._mounts .values ():
9781005 # FIXME: check it's not wrapped already?
9791006 wrap_function_wrapper (
9801007 transport ,
9811008 "handle_request" ,
982- self ._handle_request_wrapper ,
1009+ partial (
1010+ self ._handle_request_wrapper ,
1011+ tracer = tracer ,
1012+ sem_conv_opt_in_mode = sem_conv_opt_in_mode ,
1013+ request_hook = request_hook ,
1014+ response_hook = response_hook ,
1015+ ),
9831016 )
9841017 client ._is_instrumented_by_opentelemetry = True
9851018 if hasattr (client ._transport , "handle_async_request" ):
9861019 wrap_function_wrapper (
9871020 client ._transport ,
9881021 "handle_async_request" ,
989- self ._handle_async_request_wrapper ,
1022+ partial (
1023+ self ._handle_async_request_wrapper ,
1024+ tracer = tracer ,
1025+ sem_conv_opt_in_mode = sem_conv_opt_in_mode ,
1026+ async_request_hook = async_request_hook ,
1027+ async_response_hook = async_response_hook ,
1028+ ),
9901029 )
9911030 for transport in client ._mounts .values ():
9921031 # FIXME: check it's not wrapped already?
9931032 wrap_function_wrapper (
9941033 transport ,
9951034 "handle_async_request" ,
996- self ._handle_async_request_wrapper ,
1035+ partial (
1036+ self ._handle_async_request_wrapper ,
1037+ tracer = tracer ,
1038+ sem_conv_opt_in_mode = sem_conv_opt_in_mode ,
1039+ async_request_hook = async_request_hook ,
1040+ async_response_hook = async_response_hook ,
1041+ ),
9971042 )
9981043 client ._is_instrumented_by_opentelemetry = True
9991044
0 commit comments