opentelemetry-python-contrib/reference/tests/contrib/aiobotocore/test.py

318 lines
12 KiB
Python

import aiobotocore
from botocore.errorfactory import ClientError
from ddtrace.contrib.aiobotocore.patch import patch, unpatch
from ddtrace.constants import ANALYTICS_SAMPLE_RATE_KEY
from ddtrace.compat import stringify
from .utils import aiobotocore_client
from ..asyncio.utils import AsyncioTestCase, mark_asyncio
from ...test_tracer import get_dummy_tracer
from ...utils import assert_span_http_status_code
class AIOBotocoreTest(AsyncioTestCase):
"""Botocore integration testsuite"""
def setUp(self):
super(AIOBotocoreTest, self).setUp()
patch()
self.tracer = get_dummy_tracer()
def tearDown(self):
super(AIOBotocoreTest, self).tearDown()
unpatch()
self.tracer = None
@mark_asyncio
def test_traced_client(self):
with aiobotocore_client('ec2', self.tracer) as ec2:
yield from ec2.describe_instances()
traces = self.tracer.writer.pop_traces()
self.assertEqual(len(traces), 1)
self.assertEqual(len(traces[0]), 1)
span = traces[0][0]
self.assertEqual(span.get_tag('aws.agent'), 'aiobotocore')
self.assertEqual(span.get_tag('aws.region'), 'us-west-2')
self.assertEqual(span.get_tag('aws.operation'), 'DescribeInstances')
assert_span_http_status_code(span, 200)
self.assertEqual(span.get_metric('retry_attempts'), 0)
self.assertEqual(span.service, 'aws.ec2')
self.assertEqual(span.resource, 'ec2.describeinstances')
self.assertEqual(span.name, 'ec2.command')
self.assertEqual(span.span_type, 'http')
self.assertIsNone(span.get_metric(ANALYTICS_SAMPLE_RATE_KEY))
@mark_asyncio
def test_traced_client_analytics(self):
with self.override_config(
'aiobotocore',
dict(analytics_enabled=True, analytics_sample_rate=0.5)
):
with aiobotocore_client('ec2', self.tracer) as ec2:
yield from ec2.describe_instances()
spans = self.get_spans()
assert spans
span = spans[0]
self.assertEqual(span.get_metric(ANALYTICS_SAMPLE_RATE_KEY), 0.5)
@mark_asyncio
def test_s3_client(self):
with aiobotocore_client('s3', self.tracer) as s3:
yield from s3.list_buckets()
yield from s3.list_buckets()
traces = self.tracer.writer.pop_traces()
self.assertEqual(len(traces), 2)
self.assertEqual(len(traces[0]), 1)
span = traces[0][0]
self.assertEqual(span.get_tag('aws.operation'), 'ListBuckets')
assert_span_http_status_code(span, 200)
self.assertEqual(span.service, 'aws.s3')
self.assertEqual(span.resource, 's3.listbuckets')
self.assertEqual(span.name, 's3.command')
@mark_asyncio
def test_s3_put(self):
params = dict(Key='foo', Bucket='mybucket', Body=b'bar')
with aiobotocore_client('s3', self.tracer) as s3:
yield from s3.create_bucket(Bucket='mybucket')
yield from s3.put_object(**params)
spans = [trace[0] for trace in self.tracer.writer.pop_traces()]
assert spans
self.assertEqual(len(spans), 2)
self.assertEqual(spans[0].get_tag('aws.operation'), 'CreateBucket')
assert_span_http_status_code(spans[0], 200)
self.assertEqual(spans[0].service, 'aws.s3')
self.assertEqual(spans[0].resource, 's3.createbucket')
self.assertEqual(spans[1].get_tag('aws.operation'), 'PutObject')
self.assertEqual(spans[1].resource, 's3.putobject')
self.assertEqual(spans[1].get_tag('params.Key'), stringify(params['Key']))
self.assertEqual(spans[1].get_tag('params.Bucket'), stringify(params['Bucket']))
self.assertIsNone(spans[1].get_tag('params.Body'))
@mark_asyncio
def test_s3_client_error(self):
with aiobotocore_client('s3', self.tracer) as s3:
with self.assertRaises(ClientError):
# FIXME: add proper clean-up to tearDown
yield from s3.list_objects(Bucket='doesnotexist')
traces = self.tracer.writer.pop_traces()
self.assertEqual(len(traces), 1)
self.assertEqual(len(traces[0]), 1)
span = traces[0][0]
self.assertEqual(span.resource, 's3.listobjects')
self.assertEqual(span.error, 1)
self.assertTrue('NoSuchBucket' in span.get_tag('error.msg'))
@mark_asyncio
def test_s3_client_read(self):
with aiobotocore_client('s3', self.tracer) as s3:
# prepare S3 and flush traces if any
yield from s3.create_bucket(Bucket='tracing')
yield from s3.put_object(Bucket='tracing', Key='apm', Body=b'')
self.tracer.writer.pop_traces()
# calls under test
response = yield from s3.get_object(Bucket='tracing', Key='apm')
yield from response['Body'].read()
traces = self.tracer.writer.pop_traces()
version = aiobotocore.__version__.split('.')
pre_08 = int(version[0]) == 0 and int(version[1]) < 8
if pre_08:
self.assertEqual(len(traces), 2)
self.assertEqual(len(traces[1]), 1)
else:
self.assertEqual(len(traces), 1)
self.assertEqual(len(traces[0]), 1)
span = traces[0][0]
self.assertEqual(span.get_tag('aws.operation'), 'GetObject')
assert_span_http_status_code(span, 200)
self.assertEqual(span.service, 'aws.s3')
self.assertEqual(span.resource, 's3.getobject')
if pre_08:
read_span = traces[1][0]
self.assertEqual(read_span.get_tag('aws.operation'), 'GetObject')
assert_span_http_status_code(read_span, 200)
self.assertEqual(read_span.service, 'aws.s3')
self.assertEqual(read_span.resource, 's3.getobject')
self.assertEqual(read_span.name, 's3.command.read')
# enforce parenting
self.assertEqual(read_span.parent_id, span.span_id)
self.assertEqual(read_span.trace_id, span.trace_id)
@mark_asyncio
def test_sqs_client(self):
with aiobotocore_client('sqs', self.tracer) as sqs:
yield from sqs.list_queues()
traces = self.tracer.writer.pop_traces()
self.assertEqual(len(traces), 1)
self.assertEqual(len(traces[0]), 1)
span = traces[0][0]
self.assertEqual(span.get_tag('aws.region'), 'us-west-2')
self.assertEqual(span.get_tag('aws.operation'), 'ListQueues')
assert_span_http_status_code(span, 200)
self.assertEqual(span.service, 'aws.sqs')
self.assertEqual(span.resource, 'sqs.listqueues')
@mark_asyncio
def test_kinesis_client(self):
with aiobotocore_client('kinesis', self.tracer) as kinesis:
yield from kinesis.list_streams()
traces = self.tracer.writer.pop_traces()
self.assertEqual(len(traces), 1)
self.assertEqual(len(traces[0]), 1)
span = traces[0][0]
self.assertEqual(span.get_tag('aws.region'), 'us-west-2')
self.assertEqual(span.get_tag('aws.operation'), 'ListStreams')
assert_span_http_status_code(span, 200)
self.assertEqual(span.service, 'aws.kinesis')
self.assertEqual(span.resource, 'kinesis.liststreams')
@mark_asyncio
def test_lambda_client(self):
with aiobotocore_client('lambda', self.tracer) as lambda_client:
# https://github.com/spulec/moto/issues/906
yield from lambda_client.list_functions(MaxItems=5)
traces = self.tracer.writer.pop_traces()
self.assertEqual(len(traces), 1)
self.assertEqual(len(traces[0]), 1)
span = traces[0][0]
self.assertEqual(span.get_tag('aws.region'), 'us-west-2')
self.assertEqual(span.get_tag('aws.operation'), 'ListFunctions')
assert_span_http_status_code(span, 200)
self.assertEqual(span.service, 'aws.lambda')
self.assertEqual(span.resource, 'lambda.listfunctions')
@mark_asyncio
def test_kms_client(self):
with aiobotocore_client('kms', self.tracer) as kms:
yield from kms.list_keys(Limit=21)
traces = self.tracer.writer.pop_traces()
self.assertEqual(len(traces), 1)
self.assertEqual(len(traces[0]), 1)
span = traces[0][0]
self.assertEqual(span.get_tag('aws.region'), 'us-west-2')
self.assertEqual(span.get_tag('aws.operation'), 'ListKeys')
assert_span_http_status_code(span, 200)
self.assertEqual(span.service, 'aws.kms')
self.assertEqual(span.resource, 'kms.listkeys')
# checking for protection on STS against security leak
self.assertEqual(span.get_tag('params'), None)
@mark_asyncio
def test_unpatch(self):
unpatch()
with aiobotocore_client('kinesis', self.tracer) as kinesis:
yield from kinesis.list_streams()
traces = self.tracer.writer.pop_traces()
self.assertEqual(len(traces), 0)
@mark_asyncio
def test_double_patch(self):
patch()
with aiobotocore_client('sqs', self.tracer) as sqs:
yield from sqs.list_queues()
traces = self.tracer.writer.pop_traces()
self.assertEqual(len(traces), 1)
self.assertEqual(len(traces[0]), 1)
@mark_asyncio
def test_opentraced_client(self):
from tests.opentracer.utils import init_tracer
ot_tracer = init_tracer('my_svc', self.tracer)
with ot_tracer.start_active_span('ot_outer_span'):
with aiobotocore_client('ec2', self.tracer) as ec2:
yield from ec2.describe_instances()
traces = self.tracer.writer.pop_traces()
print(traces)
self.assertEqual(len(traces), 1)
self.assertEqual(len(traces[0]), 2)
ot_span = traces[0][0]
dd_span = traces[0][1]
self.assertEqual(ot_span.resource, 'ot_outer_span')
self.assertEqual(ot_span.service, 'my_svc')
# confirm the parenting
self.assertEqual(ot_span.parent_id, None)
self.assertEqual(dd_span.parent_id, ot_span.span_id)
self.assertEqual(dd_span.get_tag('aws.agent'), 'aiobotocore')
self.assertEqual(dd_span.get_tag('aws.region'), 'us-west-2')
self.assertEqual(dd_span.get_tag('aws.operation'), 'DescribeInstances')
assert_span_http_status_code(dd_span, 200)
self.assertEqual(dd_span.get_metric('retry_attempts'), 0)
self.assertEqual(dd_span.service, 'aws.ec2')
self.assertEqual(dd_span.resource, 'ec2.describeinstances')
self.assertEqual(dd_span.name, 'ec2.command')
@mark_asyncio
def test_opentraced_s3_client(self):
from tests.opentracer.utils import init_tracer
ot_tracer = init_tracer('my_svc', self.tracer)
with ot_tracer.start_active_span('ot_outer_span'):
with aiobotocore_client('s3', self.tracer) as s3:
yield from s3.list_buckets()
with ot_tracer.start_active_span('ot_inner_span1'):
yield from s3.list_buckets()
with ot_tracer.start_active_span('ot_inner_span2'):
pass
traces = self.tracer.writer.pop_traces()
self.assertEqual(len(traces), 1)
self.assertEqual(len(traces[0]), 5)
ot_outer_span = traces[0][0]
dd_span = traces[0][1]
ot_inner_span = traces[0][2]
dd_span2 = traces[0][3]
ot_inner_span2 = traces[0][4]
self.assertEqual(ot_outer_span.resource, 'ot_outer_span')
self.assertEqual(ot_inner_span.resource, 'ot_inner_span1')
self.assertEqual(ot_inner_span2.resource, 'ot_inner_span2')
# confirm the parenting
self.assertEqual(ot_outer_span.parent_id, None)
self.assertEqual(dd_span.parent_id, ot_outer_span.span_id)
self.assertEqual(ot_inner_span.parent_id, ot_outer_span.span_id)
self.assertEqual(dd_span2.parent_id, ot_inner_span.span_id)
self.assertEqual(ot_inner_span2.parent_id, ot_outer_span.span_id)
self.assertEqual(dd_span.get_tag('aws.operation'), 'ListBuckets')
assert_span_http_status_code(dd_span, 200)
self.assertEqual(dd_span.service, 'aws.s3')
self.assertEqual(dd_span.resource, 's3.listbuckets')
self.assertEqual(dd_span.name, 's3.command')
self.assertEqual(dd_span2.get_tag('aws.operation'), 'ListBuckets')
assert_span_http_status_code(dd_span2, 200)
self.assertEqual(dd_span2.service, 'aws.s3')
self.assertEqual(dd_span2.resource, 's3.listbuckets')
self.assertEqual(dd_span2.name, 's3.command')