1010
1111from wrapt import wrap_function_wrapper as wrap
1212from wrapt .importer import when_imported
13+ from ddtrace import patch_all as patch_all_dd
1314
14- from datadog_lambda .tracing import get_dd_trace_context
15+ from datadog_lambda .tracing import (
16+ get_dd_trace_context ,
17+ dd_tracing_enabled ,
18+ )
1519
1620logger = logging .getLogger (__name__ )
1721
1822if sys .version_info >= (3 , 0 , 0 ):
1923 httplib_module = "http.client"
24+ from collections .abc import MutableMapping
2025else :
2126 httplib_module = "httplib"
27+ from collections import MutableMapping
2228
2329_httplib_patched = False
2430_requests_patched = False
31+ _integration_tests_patched = False
2532
2633
2734def patch_all ():
2835 """
29- Patch the widely-used HTTP clients to automatically inject
30- Datadog trace context.
36+ Patch third-party libraries for tracing.
3137 """
32- _patch_httplib ()
33- _ensure_patch_requests ()
38+ _patch_for_integration_tests ()
39+
40+ if dd_tracing_enabled :
41+ patch_all_dd ()
42+ else :
43+ _patch_httplib ()
44+ _ensure_patch_requests ()
45+
46+
47+ def _patch_for_integration_tests ():
48+ """
49+ Patch `requests` to log the outgoing requests for integration tests.
50+ """
51+ global _integration_tests_patched
52+ is_in_tests = os .environ .get ("DD_INTEGRATION_TEST" , "false" ).lower () == "true"
53+ if not _integration_tests_patched and is_in_tests :
54+ wrap ("requests" , "Session.send" , _log_request )
55+ _integration_tests_patched = True
3456
3557
3658def _patch_httplib ():
@@ -80,17 +102,13 @@ def _wrap_requests_request(func, instance, args, kwargs):
80102 into the outgoing requests.
81103 """
82104 context = get_dd_trace_context ()
83- if "headers" in kwargs and isinstance (kwargs ["headers" ], dict ):
105+ if "headers" in kwargs and isinstance (kwargs ["headers" ], MutableMapping ):
84106 kwargs ["headers" ].update (context )
85- elif len (args ) >= 5 and isinstance (args [4 ], dict ):
107+ elif len (args ) >= 5 and isinstance (args [4 ], MutableMapping ):
86108 args [4 ].update (context )
87109 else :
88110 kwargs ["headers" ] = context
89111
90- # If we're in an integration test, log the HTTP requests made
91- if os .environ .get ("DD_INTEGRATION_TEST" , "false" ).lower () == "true" :
92- _print_request_string (args , kwargs )
93-
94112 return func (* args , ** kwargs )
95113
96114
@@ -100,43 +118,38 @@ def _wrap_httplib_request(func, instance, args, kwargs):
100118 the Datadog trace headers into the outgoing requests.
101119 """
102120 context = get_dd_trace_context ()
103- if "headers" in kwargs and isinstance (kwargs ["headers" ], dict ):
121+ if "headers" in kwargs and isinstance (kwargs ["headers" ], MutableMapping ):
104122 kwargs ["headers" ].update (context )
105- elif len (args ) >= 4 and isinstance (args [3 ], dict ):
123+ elif len (args ) >= 4 and isinstance (args [3 ], MutableMapping ):
106124 args [3 ].update (context )
107125 else :
108126 kwargs ["headers" ] = context
109127
110128 return func (* args , ** kwargs )
111129
112130
113- def _print_request_string (args , kwargs ):
131+ def _log_request (func , instance , args , kwargs ):
132+ request = kwargs .get ("request" ) or args [0 ]
133+ _print_request_string (request )
134+ return func (* args , ** kwargs )
135+
136+
137+ def _print_request_string (request ):
114138 """Print the request so that it can be checked in integration tests
115139
116140 Only used by integration tests.
117141 """
118- # Normalizes the different ways args can be passed to a request
119- # to prevent test flakiness
120- method = None
121- if len (args ) > 0 :
122- method = args [0 ]
123- else :
124- method = kwargs .get ("method" , "" ).upper ()
125-
126- url = None
127- if len (args ) > 1 :
128- url = args [1 ]
129- else :
130- url = kwargs .get ("url" )
142+ method = request .method
143+ url = request .url
131144
132145 # Sort the datapoints POSTed by their name so that snapshots always align
133- data = kwargs . get ( "data" , "{}" )
146+ data = request . body or "{}"
134147 data_dict = json .loads (data )
135148 data_dict .get ("series" , []).sort (key = lambda series : series .get ("metric" ))
136149 sorted_data = json .dumps (data_dict )
137150
138151 # Sort headers to prevent any differences in ordering
139- headers = kwargs . get ( " headers" , {})
152+ headers = request . headers or {}
140153 sorted_headers = sorted (
141154 "{}:{}" .format (key , value ) for key , value in headers .items ()
142155 )
0 commit comments