Skip to content

Commit c374fd8

Browse files
committed
release commit for 0.96
1 parent b9dbaf1 commit c374fd8

File tree

9 files changed

+67
-22
lines changed

9 files changed

+67
-22
lines changed

CHANGELOG.rst

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22
CHANGELOG
33
=========
44

5-
Unreleased
6-
==========
5+
0.96
6+
====
77
* feature: Add support for SQLAlchemy and Flask-SQLAlcemy. `PR14 <https://github.com/aws/aws-xray-sdk-python/pull/14>`_.
88
* feature: Add support for PynamoDB calls to DynamoDB. `PR13 <https://github.com/aws/aws-xray-sdk-python/pull/13>`_.
9-
* feature: Add support for httplib calls `PR19 <https://github.com/aws/aws-xray-sdk-python/pull/19>`_.
9+
* feature: Add support for httplib calls. `PR19 <https://github.com/aws/aws-xray-sdk-python/pull/19>`_.
10+
* feature: Make streaming threshold configurable through public interface. `ISSUE21 <https://github.com/aws/aws-xray-sdk-python/issues/21>`_.
1011
* bugfix: Drop invalid annotation keys and log a warning. `PR22 <https://github.com/aws/aws-xray-sdk-python/pull/22>`_.
1112
* bugfix: Respect `with` statement on cursor objects in dbapi2 patcher. `PR17 <https://github.com/aws/aws-xray-sdk-python/pull/17>`_.
13+
* bugfix: Don't throw error from built in subsegment capture when `LOG_ERROR` is set. `ISSUE4 <https://github.com/aws/aws-xray-sdk-python/issues/4>`_.
1214

1315
0.95
1416
====

aws_xray_sdk/core/recorder.py

+19-2
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def configure(self, sampling=None, plugins=None,
5757
context_missing=None, sampling_rules=None,
5858
daemon_address=None, service=None,
5959
context=None, emitter=None,
60-
dynamic_naming=None):
60+
dynamic_naming=None, streaming_threshold=None):
6161
"""Configure global X-Ray recorder.
6262
6363
Configure needs to run before patching thrid party libraries
@@ -90,6 +90,9 @@ def configure(self, sampling=None, plugins=None,
9090
:param dynamic_naming: a string that defines a pattern that host names
9191
should match. Alternatively you can pass a module which
9292
overrides ``DefaultDynamicNaming`` module.
93+
:param streaming_threshold: If breaks within a single segment it will
94+
start streaming out children subsegments. By default it is the
95+
maximum number of subsegments within a segment.
9396
9497
Environment variables AWS_XRAY_DAEMON_ADDRESS, AWS_XRAY_CONTEXT_MISSING
9598
and AWS_XRAY_TRACING_NAME respectively overrides arguments
@@ -111,6 +114,8 @@ def configure(self, sampling=None, plugins=None,
111114
self.context.context_missing = os.getenv(CONTEXT_MISSING_KEY, context_missing)
112115
if dynamic_naming:
113116
self.dynamic_naming = dynamic_naming
117+
if streaming_threshold:
118+
self.streaming_threshold = streaming_threshold
114119

115120
plugin_modules = None
116121
if plugins:
@@ -259,7 +264,7 @@ def stream_subsegments(self):
259264
if not segment or not segment.sampled:
260265
return
261266

262-
if segment.get_total_subsegments_size() <= self._max_subsegments:
267+
if segment.get_total_subsegments_size() <= self.streaming_threshold:
263268
return
264269

265270
# find all subsegments that has no open child subsegments and
@@ -326,6 +331,10 @@ def record_subsegment(self, wrapped, instance, args, kwargs, name,
326331
stack = traceback.extract_stack(limit=self._max_trace_back)
327332
raise
328333
finally:
334+
# No-op if subsegment is `None` due to `LOG_ERROR`.
335+
if subsegment is None:
336+
return
337+
329338
end_time = time.time()
330339
if callable(meta_processor):
331340
meta_processor(
@@ -440,3 +449,11 @@ def emitter(self):
440449
@emitter.setter
441450
def emitter(self, value):
442451
self._emitter = value
452+
453+
@property
454+
def streaming_threshold(self):
455+
return self._max_subsegments
456+
457+
@streaming_threshold.setter
458+
def streaming_threshold(self, value):
459+
self._max_subsegments = value

aws_xray_sdk/ext/django/apps.py

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ def ready(self):
3434
plugins=settings.PLUGINS,
3535
service=settings.AWS_XRAY_TRACING_NAME,
3636
dynamic_naming=settings.DYNAMIC_NAMING,
37+
streaming_threshold=settings.STREAMING_THRESHOLD,
3738
)
3839

3940
# if turned on subsegment will be generated on

aws_xray_sdk/ext/django/conf.py

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
'SAMPLING_RULES': None,
1313
'AWS_XRAY_TRACING_NAME': None,
1414
'DYNAMIC_NAMING': None,
15+
'STREAMING_THRESHOLD': None,
1516
}
1617

1718
XRAY_NAMESPACE = 'XRAY_RECORDER'

aws_xray_sdk/ext/httplib/patch.py

+12-12
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
_XRAY_PROP = '_xray_prop'
2222
_XRay_Data = namedtuple('xray_data', ['method', 'host', 'url'])
23+
# A flag indicates whether this module is X-Ray patched or not
24+
PATCH_FLAG = '__xray_patched'
2325

2426

2527
def http_response_processor(wrapped, instance, args, kwargs, return_value,
@@ -113,11 +115,10 @@ def _xray_traced_http_client_read(wrapped, instance, args, kwargs):
113115

114116
def patch():
115117
""" patch the built-in urllib/httplib/httplib.client methods for tracing"""
116-
117-
# we set an attribute to avoid double unwrapping
118-
if getattr(httplib, '__xray_patch', False):
118+
if getattr(httplib, PATCH_FLAG, False):
119119
return
120-
setattr(httplib, '__xray_patch', True)
120+
# we set an attribute to avoid multiple wrapping
121+
setattr(httplib, PATCH_FLAG, True)
121122

122123
wrapt.wrap_function_wrapper(
123124
httplib_client_module,
@@ -139,13 +140,12 @@ def patch():
139140

140141

141142
def unpatch():
142-
""" unpatch any previously patched modules """
143-
if not getattr(httplib, '__xray_patch', False):
144-
return
145-
setattr(httplib, '__xray_patch', False)
146-
147-
# send_request encapsulates putrequest, putheader[s], and endheaders
148-
# NOTE that requests
143+
"""
144+
Unpatch any previously patched modules.
145+
This operation is idempotent.
146+
"""
147+
setattr(httplib, PATCH_FLAG, False)
148+
# _send_request encapsulates putrequest, putheader[s], and endheaders
149149
unwrap(httplib.HTTPConnection, '_send_request')
150150
unwrap(httplib.HTTPConnection, 'getresponse')
151-
unwrap(httplib.HTTPConnection, 'read')
151+
unwrap(httplib.HTTPResponse, 'read')

docs/frameworks.rst

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ The default values are as follows::
4545
'SAMPLING_RULES': None,
4646
'AWS_XRAY_TRACING_NAME': None, # the segment name for segments generated from incoming requests
4747
'DYNAMIC_NAMING': None, # defines a pattern that host names should match
48+
'STREAMING_THRESHOLD': None, # defines when a segment starts to stream out its children subsegments
4849
}
4950

5051
Environment variables have higher precedence over user settings.

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
setup(
1111
name='aws-xray-sdk',
12-
version='0.95',
12+
version='0.96',
1313

1414
description='The AWS X-Ray SDK for Python (the SDK) enables Python developers to record'
1515
' and emit information from within their applications to the AWS X-Ray service.',

tests/ext/botocore/test_botocore.py

+22
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,25 @@ def test_map_parameter_grouping():
103103

104104
aws_meta = subsegment.aws
105105
assert sorted(aws_meta['table_names']) == ['table1', 'table2']
106+
107+
def test_pass_through_on_context_missing():
108+
"""
109+
The built-in patcher or subsegment capture logic should not throw
110+
any error when a `None` subsegment created from `LOG_ERROR` missing context.
111+
"""
112+
xray_recorder.configure(context_missing='LOG_ERROR')
113+
xray_recorder.clear_trace_entities()
114+
115+
ddb = session.create_client('dynamodb', region_name='us-west-2')
116+
response = {
117+
'ResponseMetadata': {
118+
'RequestId': REQUEST_ID,
119+
'HTTPStatusCode': 200,
120+
}
121+
}
122+
123+
with Stubber(ddb) as stubber:
124+
stubber.add_response('describe_table', response, {'TableName': 'mytable'})
125+
ddb.describe_table(TableName='mytable')
126+
127+
xray_recorder.configure(context_missing='RUNTIME_ERROR')

tests/test_recorder.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,13 @@ def test_subsegment_parenting():
3030

3131

3232
def test_subsegments_streaming():
33-
33+
xray_recorder.configure(streaming_threshold=10)
3434
segment = xray_recorder.begin_segment('name')
35-
for i in range(0, 50):
35+
for i in range(0, 11):
3636
xray_recorder.begin_subsegment(name=str(i))
37-
for i in range(0, 40):
37+
for i in range(0, 1):
38+
# subsegment '10' will be streamed out upon close
3839
xray_recorder.end_subsegment()
3940

40-
assert segment.get_total_subsegments_size() < 50
41+
assert segment.get_total_subsegments_size() == 10
4142
assert xray_recorder.current_subsegment().name == '9'

0 commit comments

Comments
 (0)