Skip to content

Commit 7a71da7

Browse files
pfreixeshaotianw465
authored andcommitted
Give up when there is no open segment and LOG_ERROR is configured (#58)
* New flag `raise_if_not_subsegment` for Aiottp client Without setting this flag as False, any HTTP call done with the Aiohttp Client when there is no an active segment will fail with the SegmentNotFoundException exception. This issue can be annoying for this systems that do not create explicitly the segements and relay on the sampled incomming requests, which create automatically segments just for a sub set of the incomming request. * New entry within the CHANGELOG * Refactorized a bit the code * Give up when there is no open segment and LOG_ERROR is configured for context_missing
1 parent 46aee71 commit 7a71da7

File tree

3 files changed

+49
-7
lines changed

3 files changed

+49
-7
lines changed

CHANGELOG.rst

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
unreleased
66
==========
77
* feature: Added Sqlalchemy parameterized query capture. `PR34 <https://github.com/aws/aws-xray-sdk-python/pull/34>`_.
8+
* bugfix: Added new `raise_if_not_subsegment` parameter for Aiohttp Client tracing `PR58 <https://github.com/aws/aws-xray-sdk-python/pull/58>`_.
89

910
1.0
1011
===

aws_xray_sdk/ext/aiohttp/client.py

+23-7
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,30 @@
2424
async def begin_subsegment(session, trace_config_ctx, params):
2525
name = trace_config_ctx.name if trace_config_ctx.name else strip_url(str(params.url))
2626
subsegment = xray_recorder.begin_subsegment(name, REMOTE_NAMESPACE)
27-
subsegment.put_http_meta(http.METHOD, params.method)
28-
subsegment.put_http_meta(http.URL, params.url.human_repr())
29-
inject_trace_header(params.headers, subsegment)
27+
28+
# No-op if subsegment is `None` due to `LOG_ERROR`.
29+
if not subsegment:
30+
trace_config_ctx.give_up = True
31+
else:
32+
trace_config_ctx.give_up = False
33+
subsegment.put_http_meta(http.METHOD, params.method)
34+
subsegment.put_http_meta(http.URL, params.url.human_repr())
35+
inject_trace_header(params.headers, subsegment)
3036

3137

3238
async def end_subsegment(session, trace_config_ctx, params):
39+
if trace_config_ctx.give_up:
40+
return
41+
3342
subsegment = xray_recorder.current_subsegment()
3443
subsegment.put_http_meta(http.STATUS, params.response.status)
3544
xray_recorder.end_subsegment()
3645

3746

3847
async def end_subsegment_with_exception(session, trace_config_ctx, params):
48+
if trace_config_ctx.give_up:
49+
return
50+
3951
subsegment = xray_recorder.current_subsegment()
4052
subsegment.add_exception(
4153
params.exception,
@@ -54,10 +66,14 @@ def aws_xray_trace_config(name=None):
5466
be used as identifier.
5567
:returns: TraceConfig.
5668
"""
57-
trace_config = aiohttp.TraceConfig(
58-
trace_config_ctx_factory=lambda trace_request_ctx: SimpleNamespace(name=name,
59-
trace_request_ctx=trace_request_ctx)
60-
)
69+
70+
def _trace_config_ctx_factory(trace_request_ctx):
71+
return SimpleNamespace(
72+
name=name,
73+
trace_request_ctx=trace_request_ctx
74+
)
75+
76+
trace_config = aiohttp.TraceConfig(trace_config_ctx_factory=_trace_config_ctx_factory)
6177
trace_config.on_request_start.append(begin_subsegment)
6278
trace_config.on_request_end.append(end_subsegment)
6379
trace_config.on_request_exception.append(end_subsegment_with_exception)

tests/ext/aiohttp/test_client.py

+25
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from aws_xray_sdk.core import xray_recorder
55
from aws_xray_sdk.core.async_context import AsyncContext
6+
from aws_xray_sdk.core.exceptions.exceptions import SegmentNotFoundException
67
from aws_xray_sdk.ext.util import strip_url
78
from aws_xray_sdk.ext.aiohttp.client import aws_xray_trace_config
89
from aws_xray_sdk.ext.aiohttp.client import REMOTE_NAMESPACE, LOCAL_NAMESPACE
@@ -130,3 +131,27 @@ async def test_invalid_url(loop, recorder):
130131

131132
exception = subsegment.cause['exceptions'][0]
132133
assert exception.type == 'ClientConnectorError'
134+
135+
136+
async def test_no_segment_raise(loop, recorder):
137+
xray_recorder.configure(context_missing='RUNTIME_ERROR')
138+
trace_config = aws_xray_trace_config()
139+
status_code = 200
140+
url = 'http://{}/status/{}?foo=bar'.format(BASE_URL, status_code)
141+
with pytest.raises(SegmentNotFoundException):
142+
async with ClientSession(loop=loop, trace_configs=[trace_config]) as session:
143+
async with session.get(url):
144+
pass
145+
146+
147+
async def test_no_segment_not_raise(loop, recorder):
148+
xray_recorder.configure(context_missing='LOG_ERROR')
149+
trace_config = aws_xray_trace_config()
150+
status_code = 200
151+
url = 'http://{}/status/{}?foo=bar'.format(BASE_URL, status_code)
152+
async with ClientSession(loop=loop, trace_configs=[trace_config]) as session:
153+
async with session.get(url) as resp:
154+
status_received = resp.status
155+
156+
# Just check that the request was done correctly
157+
assert status_received == status_code

0 commit comments

Comments
 (0)