diff --git a/tests/test_tracing.py b/tests/test_tracing.py index e30d202c..0aa38613 100644 --- a/tests/test_tracing.py +++ b/tests/test_tracing.py @@ -1,8 +1,9 @@ -import unittest +import copy import functools import json +import pytest import os -import copy +import unittest from unittest.mock import MagicMock, Mock, patch, call @@ -48,32 +49,6 @@ event_samples = "tests/event_samples/" -span_to_finish = None - - -def _clean_up_span(): - global span_to_finish - if span_to_finish is not None: - span_to_finish.finish() - span_to_finish = None - - -def register_span(span): - global span_to_finish - _clean_up_span() - span_to_finish = span - return span - - -def wrapped_span_creator(span_creator_func): - def result_func(*args, **kwargs): - return register_span(span_creator_func(*args, **kwargs)) - - return result_func - - -create_inferred_span = wrapped_span_creator(create_inferred_span) - class ClientContext(object): def __init__(self, custom=None): @@ -712,160 +687,6 @@ def test_set_dd_trace_py_root_no_span_id(self): self.mock_activate.assert_has_calls([call(expected_context)]) -class TestAuthorizerInferredSpans(unittest.TestCase): - def setUp(self): - patcher = patch("ddtrace.Span.finish", autospec=True) - self.mock_span_stop = patcher.start() - self.addCleanup(patcher.stop) - - def tearDown(self): - _clean_up_span() - - def test_create_inferred_span_from_authorizer_request_api_gateway_v1_event(self): - event_sample_source = "authorizer-request-api-gateway-v1" - finish_time = ( - 1663295021.832 # request_time_epoch + integrationLatency for api-gateway-v1 - ) - span = self._authorizer_span_testing_items(event_sample_source, finish_time) - self._basic_common_checks(span, "aws.apigateway.rest") - - def test_create_inferred_span_from_authorizer_request_api_gateway_v1_cached_event( - self, - ): - event_sample_source = "authorizer-request-api-gateway-v1-cached" - test_file = event_samples + event_sample_source + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "abc123" # injected data's requestId is abc321 - span = create_inferred_span(event, ctx) - self.mock_span_stop.assert_not_called() # NO authorizer span is injected - self._basic_common_checks(span, "aws.apigateway.rest") - - def test_create_inferred_span_from_authorizer_token_api_gateway_v1_event(self): - event_sample_source = "authorizer-token-api-gateway-v1" - finish_time = ( - 1663295021.832 # request_time_epoch + integrationLatency for api-gateway-v1 - ) - span = self._authorizer_span_testing_items(event_sample_source, finish_time) - self._basic_common_checks(span, "aws.apigateway.rest") - - def test_create_inferred_span_from_authorizer_token_api_gateway_v2_cached_event( - self, - ): - event_sample_source = "authorizer-token-api-gateway-v1-cached" - test_file = event_samples + event_sample_source + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "abc123" # injected data's requestId is abc321 - span = create_inferred_span(event, ctx) - self.mock_span_stop.assert_not_called() # NO authorizer span is injected - self._basic_common_checks(span, "aws.apigateway.rest") - - def test_create_inferred_span_from_authorizer_request_api_gateway_v2_event(self): - event_sample_source = "authorizer-request-api-gateway-v2" - finish_time = 1664228639533775400 # use the injected parent span finish time as an approximation - test_file = event_samples + event_sample_source + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "abc123" - span = create_inferred_span(event, ctx) - self.assertEqual(span.get_tag(InferredSpanInfo.TAG_SOURCE), "self") - self.assertEqual(span.get_tag(InferredSpanInfo.SYNCHRONICITY), "sync") - self.mock_span_stop.assert_not_called() - self.assertEqual(span.start_ns, finish_time) - self._basic_common_checks(span, "aws.httpapi") - - def test_create_inferred_span_from_authorizer_request_api_gateway_v2_cached_event( - self, - ): - event_sample_source = "authorizer-request-api-gateway-v2-cached" - test_file = event_samples + event_sample_source + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "abc123" # injected data's requestId is abc321 - span = create_inferred_span(event, ctx) - self.mock_span_stop.assert_not_called() # NO authorizer span is injected - self._basic_common_checks(span, "aws.httpapi") - - def test_create_inferred_span_from_authorizer_request_api_gateway_websocket_connect_event( - self, - ): - event_sample_source = "authorizer-request-api-gateway-websocket-connect" - finish_time = ( - 1664388386.892 # request_time_epoch + integrationLatency in websocket case - ) - span = self._authorizer_span_testing_items(event_sample_source, finish_time) - self._basic_common_checks( - span, "aws.apigateway.websocket", "web", "$connect", None - ) - - def test_create_inferred_span_from_authorizer_request_api_gateway_websocket_message_event( - self, - ): - event_sample_source = "authorizer-request-api-gateway-websocket-message" - test_file = event_samples + event_sample_source + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "abc123" # injected data's requestId is abc321 - span = create_inferred_span(event, ctx) - self.mock_span_stop.assert_not_called() # NO authorizer span is injected - self._basic_common_checks(span, "aws.apigateway.websocket", "web", "main", None) - - def _authorizer_span_testing_items(self, event_sample_source, finish_time): - test_file = event_samples + event_sample_source + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "abc123" - span = create_inferred_span(event, ctx) - self.assertEqual(span.get_tag(InferredSpanInfo.TAG_SOURCE), "self") - self.assertEqual(span.get_tag(InferredSpanInfo.SYNCHRONICITY), "sync") - - # checking the upstream_authorizer_span - self.mock_span_stop.assert_called_once() - args, kwargs = self.mock_span_stop.call_args_list[0] - self.assertEqual(kwargs.get("finish_time", args[1]), finish_time) - self.assertEqual(span.start, finish_time) - authorizer_span = args[0] - self.assertEqual(authorizer_span.name, "aws.apigateway.authorizer") - self.assertEqual(span.parent_id, authorizer_span.span_id) - return span - - def _basic_common_checks( - self, - span, - operation_name, - span_type="http", - route_key="/hello", - http_method="GET", - ): - self.assertEqual(span.get_tag("apiid"), "amddr1rix9") - self.assertEqual(span.get_tag("apiname"), "amddr1rix9") - self.assertEqual(span.get_tag("stage"), "dev") - self.assertEqual(span.get_tag("operation_name"), operation_name) - self.assertEqual(span.span_type, span_type) - self.assertEqual( - span.service, - "amddr1rix9.execute-api.eu-west-1.amazonaws.com", - ) - self.assertEqual( - span.get_tag("http.url"), - "amddr1rix9.execute-api.eu-west-1.amazonaws.com" + route_key, - ) - self.assertEqual(span.get_tag("endpoint"), route_key) - self.assertEqual(span.get_tag("http.method"), http_method) - self.assertEqual( - span.get_tag("resource_names"), - f"{http_method} {route_key}" if http_method else route_key, - ) - self.assertEqual(span.get_tag("request_id"), "abc123") - - class TestServiceMapping(unittest.TestCase): def setUp(self): self.service_mapping = {} @@ -1369,545 +1190,589 @@ def test_remaps_specific_inferred_span_service_names_from_eventbridge_event( self.assertEqual(span2.service, "eventbridge") -class TestInferredSpans(unittest.TestCase): - def tearDown(self): - _clean_up_span() +class _Span(object): + def __init__(self, service, start, span_type, parent_name=None, tags=None): + self.service = service + self.start = start + self.span_type = span_type + self.parent_name = parent_name + self.tags = tags or {} + + +_test_create_inferred_span = ( + ( + "api-gateway", + _Span( + service="70ixmpl4fl.execute-api.us-east-2.amazonaws.com", + start=1428582896.0, + span_type="http", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "sync", + "_inferred_span.tag_source": "self", + "apiid": "1234567890", + "apiname": "1234567890", + "endpoint": "/path/to/resource", + "http.method": "POST", + "http.url": "70ixmpl4fl.execute-api.us-east-2.amazonaws.com/path/to/resource", + "operation_name": "aws.apigateway.rest", + "request_id": "123", + "resource_names": "POST /path/to/resource", + "stage": "prod", + }, + ), + ), + ( + "api-gateway-non-proxy-async", + _Span( + service="lgxbo6a518.execute-api.eu-west-1.amazonaws.com", + start=1631210915.2510002, + span_type="http", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "async", + "_inferred_span.tag_source": "self", + "apiid": "lgxbo6a518", + "apiname": "lgxbo6a518", + "endpoint": "/http/get", + "http.method": "GET", + "http.url": "lgxbo6a518.execute-api.eu-west-1.amazonaws.com/http/get", + "operation_name": "aws.apigateway.rest", + "request_id": "123", + "resource_names": "GET /http/get", + "stage": "dev", + }, + ), + ), + ( + "api-gateway-non-proxy", + _Span( + service="lgxbo6a518.execute-api.eu-west-1.amazonaws.com", + start=1631210915.2510002, + span_type="http", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "sync", + "_inferred_span.tag_source": "self", + "apiid": "lgxbo6a518", + "apiname": "lgxbo6a518", + "endpoint": "/http/get", + "http.method": "GET", + "http.url": "lgxbo6a518.execute-api.eu-west-1.amazonaws.com/http/get", + "operation_name": "aws.apigateway.rest", + "request_id": "123", + "resource_names": "GET /http/get", + "stage": "dev", + }, + ), + ), + ( + "http-api", + _Span( + service="x02yirxc7a.execute-api.eu-west-1.amazonaws.com", + start=1631212283.738, + span_type="http", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "sync", + "_inferred_span.tag_source": "self", + "apiid": "x02yirxc7a", + "apiname": "x02yirxc7a", + "endpoint": "/httpapi/get", + "http.method": "GET", + "http.protocol": "HTTP/1.1", + "http.source_ip": "38.122.226.210", + "http.url": "x02yirxc7a.execute-api.eu-west-1.amazonaws.com/httpapi/get", + "http.user_agent": "curl/7.64.1", + "operation_name": "aws.httpapi", + "request_id": "123", + "resource_names": "GET /httpapi/get", + "stage": "$default", + }, + ), + ), + ( + "api-gateway-websocket-default", + _Span( + service="p62c47itsb.execute-api.eu-west-1.amazonaws.com", + start=1631285061.365, + span_type="web", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "sync", + "_inferred_span.tag_source": "self", + "apiid": "p62c47itsb", + "apiname": "p62c47itsb", + "connection_id": "Fc5SzcoYGjQCJlg=", + "endpoint": "$default", + "event_type": "MESSAGE", + "http.url": "p62c47itsb.execute-api.eu-west-1.amazonaws.com$default", + "message_direction": "IN", + "operation_name": "aws.apigateway.websocket", + "request_id": "123", + "resource_names": "$default", + "stage": "dev", + }, + ), + ), + ( + "api-gateway-websocket-connect", + _Span( + service="p62c47itsb.execute-api.eu-west-1.amazonaws.com", + start=1631284003.071, + span_type="web", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "sync", + "_inferred_span.tag_source": "self", + "apiid": "p62c47itsb", + "apiname": "p62c47itsb", + "connection_id": "Fc2tgfl3mjQCJfA=", + "endpoint": "$connect", + "event_type": "CONNECT", + "http.url": "p62c47itsb.execute-api.eu-west-1.amazonaws.com$connect", + "message_direction": "IN", + "operation_name": "aws.apigateway.websocket", + "request_id": "123", + "resource_names": "$connect", + "stage": "dev", + }, + ), + ), + ( + "api-gateway-websocket-disconnect", + _Span( + service="p62c47itsb.execute-api.eu-west-1.amazonaws.com", + start=1631284034.737, + span_type="web", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "sync", + "_inferred_span.tag_source": "self", + "apiid": "p62c47itsb", + "apiname": "p62c47itsb", + "connection_id": "Fc2tgfl3mjQCJfA=", + "endpoint": "$disconnect", + "event_type": "DISCONNECT", + "http.url": "p62c47itsb.execute-api.eu-west-1.amazonaws.com$disconnect", + "message_direction": "IN", + "operation_name": "aws.apigateway.websocket", + "request_id": "123", + "resource_names": "$disconnect", + "stage": "dev", + }, + ), + ), + ( + "sqs-string-msg-attribute", + _Span( + service="sqs", + start=1634662094.538, + span_type="web", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "async", + "_inferred_span.tag_source": "self", + "event_source_arn": "arn:aws:sqs:eu-west-1:601427279990:InferredSpansQueueNode", + "operation_name": "aws.sqs", + "queuename": "InferredSpansQueueNode", + "resource_names": "InferredSpansQueueNode", + "sender_id": "AROAYYB64AB3LSVUYFP5T:harv-inferred-spans-dev-initSender", + }, + ), + ), + ( + "sns-string-msg-attribute", + _Span( + service="sns", + start=1643638421.637, + span_type="web", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "async", + "_inferred_span.tag_source": "self", + "message_id": "87056a47-f506-5d77-908b-303605d3b197", + "operation_name": "aws.sns", + "resource_names": "serverlessTracingTopicPy", + "topic_arn": "arn:aws:sns:eu-west-1:601427279990:serverlessTracingTopicPy", + "topicname": "serverlessTracingTopicPy", + "type": "Notification", + }, + ), + ), + ( + "sns-b64-msg-attribute", + _Span( + service="sns", + start=1643638421.637, + span_type="web", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "async", + "_inferred_span.tag_source": "self", + "message_id": "87056a47-f506-5d77-908b-303605d3b197", + "operation_name": "aws.sns", + "resource_names": "serverlessTracingTopicPy", + "topic_arn": "arn:aws:sns:eu-west-1:601427279990:serverlessTracingTopicPy", + "topicname": "serverlessTracingTopicPy", + "type": "Notification", + }, + ), + ), + ( + "kinesis", + _Span( + service="kinesis", + start=1643638425.163, + span_type="web", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "async", + "_inferred_span.tag_source": "self", + "endpoint": None, + "event_id": "shardId-000000000002:49624230154685806402418173680709770494154422022871973922", + "event_name": "aws:kinesis:record", + "event_source_arn": "arn:aws:kinesis:eu-west-1:601427279990:stream/kinesisStream", + "event_version": "1.0", + "http.method": None, + "http.url": None, + "operation_name": "aws.kinesis", + "partition_key": "partitionkey", + "request_id": None, + "resource_names": "stream/kinesisStream", + "shardid": "shardId-000000000002", + "streamname": "stream/kinesisStream", + }, + ), + ), + ( + "dynamodb", + _Span( + service="dynamodb", + start=1428537600.0, + span_type="web", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "async", + "_inferred_span.tag_source": "self", + "endpoint": None, + "event_id": "c4ca4238a0b923820dcc509a6f75849b", + "event_name": "INSERT", + "event_source_arn": "arn:aws:dynamodb:us-east-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899", + "event_version": "1.1", + "http.method": None, + "http.url": None, + "operation_name": "aws.dynamodb", + "request_id": None, + "resource_names": "ExampleTableWithStream", + "size_bytes": "26", + "stream_view_type": "NEW_AND_OLD_IMAGES", + "tablename": "ExampleTableWithStream", + }, + ), + ), + ( + "s3", + _Span( + service="s3", + start=0.0, + span_type="web", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "async", + "_inferred_span.tag_source": "self", + "bucket_arn": "arn:aws:s3:::example-bucket", + "bucketname": "example-bucket", + "endpoint": None, + "event_name": "ObjectCreated:Put", + "http.method": None, + "http.url": None, + "object_etag": "0123456789abcdef0123456789abcdef", + "object_key": "test/key", + "object_size": "1024", + "operation_name": "aws.s3", + "request_id": None, + "resource_names": "example-bucket", + }, + ), + ), + ( + "eventbridge-custom", + _Span( + service="eventbridge", + start=1635989865.0, + span_type="web", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "async", + "_inferred_span.tag_source": "self", + "endpoint": None, + "http.method": None, + "http.url": None, + "operation_name": "aws.eventbridge", + "request_id": None, + "resource_names": "eventbridge.custom.event.sender", + }, + ), + ), + ( + "eventbridge-sqs", + _Span( + service="sqs", + start=1691102943.638, + span_type="web", + parent_name="aws.eventbridge", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "async", + "_inferred_span.tag_source": "self", + "endpoint": None, + "event_source_arn": "arn:aws:sqs:us-east-1:425362996713:eventbridge-sqs-queue", + "http.method": None, + "http.url": None, + "operation_name": "aws.sqs", + "queuename": "eventbridge-sqs-queue", + "request_id": None, + "resource_names": "eventbridge-sqs-queue", + "sender_id": "AIDAJXNJGGKNS7OSV23OI", + }, + ), + ), + ( + "api-gateway-no-apiid", + _Span( + service="70ixmpl4fl.execute-api.us-east-2.amazonaws.com", + start=1428582896.0, + span_type="http", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "sync", + "_inferred_span.tag_source": "self", + "apiid": "None", + "apiname": "None", + "endpoint": "/path/to/resource", + "http.method": "POST", + "http.url": "70ixmpl4fl.execute-api.us-east-2.amazonaws.com/path/to/resource", + "operation_name": "aws.apigateway.rest", + "request_id": "123", + "resource_names": "POST /path/to/resource", + "stage": "prod", + }, + ), + ), + ( + "authorizer-request-api-gateway-v1", + _Span( + service="amddr1rix9.execute-api.eu-west-1.amazonaws.com", + start=1663295021.832, + span_type="http", + parent_name="aws.apigateway.authorizer", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "sync", + "_inferred_span.tag_source": "self", + "apiid": "amddr1rix9", + "apiname": "amddr1rix9", + "endpoint": "/hello", + "http.method": "GET", + "http.url": "amddr1rix9.execute-api.eu-west-1.amazonaws.com/hello", + "operation_name": "aws.apigateway.rest", + "request_id": "123", + "resource_names": "GET /hello", + "stage": "dev", + }, + ), + ), + ( + "authorizer-request-api-gateway-v1-cached", + _Span( + service="amddr1rix9.execute-api.eu-west-1.amazonaws.com", + start=1666714653.636, + span_type="http", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "sync", + "_inferred_span.tag_source": "self", + "apiid": "amddr1rix9", + "apiname": "amddr1rix9", + "endpoint": "/hello", + "http.method": "GET", + "http.url": "amddr1rix9.execute-api.eu-west-1.amazonaws.com/hello", + "operation_name": "aws.apigateway.rest", + "request_id": "123", + "resource_names": "GET /hello", + "stage": "dev", + }, + ), + ), + ( + "authorizer-token-api-gateway-v1", + _Span( + service="amddr1rix9.execute-api.eu-west-1.amazonaws.com", + start=1663295021.832, + span_type="http", + parent_name="aws.apigateway.authorizer", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "sync", + "_inferred_span.tag_source": "self", + "apiid": "amddr1rix9", + "apiname": "amddr1rix9", + "endpoint": "/hello", + "http.method": "GET", + "http.url": "amddr1rix9.execute-api.eu-west-1.amazonaws.com/hello", + "operation_name": "aws.apigateway.rest", + "request_id": "123", + "resource_names": "GET /hello", + "stage": "dev", + }, + ), + ), + ( + "authorizer-token-api-gateway-v1-cached", + _Span( + service="amddr1rix9.execute-api.eu-west-1.amazonaws.com", + start=1666803622.99, + span_type="http", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "sync", + "_inferred_span.tag_source": "self", + "apiid": "amddr1rix9", + "apiname": "amddr1rix9", + "endpoint": "/hello", + "http.method": "GET", + "http.url": "amddr1rix9.execute-api.eu-west-1.amazonaws.com/hello", + "operation_name": "aws.apigateway.rest", + "request_id": "123", + "resource_names": "GET /hello", + "stage": "dev", + }, + ), + ), + ( + "authorizer-request-api-gateway-v2", + _Span( + service="amddr1rix9.execute-api.eu-west-1.amazonaws.com", + start=1664228639.5337753, + span_type="http", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "sync", + "_inferred_span.tag_source": "self", + "apiid": "amddr1rix9", + "apiname": "amddr1rix9", + "endpoint": "/hello", + "http.method": "GET", + "http.url": "amddr1rix9.execute-api.eu-west-1.amazonaws.com/hello", + "operation_name": "aws.httpapi", + "request_id": "123", + "resource_names": "GET /hello", + "stage": "dev", + }, + ), + ), + ( + "authorizer-request-api-gateway-v2-cached", + _Span( + service="amddr1rix9.execute-api.eu-west-1.amazonaws.com", + start=1666715429.349, + span_type="http", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "sync", + "_inferred_span.tag_source": "self", + "apiid": "amddr1rix9", + "apiname": "amddr1rix9", + "endpoint": "/hello", + "http.method": "GET", + "http.url": "amddr1rix9.execute-api.eu-west-1.amazonaws.com/hello", + "operation_name": "aws.httpapi", + "request_id": "123", + "resource_names": "GET /hello", + "stage": "dev", + }, + ), + ), + ( + "authorizer-request-api-gateway-websocket-connect", + _Span( + service="amddr1rix9.execute-api.eu-west-1.amazonaws.com", + start=1664388386.892, + span_type="web", + parent_name="aws.apigateway.authorizer", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "sync", + "_inferred_span.tag_source": "self", + "apiid": "amddr1rix9", + "apiname": "amddr1rix9", + "connection_id": "ZLr9QeNLmjQCIZA=", + "endpoint": "$connect", + "event_type": "CONNECT", + "http.url": "amddr1rix9.execute-api.eu-west-1.amazonaws.com$connect", + "message_direction": "IN", + "operation_name": "aws.apigateway.websocket", + "request_id": "123", + "resource_names": "$connect", + "stage": "dev", + }, + ), + ), + ( + "authorizer-request-api-gateway-websocket-message", + _Span( + service="amddr1rix9.execute-api.eu-west-1.amazonaws.com", + start=1664390397.1169999, + span_type="web", + tags={ + "_dd.origin": "lambda", + "_inferred_span.synchronicity": "sync", + "_inferred_span.tag_source": "self", + "apiid": "amddr1rix9", + "apiname": "amddr1rix9", + "connection_id": "ZLwtceO1mjQCI8Q=", + "endpoint": "main", + "event_type": "MESSAGE", + "http.url": "amddr1rix9.execute-api.eu-west-1.amazonaws.commain", + "message_direction": "IN", + "operation_name": "aws.apigateway.websocket", + "request_id": "123", + "resource_names": "main", + "stage": "dev", + }, + ), + ), +) - def test_create_inferred_span_from_api_gateway_event(self): - event_sample_source = "api-gateway" - test_file = event_samples + event_sample_source + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "123" - span = create_inferred_span(event, ctx) - self.assertEqual(span.get_tag("operation_name"), "aws.apigateway.rest") - self.assertEqual( - span.service, - "70ixmpl4fl.execute-api.us-east-2.amazonaws.com", - ) - self.assertEqual( - span.get_tag("http.url"), - "70ixmpl4fl.execute-api.us-east-2.amazonaws.com/path/to/resource", - ) - self.assertEqual(span.get_tag("endpoint"), "/path/to/resource") - self.assertEqual(span.get_tag("http.method"), "POST") - self.assertEqual( - span.get_tag("resource_names"), - "POST /path/to/resource", - ) - self.assertEqual(span.get_tag("request_id"), "123") - self.assertEqual(span.get_tag("apiid"), "1234567890") - self.assertEqual(span.get_tag("apiname"), "1234567890") - self.assertEqual(span.get_tag("stage"), "prod") - self.assertEqual(span.start, 1428582896.0) - self.assertEqual(span.span_type, "http") - self.assertEqual(span.get_tag(InferredSpanInfo.TAG_SOURCE), "self") - self.assertEqual(span.get_tag(InferredSpanInfo.SYNCHRONICITY), "sync") - - def test_create_inferred_span_from_api_gateway_non_proxy_event_async(self): - event_sample_source = "api-gateway-non-proxy-async" - test_file = event_samples + event_sample_source + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "123" - span = create_inferred_span(event, ctx) - self.assertEqual(span.get_tag("operation_name"), "aws.apigateway.rest") - self.assertEqual( - span.service, - "lgxbo6a518.execute-api.eu-west-1.amazonaws.com", - ) - self.assertEqual( - span.get_tag("http.url"), - "lgxbo6a518.execute-api.eu-west-1.amazonaws.com/http/get", - ) - self.assertEqual(span.get_tag("endpoint"), "/http/get") - self.assertEqual(span.get_tag("http.method"), "GET") - self.assertEqual( - span.get_tag("resource_names"), - "GET /http/get", - ) - self.assertEqual(span.get_tag("request_id"), "123") - self.assertEqual(span.get_tag("apiid"), "lgxbo6a518") - self.assertEqual(span.get_tag("apiname"), "lgxbo6a518") - self.assertEqual(span.get_tag("stage"), "dev") - self.assertEqual(span.start, 1631210915.2510002) - self.assertEqual(span.span_type, "http") - self.assertEqual(span.get_tag(InferredSpanInfo.TAG_SOURCE), "self") - self.assertEqual(span.get_tag(InferredSpanInfo.SYNCHRONICITY), "async") - - def test_create_inferred_span_from_api_gateway_non_proxy_event_sync(self): - event_sample_source = "api-gateway-non-proxy" - test_file = event_samples + event_sample_source + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "123" - span = create_inferred_span(event, ctx) - self.assertEqual(span.get_tag("operation_name"), "aws.apigateway.rest") - self.assertEqual( - span.service, - "lgxbo6a518.execute-api.eu-west-1.amazonaws.com", - ) - self.assertEqual( - span.get_tag("http.url"), - "lgxbo6a518.execute-api.eu-west-1.amazonaws.com/http/get", - ) - self.assertEqual(span.get_tag("endpoint"), "/http/get") - self.assertEqual(span.get_tag("http.method"), "GET") - self.assertEqual( - span.get_tag("resource_names"), - "GET /http/get", - ) - self.assertEqual(span.get_tag("request_id"), "123") - self.assertEqual(span.get_tag("apiid"), "lgxbo6a518") - self.assertEqual(span.get_tag("apiname"), "lgxbo6a518") - self.assertEqual(span.get_tag("stage"), "dev") - self.assertEqual(span.start, 1631210915.2510002) - self.assertEqual(span.span_type, "http") - self.assertEqual(span.get_tag(InferredSpanInfo.TAG_SOURCE), "self") - self.assertEqual(span.get_tag(InferredSpanInfo.SYNCHRONICITY), "sync") - - def test_create_inferred_span_from_http_api_event(self): - event_sample_source = "http-api" - test_file = event_samples + event_sample_source + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "123" - span = create_inferred_span(event, ctx) - self.assertEqual(span.get_tag("operation_name"), "aws.httpapi") - self.assertEqual( - span.service, - "x02yirxc7a.execute-api.eu-west-1.amazonaws.com", - ) - self.assertEqual( - span.get_tag("http.url"), - "x02yirxc7a.execute-api.eu-west-1.amazonaws.com/httpapi/get", - ) - self.assertEqual(span.get_tag("endpoint"), "/httpapi/get") - self.assertEqual(span.get_tag("http.method"), "GET") - self.assertEqual( - span.get_tag("resource_names"), - "GET /httpapi/get", - ) - self.assertEqual(span.get_tag("request_id"), "123") - self.assertEqual(span.get_tag("apiid"), "x02yirxc7a") - self.assertEqual(span.get_tag("apiname"), "x02yirxc7a") - self.assertEqual(span.get_tag("stage"), "$default") - self.assertEqual(span.get_tag("http.protocol"), "HTTP/1.1") - self.assertEqual(span.get_tag("http.source_ip"), "38.122.226.210") - self.assertEqual(span.get_tag("http.user_agent"), "curl/7.64.1") - self.assertEqual(span.start, 1631212283.738) - self.assertEqual(span.span_type, "http") - self.assertEqual(span.get_tag(InferredSpanInfo.TAG_SOURCE), "self") - self.assertEqual(span.get_tag(InferredSpanInfo.SYNCHRONICITY), "sync") - - def test_create_inferred_span_from_api_gateway_websocket_default_event(self): - event_sample_source = "api-gateway-websocket-default" - test_file = event_samples + event_sample_source + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "123" - span = create_inferred_span(event, ctx) - self.assertEqual(span.get_tag("operation_name"), "aws.apigateway.websocket") - self.assertEqual( - span.service, - "p62c47itsb.execute-api.eu-west-1.amazonaws.com", - ) - self.assertEqual( - span.get_tag("http.url"), - "p62c47itsb.execute-api.eu-west-1.amazonaws.com$default", - ) - self.assertEqual(span.get_tag("endpoint"), "$default") - self.assertEqual(span.get_tag("http.method"), None) - self.assertEqual( - span.get_tag("resource_names"), - "$default", - ) - self.assertEqual(span.get_tag("request_id"), "123") - self.assertEqual(span.get_tag("apiid"), "p62c47itsb") - self.assertEqual(span.get_tag("apiname"), "p62c47itsb") - self.assertEqual(span.get_tag("stage"), "dev") - self.assertEqual(span.get_tag("connection_id"), "Fc5SzcoYGjQCJlg=") - self.assertEqual(span.get_tag("event_type"), "MESSAGE") - self.assertEqual(span.get_tag("message_direction"), "IN") - self.assertEqual(span.start, 1631285061.365) - self.assertEqual(span.span_type, "web") - self.assertEqual(span.get_tag(InferredSpanInfo.TAG_SOURCE), "self") - self.assertEqual(span.get_tag(InferredSpanInfo.SYNCHRONICITY), "sync") - - def test_create_inferred_span_from_api_gateway_websocket_connect_event(self): - event_sample_source = "api-gateway-websocket-connect" - test_file = event_samples + event_sample_source + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "123" - span = create_inferred_span(event, ctx) - self.assertEqual(span.get_tag("operation_name"), "aws.apigateway.websocket") - self.assertEqual( - span.service, - "p62c47itsb.execute-api.eu-west-1.amazonaws.com", - ) - self.assertEqual( - span.get_tag("http.url"), - "p62c47itsb.execute-api.eu-west-1.amazonaws.com$connect", - ) - self.assertEqual(span.get_tag("endpoint"), "$connect") - self.assertEqual(span.get_tag("http.method"), None) - self.assertEqual( - span.get_tag("resource_names"), - "$connect", - ) - self.assertEqual(span.get_tag("request_id"), "123") - self.assertEqual(span.get_tag("apiid"), "p62c47itsb") - self.assertEqual(span.get_tag("apiname"), "p62c47itsb") - self.assertEqual(span.get_tag("stage"), "dev") - self.assertEqual(span.get_tag("connection_id"), "Fc2tgfl3mjQCJfA=") - self.assertEqual(span.get_tag("event_type"), "CONNECT") - self.assertEqual(span.get_tag("message_direction"), "IN") - self.assertEqual(span.start, 1631284003.071) - self.assertEqual(span.span_type, "web") - self.assertEqual(span.get_tag(InferredSpanInfo.TAG_SOURCE), "self") - self.assertEqual(span.get_tag(InferredSpanInfo.SYNCHRONICITY), "sync") - - def test_create_inferred_span_from_api_gateway_websocket_disconnect_event(self): - event_sample_source = "api-gateway-websocket-disconnect" - test_file = event_samples + event_sample_source + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "123" - span = create_inferred_span(event, ctx) - self.assertEqual(span.get_tag("operation_name"), "aws.apigateway.websocket") - self.assertEqual( - span.service, - "p62c47itsb.execute-api.eu-west-1.amazonaws.com", - ) - self.assertEqual( - span.get_tag("http.url"), - "p62c47itsb.execute-api.eu-west-1.amazonaws.com$disconnect", - ) - self.assertEqual(span.get_tag("endpoint"), "$disconnect") - self.assertEqual(span.get_tag("http.method"), None) - self.assertEqual( - span.get_tag("resource_names"), - "$disconnect", - ) - self.assertEqual(span.get_tag("request_id"), "123") - self.assertEqual(span.get_tag("apiid"), "p62c47itsb") - self.assertEqual(span.get_tag("apiname"), "p62c47itsb") - self.assertEqual(span.get_tag("stage"), "dev") - self.assertEqual(span.get_tag("connection_id"), "Fc2tgfl3mjQCJfA=") - self.assertEqual(span.get_tag("event_type"), "DISCONNECT") - self.assertEqual(span.get_tag("message_direction"), "IN") - self.assertEqual(span.start, 1631284034.737) - self.assertEqual(span.span_type, "web") - self.assertEqual(span.get_tag(InferredSpanInfo.TAG_SOURCE), "self") - self.assertEqual(span.get_tag(InferredSpanInfo.SYNCHRONICITY), "sync") - - def test_create_inferred_span_from_sqs_event_string_msg_attr(self): - event_sample_name = "sqs-string-msg-attribute" - test_file = event_samples + event_sample_name + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "123" - span = create_inferred_span(event, ctx) - self.assertEqual(span.get_tag("operation_name"), "aws.sqs") - self.assertEqual( - span.service, - "sqs", - ) - self.assertEqual( - span.get_tag("http.url"), - None, - ) - self.assertEqual(span.get_tag("endpoint"), None) - self.assertEqual(span.get_tag("http.method"), None) - self.assertEqual( - span.get_tag("resource_names"), - "InferredSpansQueueNode", - ) - self.assertEqual(span.get_tag("request_id"), None) - self.assertEqual(span.get_tag("queuename"), "InferredSpansQueueNode") - self.assertEqual( - span.get_tag("event_source_arn"), - "arn:aws:sqs:eu-west-1:601427279990:InferredSpansQueueNode", - ) - self.assertEqual( - span.get_tag("sender_id"), - "AROAYYB64AB3LSVUYFP5T:harv-inferred-spans-dev-initSender", - ) - self.assertEqual(span.start, 1634662094.538) - self.assertEqual(span.span_type, "web") - self.assertEqual(span.get_tag(InferredSpanInfo.TAG_SOURCE), "self") - self.assertEqual(span.get_tag(InferredSpanInfo.SYNCHRONICITY), "async") - - def test_create_inferred_span_from_sns_event_string_msg_attr(self): - event_sample_name = "sns-string-msg-attribute" - test_file = event_samples + event_sample_name + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "123" - span = create_inferred_span(event, ctx) - self.assertEqual(span.get_tag("operation_name"), "aws.sns") - self.assertEqual( - span.service, - "sns", - ) - self.assertEqual( - span.get_tag("http.url"), - None, - ) - self.assertEqual(span.get_tag("endpoint"), None) - self.assertEqual(span.get_tag("http.method"), None) - self.assertEqual( - span.get_tag("resource_names"), - "serverlessTracingTopicPy", - ) - self.assertEqual(span.get_tag("topicname"), "serverlessTracingTopicPy") - self.assertEqual( - span.get_tag("topic_arn"), - "arn:aws:sns:eu-west-1:601427279990:serverlessTracingTopicPy", - ) - self.assertEqual( - span.get_tag("message_id"), "87056a47-f506-5d77-908b-303605d3b197" - ) - self.assertEqual(span.get_tag("type"), "Notification") - self.assertEqual(span.get_tag("subject"), None) - self.assertEqual(span.start, 1643638421.637) - self.assertEqual(span.span_type, "web") - self.assertEqual(span.get_tag(InferredSpanInfo.TAG_SOURCE), "self") - self.assertEqual(span.get_tag(InferredSpanInfo.SYNCHRONICITY), "async") - - def test_create_inferred_span_from_sns_event_b64_msg_attr(self): - event_sample_name = "sns-b64-msg-attribute" - test_file = event_samples + event_sample_name + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "123" - span = create_inferred_span(event, ctx) - self.assertEqual(span.get_tag("operation_name"), "aws.sns") - self.assertEqual( - span.service, - "sns", - ) - self.assertEqual( - span.get_tag("http.url"), - None, - ) - self.assertEqual(span.get_tag("endpoint"), None) - self.assertEqual(span.get_tag("http.method"), None) - self.assertEqual( - span.get_tag("resource_names"), - "serverlessTracingTopicPy", - ) - self.assertEqual(span.get_tag("topicname"), "serverlessTracingTopicPy") - self.assertEqual( - span.get_tag("topic_arn"), - "arn:aws:sns:eu-west-1:601427279990:serverlessTracingTopicPy", - ) - self.assertEqual( - span.get_tag("message_id"), "87056a47-f506-5d77-908b-303605d3b197" - ) - self.assertEqual(span.get_tag("type"), "Notification") - self.assertEqual(span.get_tag("subject"), None) - self.assertEqual(span.start, 1643638421.637) - self.assertEqual(span.span_type, "web") - self.assertEqual(span.get_tag(InferredSpanInfo.TAG_SOURCE), "self") - self.assertEqual(span.get_tag(InferredSpanInfo.SYNCHRONICITY), "async") - - def test_create_inferred_span_from_kinesis_event(self): - event_sample_source = "kinesis" - test_file = event_samples + event_sample_source + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "123" - span = create_inferred_span(event, ctx) - self.assertEqual(span.get_tag("operation_name"), "aws.kinesis") - self.assertEqual( - span.service, - "kinesis", - ) - self.assertEqual( - span.get_tag("http.url"), - None, - ) - self.assertEqual(span.get_tag("endpoint"), None) - self.assertEqual(span.get_tag("http.method"), None) - self.assertEqual( - span.get_tag("resource_names"), - "stream/kinesisStream", - ) - self.assertEqual(span.get_tag("request_id"), None) - self.assertEqual(span.get_tag("streamname"), "stream/kinesisStream") - self.assertEqual(span.get_tag("shardid"), "shardId-000000000002") - self.assertEqual( - span.get_tag("event_source_arn"), - "arn:aws:kinesis:eu-west-1:601427279990:stream/kinesisStream", - ) - self.assertEqual( - span.get_tag("event_id"), - "shardId-000000000002:49624230154685806402418173680709770494154422022871973922", - ) - self.assertEqual(span.get_tag("event_name"), "aws:kinesis:record") - self.assertEqual(span.get_tag("event_version"), "1.0") - self.assertEqual(span.get_tag("partition_key"), "partitionkey") - self.assertEqual(span.start, 1643638425.163) - self.assertEqual(span.span_type, "web") - self.assertEqual(span.get_tag(InferredSpanInfo.TAG_SOURCE), "self") - self.assertEqual(span.get_tag(InferredSpanInfo.SYNCHRONICITY), "async") - - def test_create_inferred_span_from_dynamodb_event(self): - event_sample_source = "dynamodb" - test_file = event_samples + event_sample_source + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "123" - span = create_inferred_span(event, ctx) - self.assertEqual(span.get_tag("operation_name"), "aws.dynamodb") - self.assertEqual( - span.service, - "dynamodb", - ) - self.assertEqual( - span.get_tag("http.url"), - None, - ) - self.assertEqual(span.get_tag("endpoint"), None) - self.assertEqual(span.get_tag("http.method"), None) - self.assertEqual( - span.get_tag("resource_names"), - "ExampleTableWithStream", - ) - self.assertEqual(span.get_tag("request_id"), None) - self.assertEqual(span.get_tag("tablename"), "ExampleTableWithStream") - self.assertEqual( - span.get_tag("event_source_arn"), - "arn:aws:dynamodb:us-east-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899", - ) - self.assertEqual(span.get_tag("event_id"), "c4ca4238a0b923820dcc509a6f75849b") - self.assertEqual(span.get_tag("event_name"), "INSERT") - self.assertEqual(span.get_tag("event_version"), "1.1") - self.assertEqual(span.get_tag("stream_view_type"), "NEW_AND_OLD_IMAGES") - self.assertEqual(span.get_tag("size_bytes"), "26") - self.assertEqual(span.start, 1428537600.0) - self.assertEqual(span.span_type, "web") - self.assertEqual(span.get_tag(InferredSpanInfo.TAG_SOURCE), "self") - self.assertEqual(span.get_tag(InferredSpanInfo.SYNCHRONICITY), "async") - - def test_create_inferred_span_from_s3_event(self): - event_sample_source = "s3" - test_file = event_samples + event_sample_source + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "123" - span = create_inferred_span(event, ctx) - self.assertEqual(span.get_tag("operation_name"), "aws.s3") - self.assertEqual( - span.service, - "s3", - ) - self.assertEqual( - span.get_tag("http.url"), - None, - ) - self.assertEqual(span.get_tag("endpoint"), None) - self.assertEqual(span.get_tag("http.method"), None) - self.assertEqual( - span.get_tag("resource_names"), - "example-bucket", - ) - self.assertEqual(span.get_tag("request_id"), None) - self.assertEqual(span.get_tag("event_name"), "ObjectCreated:Put") - self.assertEqual(span.get_tag("bucketname"), "example-bucket") - self.assertEqual(span.get_tag("bucket_arn"), "arn:aws:s3:::example-bucket") - self.assertEqual(span.get_tag("object_key"), "test/key") - self.assertEqual(span.get_tag("object_size"), "1024") - self.assertEqual( - span.get_tag("object_etag"), "0123456789abcdef0123456789abcdef" - ) - self.assertEqual(span.start, 0.0) - self.assertEqual(span.span_type, "web") - self.assertEqual(span.get_tag(InferredSpanInfo.TAG_SOURCE), "self") - self.assertEqual(span.get_tag(InferredSpanInfo.SYNCHRONICITY), "async") - def test_create_inferred_span_from_eventbridge_event(self): - event_sample_source = "eventbridge-custom" - test_file = event_samples + event_sample_source + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "123" - span = create_inferred_span(event, ctx) - self.assertEqual(span.get_tag("operation_name"), "aws.eventbridge") - self.assertEqual( - span.service, - "eventbridge", - ) - self.assertEqual( - span.get_tag("http.url"), - None, - ) - self.assertEqual(span.get_tag("endpoint"), None) - self.assertEqual(span.get_tag("http.method"), None) - self.assertEqual( - span.get_tag("resource_names"), - "eventbridge.custom.event.sender", - ) - self.assertEqual(span.get_tag("request_id"), None) - self.assertEqual(span.start, 1635989865.0) - self.assertEqual(span.span_type, "web") - self.assertEqual(span.get_tag(InferredSpanInfo.TAG_SOURCE), "self") - self.assertEqual(span.get_tag(InferredSpanInfo.SYNCHRONICITY), "async") - - def test_create_inferred_span_from_eventbridge_sqs_event(self): - event_sample_name = "eventbridge-sqs" - test_file = event_samples + event_sample_name + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "123" - span = create_inferred_span(event, ctx) - self.assertEqual(span.get_tag("operation_name"), "aws.sqs") - self.assertEqual( - span.service, - "sqs", - ) - self.assertEqual( - span.get_tag("http.url"), - None, - ) - self.assertEqual(span.get_tag("endpoint"), None) - self.assertEqual(span.get_tag("http.method"), None) - self.assertEqual( - span.get_tag("resource_names"), - "eventbridge-sqs-queue", - ) - self.assertEqual(span.get_tag("request_id"), None) - self.assertEqual(span.get_tag("queuename"), "eventbridge-sqs-queue") - self.assertEqual( - span.get_tag("event_source_arn"), - "arn:aws:sqs:us-east-1:425362996713:eventbridge-sqs-queue", - ) - self.assertEqual( - span.get_tag("sender_id"), - "AIDAJXNJGGKNS7OSV23OI", - ) - self.assertEqual(span.start, 1691102943.638) - self.assertEqual(span.span_type, "web") - self.assertEqual(span.get_tag(InferredSpanInfo.TAG_SOURCE), "self") - self.assertEqual(span.get_tag(InferredSpanInfo.SYNCHRONICITY), "async") +@pytest.mark.parametrize("source,expect", _test_create_inferred_span) +@patch("ddtrace.Span.finish", autospec=True) +def test_create_inferred_span(mock_span_finish, source, expect): + with open(f"{event_samples}{source}.json") as f: + event = json.load(f) + ctx = get_mock_context(aws_request_id="123") + + actual = create_inferred_span(event, ctx) + assert actual.service == expect.service + assert actual.start == expect.start + assert actual.span_type == expect.span_type + for tag, value in expect.tags.items(): + assert actual.get_tag(tag) == value, f"wrong value for tag {tag}" + + if expect.parent_name is not None: # there are two inferred spans + assert mock_span_finish.call_count == 1 + args, kwargs = mock_span_finish.call_args_list[0] + parent = args[0] + finish_time = kwargs.get("finish_time") or args[1] + assert parent.name == expect.parent_name + assert actual.parent_id == parent.span_id + assert finish_time == expect.start + else: # there is only one inferred span + assert mock_span_finish.call_count == 0 + +class TestInferredSpans(unittest.TestCase): def test_extract_context_from_eventbridge_event(self): event_sample_source = "eventbridge-custom" test_file = event_samples + event_sample_source + ".json" @@ -2029,38 +1894,6 @@ def test_extract_context_from_kinesis_batch_event(self): self.assertEqual(context.span_id, 2876253380018681026) self.assertEqual(context.sampling_priority, 1) - def test_create_inferred_span_from_api_gateway_event_no_apiid(self): - event_sample_source = "api-gateway-no-apiid" - test_file = event_samples + event_sample_source + ".json" - with open(test_file, "r") as event: - event = json.load(event) - ctx = get_mock_context() - ctx.aws_request_id = "123" - span = create_inferred_span(event, ctx) - self.assertEqual(span.get_tag("operation_name"), "aws.apigateway.rest") - self.assertEqual( - span.service, - "70ixmpl4fl.execute-api.us-east-2.amazonaws.com", - ) - self.assertEqual( - span.get_tag("http.url"), - "70ixmpl4fl.execute-api.us-east-2.amazonaws.com/path/to/resource", - ) - self.assertEqual(span.get_tag("endpoint"), "/path/to/resource") - self.assertEqual(span.get_tag("http.method"), "POST") - self.assertEqual( - span.get_tag("resource_names"), - "POST /path/to/resource", - ) - self.assertEqual(span.get_tag("request_id"), "123") - self.assertEqual(span.get_tag("apiid"), "None") - self.assertEqual(span.get_tag("apiname"), "None") - self.assertEqual(span.get_tag("stage"), "prod") - self.assertEqual(span.start, 1428582896.0) - self.assertEqual(span.span_type, "http") - self.assertEqual(span.get_tag(InferredSpanInfo.TAG_SOURCE), "self") - self.assertEqual(span.get_tag(InferredSpanInfo.SYNCHRONICITY), "sync") - @patch("datadog_lambda.tracing.submit_errors_metric") def test_mark_trace_as_error_for_5xx_responses_getting_400_response_code( self, mock_submit_errors_metric