Skip to content

Commit d8df89a

Browse files
author
Emanuele Palazzetti
committed
[requests] code refactoring in multiple modules
1 parent 885f4f9 commit d8df89a

File tree

4 files changed

+87
-82
lines changed

4 files changed

+87
-82
lines changed

ddtrace/contrib/requests/__init__.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,11 @@
3232

3333
with require_modules(required_modules) as missing_modules:
3434
if not missing_modules:
35-
from .patch import TracedSession, patch, unpatch
36-
__all__ = ['TracedSession', 'patch', 'unpatch']
35+
from .patch import patch, unpatch
36+
from .session import TracedSession
37+
38+
__all__ = [
39+
'patch',
40+
'unpatch',
41+
'TracedSession',
42+
]
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import os
2+
import logging
3+
import ddtrace
4+
5+
from ...ext import http
6+
from ...util import asbool
7+
from ...propagation.http import HTTPPropagator
8+
9+
10+
log = logging.getLogger(__name__)
11+
12+
13+
def _wrap_session_init(func, instance, args, kwargs):
14+
"""Configure tracing settings when the `Session` is initialized"""
15+
func(*args, **kwargs)
16+
17+
# set tracer settings
18+
distributed_tracing = asbool(os.environ.get('DATADOG_REQUESTS_DISTRIBUTED_TRACING')) or False
19+
setattr(instance, 'distributed_tracing', distributed_tracing)
20+
21+
22+
def _wrap_request(func, instance, args, kwargs):
23+
"""Trace the `Session.request` instance method"""
24+
tracer = getattr(instance, 'datadog_tracer', ddtrace.tracer)
25+
26+
# [TODO:christian] replace this with a unified way of handling options (eg, Pin)
27+
distributed_tracing = getattr(instance, 'distributed_tracing', None)
28+
29+
# skip if tracing is not enabled
30+
if not tracer.enabled:
31+
return func(*args, **kwargs)
32+
33+
method = kwargs.get('method') or args[0]
34+
url = kwargs.get('url') or args[1]
35+
headers = kwargs.get('headers', {})
36+
37+
with tracer.trace("requests.request", span_type=http.TYPE) as span:
38+
if distributed_tracing:
39+
propagator = HTTPPropagator()
40+
propagator.inject(span.context, headers)
41+
kwargs['headers'] = headers
42+
43+
response = None
44+
try:
45+
response = func(*args, **kwargs)
46+
return response
47+
finally:
48+
try:
49+
span.set_tag(http.METHOD, method)
50+
span.set_tag(http.URL, url)
51+
if response is not None:
52+
span.set_tag(http.STATUS_CODE, response.status_code)
53+
# `span.error` must be an integer
54+
span.error = int(500 <= response.status_code)
55+
except Exception:
56+
log.debug("error patching tags", exc_info=True)

ddtrace/contrib/requests/patch.py

Lines changed: 5 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,9 @@
1-
import os
2-
import logging
3-
4-
import wrapt
5-
import ddtrace
61
import requests
72

8-
from ...ext import http
9-
from ...propagation.http import HTTPPropagator
10-
from ...utils.formats import asbool
11-
from ...utils.wrappers import unwrap as _u
12-
3+
from wrapt import wrap_function_wrapper as _w
134

14-
log = logging.getLogger(__name__)
5+
from ...util import unwrap as _u
6+
from .connection import _wrap_session_init, _wrap_request
157

168

179
def patch():
@@ -20,8 +12,8 @@ def patch():
2012
return
2113
setattr(requests, '__datadog_patch', True)
2214

23-
wrapt.wrap_function_wrapper('requests', 'Session.__init__', _session_initializer)
24-
wrapt.wrap_function_wrapper('requests', 'Session.request', _traced_request_func)
15+
_w('requests', 'Session.__init__', _wrap_session_init)
16+
_w('requests', 'Session.request', _wrap_request)
2517

2618

2719
def unpatch():
@@ -32,70 +24,3 @@ def unpatch():
3224

3325
_u(requests.Session, '__init__')
3426
_u(requests.Session, 'request')
35-
36-
37-
def _session_initializer(func, instance, args, kwargs):
38-
"""Define settings when requests client is initialized"""
39-
func(*args, **kwargs)
40-
41-
# set tracer settings
42-
distributed_tracing = asbool(os.environ.get('DATADOG_REQUESTS_DISTRIBUTED_TRACING')) or False
43-
setattr(instance, 'distributed_tracing', distributed_tracing)
44-
45-
46-
def _traced_request_func(func, instance, args, kwargs):
47-
""" traced_request is a tracing wrapper for requests' Session.request
48-
instance method.
49-
"""
50-
51-
# perhaps a global tracer isn't what we want, so permit individual requests
52-
# sessions to have their own (with the standard global fallback)
53-
tracer = getattr(instance, 'datadog_tracer', ddtrace.tracer)
54-
55-
# [TODO:christian] replace this with a unified way of handling options (eg, Pin)
56-
distributed_tracing = getattr(instance, 'distributed_tracing', None)
57-
58-
# bail on the tracing if not enabled.
59-
if not tracer.enabled:
60-
return func(*args, **kwargs)
61-
62-
method = kwargs.get('method') or args[0]
63-
url = kwargs.get('url') or args[1]
64-
headers = kwargs.get('headers', {})
65-
66-
with tracer.trace("requests.request", span_type=http.TYPE) as span:
67-
if distributed_tracing:
68-
propagator = HTTPPropagator()
69-
propagator.inject(span.context, headers)
70-
kwargs['headers'] = headers
71-
72-
resp = None
73-
try:
74-
resp = func(*args, **kwargs)
75-
return resp
76-
finally:
77-
try:
78-
_apply_tags(span, method, url, resp)
79-
except Exception:
80-
log.debug("error patching tags", exc_info=True)
81-
82-
83-
def _apply_tags(span, method, url, response):
84-
""" apply_tags will patch the given span with tags about the given request. """
85-
span.set_tag(http.METHOD, method)
86-
span.set_tag(http.URL, url)
87-
if response is not None:
88-
span.set_tag(http.STATUS_CODE, response.status_code)
89-
# `span.error` must be an integer
90-
span.error = int(500 <= response.status_code)
91-
92-
93-
class TracedSession(requests.Session):
94-
""" TracedSession is a requests' Session that is already patched.
95-
"""
96-
pass
97-
98-
99-
# Always patch our traced session with the traced method (cheesy way of sharing
100-
# code)
101-
wrapt.wrap_function_wrapper(TracedSession, 'request', _traced_request_func)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import requests
2+
3+
from wrapt import wrap_function_wrapper as _w
4+
5+
from .connection import _wrap_session_init, _wrap_request
6+
7+
8+
class TracedSession(requests.Session):
9+
"""TracedSession is a requests' Session that is already traced.
10+
You can use it if you want a finer grained control for your
11+
HTTP clients.
12+
"""
13+
pass
14+
15+
16+
# always patch our `TracedSession` when imported
17+
_w(TracedSession, 'request', _wrap_session_init)
18+
_w(TracedSession, 'request', _wrap_request)

0 commit comments

Comments
 (0)