Skip to content

Commit 9180931

Browse files
authored
[core/api] Enable buffering on getresponse (#527)
* [core/api] buffer http recv calls * [core] add regression test for get_connect_response compat function
1 parent de764bb commit 9180931

File tree

4 files changed

+42
-5
lines changed

4 files changed

+42
-5
lines changed

ddtrace/api.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
# project
88
from .encoding import get_encoder, JSONEncoder
9-
from .compat import httplib, PYTHON_VERSION, PYTHON_INTERPRETER
9+
from .compat import httplib, PYTHON_VERSION, PYTHON_INTERPRETER, get_connection_response
1010

1111

1212
log = logging.getLogger(__name__)
@@ -140,4 +140,4 @@ def _put(self, endpoint, data, count=0):
140140
headers[TRACE_COUNT_HEADER] = str(count)
141141

142142
conn.request("PUT", endpoint, data, headers)
143-
return conn.getresponse()
143+
return get_connection_response(conn)

ddtrace/compat.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,24 @@ def to_unicode(s):
7070
return stringify(s)
7171

7272

73+
def get_connection_response(conn):
74+
"""Returns the response for a connection.
75+
76+
If using Python 2 enable buffering.
77+
78+
Python 2 does not enable buffering by default resulting in many recv
79+
syscalls.
80+
81+
See:
82+
https://bugs.python.org/issue4879
83+
https://github.com/python/cpython/commit/3c43fcba8b67ea0cec4a443c755ce5f25990a6cf
84+
"""
85+
if PY2:
86+
return conn.getresponse(buffering=True)
87+
else:
88+
return conn.getresponse()
89+
90+
7391
if PY2:
7492
string_type = basestring
7593
msgpack_type = basestring

tests/test_compat.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
import sys
44

55
# Third party
6-
from nose.tools import eq_, assert_raises
6+
from nose.tools import eq_, ok_, assert_raises
77

88
# Project
9-
from ddtrace.compat import to_unicode, PY2, reraise
9+
from ddtrace.compat import to_unicode, PY2, reraise, get_connection_response
1010

1111

1212
# Use different test suites for each Python version, this allows us to test the expected
@@ -61,6 +61,16 @@ def test_to_unicode_non_string(self):
6161
eq_(to_unicode(None), u'None')
6262
eq_(to_unicode(dict(key='value')), u'{\'key\': \'value\'}')
6363

64+
def test_get_connection_response(self):
65+
"""Ensure that buffering is in kwargs."""
66+
67+
class MockConn(object):
68+
def getresponse(self, *args, **kwargs):
69+
ok_('buffering' in kwargs)
70+
71+
mock = MockConn()
72+
get_connection_response(mock)
73+
6474
else:
6575
class TestCompatPY3(object):
6676
def test_to_unicode_string(self):
@@ -94,6 +104,16 @@ def test_to_unicode_non_string(self):
94104
eq_(to_unicode(None), 'None')
95105
eq_(to_unicode(dict(key='value')), '{\'key\': \'value\'}')
96106

107+
def test_get_connection_response(self):
108+
"""Ensure that buffering is NOT in kwargs."""
109+
110+
class MockConn(object):
111+
def getresponse(self, *args, **kwargs):
112+
ok_('buffering' not in kwargs)
113+
114+
mock = MockConn()
115+
get_connection_response(mock)
116+
97117

98118
class TestPy2Py3Compat(object):
99119
"""Common tests to ensure functions are both Python 2 and

tests/test_integration.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
from ddtrace.ext import http
1414
from ddtrace.filters import FilterRequestsOnUrl
1515
from ddtrace.constants import FILTERS_KEY
16-
from ddtrace.span import Span
1716
from ddtrace.tracer import Tracer
1817
from ddtrace.encoding import JSONEncoder, MsgpackEncoder, get_encoder
1918
from ddtrace.compat import httplib, PYTHON_INTERPRETER, PYTHON_VERSION

0 commit comments

Comments
 (0)