1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
from __future__ import absolute_import
# Need absolute import as botocore is also in the current folder for py27
import json
from pkg_resources import resource_filename
from botocore.exceptions import ClientError
from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core.models import http
from aws_xray_sdk.ext.util import inject_trace_header, to_snake_case
with open(resource_filename(__name__, 'resources/aws_para_whitelist.json'), 'r') as data_file:
whitelist = json.load(data_file)
def inject_header(wrapped, instance, args, kwargs):
headers = args[0]
inject_trace_header(headers, xray_recorder.current_subsegment())
return wrapped(*args, **kwargs)
def aws_meta_processor(wrapped, instance, args, kwargs,
return_value, exception, subsegment, stack):
region = instance.meta.region_name
if 'operation_name' in kwargs:
operation_name = kwargs['operation_name']
else:
operation_name = args[0]
aws_meta = {
'operation': operation_name,
'region': region,
}
if return_value:
resp_meta = return_value.get('ResponseMetadata')
if resp_meta:
aws_meta['request_id'] = resp_meta.get('RequestId')
subsegment.put_http_meta(http.STATUS,
resp_meta.get('HTTPStatusCode'))
# for service like S3 that returns special request id in response headers
if 'HTTPHeaders' in resp_meta and resp_meta['HTTPHeaders'].get('x-amz-id-2'):
aws_meta['id_2'] = resp_meta['HTTPHeaders']['x-amz-id-2']
elif exception:
_aws_error_handler(exception, stack, subsegment, aws_meta)
_extract_whitelisted_params(subsegment.name, operation_name,
aws_meta, args, kwargs, return_value)
subsegment.set_aws(aws_meta)
def _aws_error_handler(exception, stack, subsegment, aws_meta):
if not exception or not isinstance(exception, ClientError):
return
response_metadata = exception.response.get('ResponseMetadata')
if not response_metadata:
return
aws_meta['request_id'] = response_metadata.get('RequestId')
status_code = response_metadata.get('HTTPStatusCode')
subsegment.put_http_meta(http.STATUS, status_code)
subsegment.add_exception(exception, stack, True)
def _extract_whitelisted_params(service, operation,
aws_meta, args, kwargs, response):
# check if service is whitelisted
if service not in whitelist['services']:
return
operations = whitelist['services'][service]['operations']
# check if operation is whitelisted
if operation not in operations:
return
params = operations[operation]
# record whitelisted request/response parameters
if 'request_parameters' in params:
_record_params(params['request_parameters'], args[1], aws_meta)
if 'request_descriptors' in params:
_record_special_params(params['request_descriptors'],
args[1], aws_meta)
if 'response_parameters' in params and response:
_record_params(params['response_parameters'], response, aws_meta)
if 'response_descriptors' in params and response:
_record_special_params(params['response_descriptors'],
response, aws_meta)
def _record_params(whitelisted, actual, aws_meta):
for key in whitelisted:
if key in actual:
snake_key = to_snake_case(key)
aws_meta[snake_key] = actual[key]
def _record_special_params(whitelisted, actual, aws_meta):
for key in whitelisted:
if key in actual:
_process_descriptor(whitelisted[key], actual[key], aws_meta)
def _process_descriptor(descriptor, value, aws_meta):
# "get_count" = true
if 'get_count' in descriptor and descriptor['get_count']:
value = len(value)
# "get_keys" = true
if 'get_keys' in descriptor and descriptor['get_keys']:
value = value.keys()
aws_meta[descriptor['rename_to']] = value
|