Skip to content

Use the official middleware pattern for Aiohttp ext #29

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
CHANGELOG
=========

unreleased
==========
* feature: Use the official middleware pattern for Aiohttp ext. `PR29 <https://github.com/aws/aws-xray-sdk-python/pull/29>`_.

0.96
====
* feature: Add support for SQLAlchemy and Flask-SQLAlcemy. `PR14 <https://github.com/aws/aws-xray-sdk-python/pull/14>`_.
Expand Down
110 changes: 53 additions & 57 deletions aws_xray_sdk/ext/aiohttp/middleware.py
Original file line number Diff line number Diff line change
@@ -1,78 +1,74 @@
"""
AioHttp Middleware
"""
import aiohttp
import traceback

from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core.models import http
from aws_xray_sdk.ext.util import calculate_sampling_decision, calculate_segment_name, construct_xray_header


async def middleware(app, handler):
@aiohttp.web.middleware
async def middleware(request, handler):
"""
AioHttp Middleware Factory
Main middleware function, deals with all the X-Ray segment logic
"""
async def _middleware(request):
"""
Main middleware function, deals with all the X-Ray segment logic
"""
# Create X-Ray headers
xray_header = construct_xray_header(request.headers)
# Get name of service or generate a dynamic one from host
name = calculate_segment_name(request.headers['host'].split(':', 1)[0], xray_recorder)
# Create X-Ray headers
xray_header = construct_xray_header(request.headers)
# Get name of service or generate a dynamic one from host
name = calculate_segment_name(request.headers['host'].split(':', 1)[0], xray_recorder)

sampling_decision = calculate_sampling_decision(
trace_header=xray_header,
recorder=xray_recorder,
service_name=request.headers['host'],
method=request.method,
path=request.path,
)
sampling_decision = calculate_sampling_decision(
trace_header=xray_header,
recorder=xray_recorder,
service_name=request.headers['host'],
method=request.method,
path=request.path,
)

# Start a segment
segment = xray_recorder.begin_segment(
name=name,
traceid=xray_header.root,
parent_id=xray_header.parent,
sampling=sampling_decision,
)
# Start a segment
segment = xray_recorder.begin_segment(
name=name,
traceid=xray_header.root,
parent_id=xray_header.parent,
sampling=sampling_decision,
)

# Store request metadata in the current segment
segment.put_http_meta(http.URL, request.url)
segment.put_http_meta(http.METHOD, request.method)
# Store request metadata in the current segment
segment.put_http_meta(http.URL, request.url)
segment.put_http_meta(http.METHOD, request.method)

if 'User-Agent' in request.headers:
segment.put_http_meta(http.USER_AGENT, request.headers['User-Agent'])
if 'User-Agent' in request.headers:
segment.put_http_meta(http.USER_AGENT, request.headers['User-Agent'])

if 'X-Forwarded-For' in request.headers:
segment.put_http_meta(http.CLIENT_IP, request.headers['X-Forwarded-For'])
segment.put_http_meta(http.X_FORWARDED_FOR, True)
elif 'remote_addr' in request.headers:
segment.put_http_meta(http.CLIENT_IP, request.headers['remote_addr'])
else:
segment.put_http_meta(http.CLIENT_IP, request.remote)
if 'X-Forwarded-For' in request.headers:
segment.put_http_meta(http.CLIENT_IP, request.headers['X-Forwarded-For'])
segment.put_http_meta(http.X_FORWARDED_FOR, True)
elif 'remote_addr' in request.headers:
segment.put_http_meta(http.CLIENT_IP, request.headers['remote_addr'])
else:
segment.put_http_meta(http.CLIENT_IP, request.remote)

try:
# Call next middleware or request handler
response = await handler(request)
except Exception as err:
# Store exception information including the stacktrace to the segment
segment = xray_recorder.current_segment()
segment.put_http_meta(http.STATUS, 500)
stack = traceback.extract_stack(limit=xray_recorder._max_trace_back)
segment.add_exception(err, stack)
xray_recorder.end_segment()
raise

# Store response metadata into the current segment
segment.put_http_meta(http.STATUS, response.status)
try:
# Call next middleware or request handler
response = await handler(request)
except Exception as err:
# Store exception information including the stacktrace to the segment
segment = xray_recorder.current_segment()
segment.put_http_meta(http.STATUS, 500)
stack = traceback.extract_stack(limit=xray_recorder._max_trace_back)
segment.add_exception(err, stack)
xray_recorder.end_segment()
raise

if 'Content-Length' in response.headers:
length = int(response.headers['Content-Length'])
segment.put_http_meta(http.CONTENT_LENGTH, length)
# Store response metadata into the current segment
segment.put_http_meta(http.STATUS, response.status)

# Close segment so it can be dispatched off to the daemon
xray_recorder.end_segment()
if 'Content-Length' in response.headers:
length = int(response.headers['Content-Length'])
segment.put_http_meta(http.CONTENT_LENGTH, length)

return response
return _middleware
# Close segment so it can be dispatched off to the daemon
xray_recorder.end_segment()
return response
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ You can get started in minutes using ``pip`` or by downloading a zip file.
Currently supported web frameworks and libraries:

* aioboto3/aiobotocore
* aiohttp
* aiohttp >=2.3
* boto3/botocore
* Django >=1.10
* Flask
Expand Down