Skip to content

Commit 37360e8

Browse files
committed
releasing 0.97
1 parent 4f91e5f commit 37360e8

File tree

12 files changed

+127
-58
lines changed

12 files changed

+127
-58
lines changed

CHANGELOG.rst

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

5-
unreleased
6-
==========
7-
* feature: Aiohttp client tracing for aiohttp versions > 3. `PR42 <https://github.com/aws/aws-xray-sdk-python/pull/42>`_.
5+
0.97
6+
====
7+
* feature: Support aiohttp client tracing for aiohttp 3.x. `PR42 <https://github.com/aws/aws-xray-sdk-python/pull/42>`_.
88
* feature: Use the official middleware pattern for Aiohttp ext. `PR29 <https://github.com/aws/aws-xray-sdk-python/pull/29>`_.
9-
* bugfix: SQLAlcemy plugin would cause warning messages with some db connection strings that contained invalid characters for a segment/subsegment name.
109
* bugfix: Aiohttp middleware serialized URL values incorrectly. `PR37 <https://github.com/aws/aws-xray-sdk-python/pull/37>`_
1110
* bugfix: Don't overwrite plugins list on each `.configure` call. `PR38 <https://github.com/aws/aws-xray-sdk-python/pull/38>`_
12-
* bugfix: Do not swallow `return_value`. `PR44 <https://github.com/aws/aws-xray-sdk-python/pull/44>`_
11+
* bugfix: Do not swallow `return_value` when context is missing and `LOG_ERROR` is set. `PR44 <https://github.com/aws/aws-xray-sdk-python/pull/44>`_
12+
* bugfix: Loose entity name validation. `ISSUE36 <https://github.com/aws/aws-xray-sdk-python/issues/36>`_
13+
* bugfix: Fix PyPI project page being rendered incorrectly. `ISSUE30 <https://github.com/aws/aws-xray-sdk-python/issues/30>`_
1314

1415
0.96
1516
====

README.md

+5-4
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,10 @@ xray_recorder.configure(service='fallback_name', dynamic_naming='*mysite.com*')
160160
XRayMiddleware(app, xray_recorder)
161161
```
162162

163-
### Add aiohttp middleware
163+
### Working with aiohttp
164+
165+
Adding aiohttp middleware. Support aiohttp >= 2.3.
166+
164167
```python
165168
from aiohttp import web
166169

@@ -176,9 +179,7 @@ app.router.add_get("/", handler)
176179
web.run_app(app)
177180
```
178181

179-
### Trace aiohttp client requests
180-
181-
Only available using Aiohttp releases greater than 3.X.
182+
Tracing aiohttp client. Support aiohttp >=3.
182183

183184
```python
184185
from aws_xray_sdk.ext.aiohttp.client import aws_xray_trace_config

aws_xray_sdk/core/async_recorder.py

+18-16
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,22 @@ async def record_subsegment_async(self, wrapped, instance, args, kwargs, name,
5050
stack = traceback.extract_stack(limit=self._max_trace_back)
5151
raise
5252
finally:
53-
end_time = time.time()
54-
if callable(meta_processor):
55-
meta_processor(
56-
wrapped=wrapped,
57-
instance=instance,
58-
args=args,
59-
kwargs=kwargs,
60-
return_value=return_value,
61-
exception=exception,
62-
subsegment=subsegment,
63-
stack=stack,
64-
)
65-
elif exception:
66-
if subsegment:
67-
subsegment.add_exception(exception, stack)
53+
# No-op if subsegment is `None` due to `LOG_ERROR`.
54+
if subsegment is not None:
55+
end_time = time.time()
56+
if callable(meta_processor):
57+
meta_processor(
58+
wrapped=wrapped,
59+
instance=instance,
60+
args=args,
61+
kwargs=kwargs,
62+
return_value=return_value,
63+
exception=exception,
64+
subsegment=subsegment,
65+
stack=stack,
66+
)
67+
elif exception:
68+
if subsegment:
69+
subsegment.add_exception(exception, stack)
6870

69-
self.end_subsegment(end_time)
71+
self.end_subsegment(end_time)

aws_xray_sdk/core/models/entity.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414

1515
log = logging.getLogger(__name__)
1616

17-
# List of valid characters found at http://docs.aws.amazon.com/xray/latest/devguide/xray-api-segmentdocuments.html
18-
_valid_name_characters = string.ascii_letters + string.digits + '_.:/%&#=+\-@ '
17+
# Valid characters can be found at http://docs.aws.amazon.com/xray/latest/devguide/xray-api-segmentdocuments.html
18+
_common_invalid_name_characters = '?;*()!$~^<>'
1919
_valid_annotation_key_characters = string.ascii_letters + string.digits + '_'
2020

2121

@@ -30,7 +30,7 @@ def __init__(self, name):
3030
# required attributes
3131
self.id = self._generate_random_id()
3232
self.name = name
33-
self.name = ''.join([c for c in name if c in _valid_name_characters])
33+
self.name = ''.join([c for c in name if c not in _common_invalid_name_characters])
3434
self.start_time = time.time()
3535
self.parent_id = None
3636

aws_xray_sdk/core/recorder.py

+18-20
Original file line numberDiff line numberDiff line change
@@ -335,26 +335,24 @@ def record_subsegment(self, wrapped, instance, args, kwargs, name,
335335
raise
336336
finally:
337337
# No-op if subsegment is `None` due to `LOG_ERROR`.
338-
if subsegment is None:
339-
return return_value
340-
341-
end_time = time.time()
342-
if callable(meta_processor):
343-
meta_processor(
344-
wrapped=wrapped,
345-
instance=instance,
346-
args=args,
347-
kwargs=kwargs,
348-
return_value=return_value,
349-
exception=exception,
350-
subsegment=subsegment,
351-
stack=stack,
352-
)
353-
elif exception:
354-
if subsegment:
355-
subsegment.add_exception(exception, stack)
356-
357-
self.end_subsegment(end_time)
338+
if subsegment is not None:
339+
end_time = time.time()
340+
if callable(meta_processor):
341+
meta_processor(
342+
wrapped=wrapped,
343+
instance=instance,
344+
args=args,
345+
kwargs=kwargs,
346+
return_value=return_value,
347+
exception=exception,
348+
subsegment=subsegment,
349+
stack=stack,
350+
)
351+
elif exception:
352+
if subsegment:
353+
subsegment.add_exception(exception, stack)
354+
355+
self.end_subsegment(end_time)
358356

359357
def _populate_runtime_context(self, segment):
360358
if not self._plugins:

aws_xray_sdk/ext/sqlalchemy/util/decerators.py

-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import re
22
from aws_xray_sdk.core import xray_recorder
33
from aws_xray_sdk.ext.util import strip_url
4-
from aws_xray_sdk.core.models.entity import _valid_name_characters
54
from future.standard_library import install_aliases
65
install_aliases()
76
from urllib.parse import urlparse, uses_netloc
@@ -49,8 +48,6 @@ def wrapper(*args, **kw):
4948
if getattr(c._local, 'entities', None) is not None:
5049
# Strip URL of ? and following text
5150
sub_name = strip_url(sql['url'])
52-
# Ensure url has a valid characters.
53-
sub_name = ''.join([c for c in sub_name if c in _valid_name_characters])
5451
subsegment = xray_recorder.begin_subsegment(sub_name, namespace='remote')
5552
else:
5653
subsegment = None

docs/conf.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@
6262
# built documents.
6363
#
6464
# The short X.Y version.
65-
version = u'0.96'
65+
version = u'0.97'
6666
# The full version, including alpha/beta/rc tags.
67-
release = u'0.96'
67+
release = u'0.97'
6868

6969
# The language for content autogenerated by Sphinx. Refer to documentation
7070
# for a list of supported languages.

setup.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
from setuptools import setup, find_packages
22
from os import path
3-
import codecs
43

54
CURRENT_DIR = path.abspath(path.dirname(__file__))
65

7-
with codecs.open(path.join(CURRENT_DIR, 'README.md'), encoding='utf-8') as f:
8-
long_description = f.read()
6+
try:
7+
from pypandoc import convert
8+
read_md = lambda f: convert(f, 'rst')
9+
except ImportError:
10+
read_md = lambda f: open(f, 'r').read()
11+
12+
long_description = read_md(path.join(CURRENT_DIR, 'README.md'))
913

1014
setup(
1115
name='aws-xray-sdk',
12-
version='0.96',
16+
version='0.97',
1317

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

tests/ext/aiobotocore/test_aiobotocore.py

+28
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import aiobotocore
44
from botocore.stub import Stubber, ANY
5+
from botocore.exceptions import ClientError
56

67
from aws_xray_sdk.core import patch
78
from aws_xray_sdk.core.async_context import AsyncContext
@@ -103,3 +104,30 @@ async def test_map_parameter_grouping(loop, recorder):
103104

104105
aws_meta = subsegment.aws
105106
assert sorted(aws_meta['table_names']) == ['table1', 'table2']
107+
108+
109+
async def test_context_missing_not_swallow_return(loop, recorder):
110+
xray_recorder.configure(service='test', sampling=False,
111+
context=AsyncContext(loop=loop), context_missing='LOG_ERROR')
112+
113+
response = {'ResponseMetadata': {'RequestId': '1234', 'HTTPStatusCode': 403}}
114+
115+
session = aiobotocore.get_session(loop=loop)
116+
async with session.create_client('dynamodb', region_name='eu-west-2') as client:
117+
with Stubber(client) as stubber:
118+
stubber.add_response('describe_table', response, {'TableName': 'mytable'})
119+
actual_resp = await client.describe_table(TableName='mytable')
120+
121+
assert actual_resp == response
122+
123+
124+
async def test_context_missing_not_suppress_exception(loop, recorder):
125+
xray_recorder.configure(service='test', sampling=False,
126+
context=AsyncContext(loop=loop), context_missing='LOG_ERROR')
127+
128+
session = aiobotocore.get_session(loop=loop)
129+
async with session.create_client('dynamodb', region_name='eu-west-2') as client:
130+
with Stubber(client) as stubber:
131+
stubber.add_client_error('describe_table', expected_params={'TableName': ANY})
132+
with pytest.raises(ClientError):
133+
await client.describe_table(TableName='mytable')

tests/ext/botocore/test_botocore.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,6 @@ def test_pass_through_on_context_missing():
123123
with Stubber(ddb) as stubber:
124124
stubber.add_response('describe_table', response, {'TableName': 'mytable'})
125125
result = ddb.describe_table(TableName='mytable')
126-
assert result is not None
126+
assert result is not None
127127

128128
xray_recorder.configure(context_missing='RUNTIME_ERROR')

tests/test_recorder.py

+26
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import pytest
12
from .util import get_new_stubbed_recorder
23

34

@@ -40,3 +41,28 @@ def test_subsegments_streaming():
4041

4142
assert segment.get_total_subsegments_size() == 10
4243
assert xray_recorder.current_subsegment().name == '9'
44+
45+
46+
def test_capture_not_suppress_exception():
47+
xray_recorder = get_new_stubbed_recorder()
48+
xray_recorder.configure(sampling=False, context_missing='LOG_ERROR')
49+
50+
@xray_recorder.capture()
51+
def buggy_func():
52+
return 1 / 0
53+
54+
with pytest.raises(ZeroDivisionError):
55+
buggy_func()
56+
57+
58+
def test_capture_not_swallow_return():
59+
xray_recorder = get_new_stubbed_recorder()
60+
xray_recorder.configure(sampling=False, context_missing='LOG_ERROR')
61+
value = 1
62+
63+
@xray_recorder.capture()
64+
def my_func():
65+
return value
66+
67+
actual = my_func()
68+
assert actual == value

tests/test_trace_entities.py

+12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# -*- coding: iso-8859-15 -*-
12
import pytest
23

34
from aws_xray_sdk.core.models.segment import Segment
@@ -10,6 +11,17 @@
1011
from .util import entity_to_dict
1112

1213

14+
def test_unicode_entity_name():
15+
16+
name1 = u'福'
17+
name2 = u'セツナ'
18+
segment = Segment(name1)
19+
subsegment = Subsegment(name2, 'local', segment)
20+
21+
assert segment.name == name1
22+
assert subsegment.name == name2
23+
24+
1325
def test_put_http_meta():
1426

1527
segment = Segment('seg')

0 commit comments

Comments
 (0)