From e14dd830eba113c1cf04b99a8c0e55d23b1d8ccf Mon Sep 17 00:00:00 2001 From: maxday Date: Fri, 3 Sep 2021 09:02:57 -0400 Subject: [PATCH 01/14] first tests --- datadog_lambda/constants.py | 7 +++ datadog_lambda/xray.py | 47 ++++++++++++++++++ tests/test_wrapper.py | 99 +------------------------------------ tests/test_xray.py | 34 +++++++++++++ 4 files changed, 89 insertions(+), 98 deletions(-) create mode 100644 datadog_lambda/xray.py create mode 100644 tests/test_xray.py diff --git a/datadog_lambda/constants.py b/datadog_lambda/constants.py index dcfd6088..2eaa4fb5 100644 --- a/datadog_lambda/constants.py +++ b/datadog_lambda/constants.py @@ -34,3 +34,10 @@ class TraceContextSource(object): XRAY = "xray" EVENT = "event" DDTRACE = "ddtrace" + +# X-Ray deamon +class XrayDeamon(object): + HOST = "127.0.0.1" + PORT = 2000 + + diff --git a/datadog_lambda/xray.py b/datadog_lambda/xray.py new file mode 100644 index 00000000..20fabe18 --- /dev/null +++ b/datadog_lambda/xray.py @@ -0,0 +1,47 @@ +import os +import logging + +awsXrayDaemonAddressEnvVar = "AWS_XRAY_DAEMON_ADDRESS"; +logger = logging.getLogger(__name__) + +# class XRaySender(object): +# def __init__(self): +# self.host = "localhost" +# self.port = 2000 +# sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +# sock.setblocking(0) +# sock.connect(XrayDeamon.HOST, XrayDeamon.PORT) +# self.sock = sock + +def get_xray_host_port(awsXrayDaemonAddressEnvVar): + env_value = os.environ.get(awsXrayDaemonAddressEnvVar, "") + if env_value == "": + logger.debug("X-Ray daemon env var not set, not sending sub-segment") + return None + parts = env_value.split(":") + if len(parts) <= 1: + logger.debug("X-Ray daemon env var not set, not sending sub-segment") + return None + port = int(parts[1]) + host = parts[0] + return (host, port) + +def send(host_port_tuple, segment): + sock = None + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.setblocking(0) + sock.connect(host_port_tuple[0], host_port_tuple[1]) + sock.send(segment.encode("utf-8")) + except Exception as e_send: + logger.error("Error occurred submitting to xray daemon: %s", str(e_send)) + try: + sock.close() + except Exception as e_close: + logger.error("Error while closing the socket: %s", str(e_close)) + +def build_payload(payload): + if payload is None: + return None + return "{\"format\": \"json\", \"version\": 1}\n" + payload + diff --git a/tests/test_wrapper.py b/tests/test_wrapper.py index f7190276..587b9414 100644 --- a/tests/test_wrapper.py +++ b/tests/test_wrapper.py @@ -132,104 +132,7 @@ def lambda_handler(event, context): del os.environ["DD_FLUSH_TO_LOG"] - def test_datadog_lambda_wrapper_flush_in_thread(self): - # force ThreadStats to flush in thread - import datadog_lambda.metric as metric_module - - metric_module.lambda_stats.stop() - metric_module.lambda_stats = ThreadStatsWriter(True) - - @datadog_lambda_wrapper - def lambda_handler(event, context): - import time - - lambda_metric("test.metric", 100) - time.sleep(11) - # assert flushing in the thread - self.assertEqual(self.mock_threadstats_flush_distributions.call_count, 1) - lambda_metric("test.metric", 200) - - lambda_event = {} - lambda_handler(lambda_event, get_mock_context()) - - # assert another flushing in the end - self.assertEqual(self.mock_threadstats_flush_distributions.call_count, 2) - - # reset ThreadStats - metric_module.lambda_stats.stop() - metric_module.lambda_stats = ThreadStatsWriter(False) - - def test_datadog_lambda_wrapper_not_flush_in_thread(self): - # force ThreadStats to not flush in thread - import datadog_lambda.metric as metric_module - - metric_module.lambda_stats.stop() - metric_module.lambda_stats = ThreadStatsWriter(False) - - @datadog_lambda_wrapper - def lambda_handler(event, context): - import time - - lambda_metric("test.metric", 100) - time.sleep(11) - # assert no flushing in the thread - self.assertEqual(self.mock_threadstats_flush_distributions.call_count, 0) - lambda_metric("test.metric", 200) - - lambda_event = {} - lambda_handler(lambda_event, get_mock_context()) - - # assert flushing in the end - self.assertEqual(self.mock_threadstats_flush_distributions.call_count, 1) - - # reset ThreadStats - metric_module.lambda_stats.stop() - metric_module.lambda_stats = ThreadStatsWriter(False) - - def test_datadog_lambda_wrapper_inject_correlation_ids(self): - os.environ["DD_LOGS_INJECTION"] = "True" - - @datadog_lambda_wrapper - def lambda_handler(event, context): - lambda_metric("test.metric", 100) - - lambda_event = {} - lambda_handler(lambda_event, get_mock_context()) - - self.mock_set_correlation_ids.assert_called() - self.mock_inject_correlation_ids.assert_called() - - del os.environ["DD_LOGS_INJECTION"] - - def test_invocations_metric(self): - @datadog_lambda_wrapper - def lambda_handler(event, context): - lambda_metric("test.metric", 100) - - lambda_event = {} - - lambda_handler(lambda_event, get_mock_context()) - - self.mock_write_metric_point_to_stdout.assert_has_calls( - [ - call( - "aws.lambda.enhanced.invocations", - 1, - tags=[ - "region:us-west-1", - "account_id:123457598159", - "functionname:python-layer-test", - "resource:python-layer-test:1", - "cold_start:true", - "memorysize:256", - "runtime:python2.7", - "datadog_lambda:v6.6.6", - "dd_lambda_layer:datadog-python27_0.1.0", - ], - timestamp=None, - ) - ] - ) + def test_errors_metric(self): @datadog_lambda_wrapper diff --git a/tests/test_xray.py b/tests/test_xray.py new file mode 100644 index 00000000..3e9f5f17 --- /dev/null +++ b/tests/test_xray.py @@ -0,0 +1,34 @@ +import os +import unittest + +from datadog_lambda.xray import ( + get_xray_host_port, + build_payload +) + +class TestXRay(unittest.TestCase): + + def test_get_xray_host_port_empty_env_var(self): + result = get_xray_host_port("invalid_env_var") + self.assertIsNone(result) + + def test_get_xray_host_port_invalid_value_env_var(self): + os.environ["myVar"] = "invalueValue" + result = get_xray_host_port("myVar") + self.assertIsNone(result) + del os.environ["myVar"] + + def test_get_xray_host_port_success(self): + os.environ["myVar"] = "mySuperHost:1000" + result = get_xray_host_port("myVar") + self.assertEqual("mySuperHost", result[0]) + self.assertEqual(1000, result[1]) + del os.environ["myVar"] + + def test_build_payload_ok(self): + exected_text = "{\"format\": \"json\", \"version\": 1}\nmyPayload" + self.assertEqual(exected_text, build_payload("myPayload")) + + def test_build_payload_no_payload(self): + self.assertIsNone(build_payload(None)) + From 2cd0228a4c108689f9b576171fbc8866727c6b1c Mon Sep 17 00:00:00 2001 From: maxday Date: Fri, 3 Sep 2021 11:43:18 -0400 Subject: [PATCH 02/14] add tests --- datadog_lambda/tracing.py | 36 +++++++-------- datadog_lambda/xray.py | 93 +++++++++++++++++++++++++++++++-------- tests/test_tracing.py | 89 +++++++++++++++++-------------------- tests/test_xray.py | 52 ++++++++++++++++------ 4 files changed, 170 insertions(+), 100 deletions(-) diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index e14bdf6d..504c2408 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -7,14 +7,17 @@ import os import json -from aws_xray_sdk.core import xray_recorder -from aws_xray_sdk.core.lambda_launcher import LambdaContext from datadog_lambda.constants import ( SamplingPriority, TraceHeader, XraySubsegment, TraceContextSource, ) +from datadog_lambda.xray import ( + send_segment, + parse_xray_header, + XRAY_TRACE_ID_HEADER_NAME +) from ddtrace import tracer, patch from ddtrace import __version__ as ddtrace_version from ddtrace.propagation.http import HTTPPropagator @@ -27,6 +30,7 @@ propagator = HTTPPropagator() +FUNCTION_NAME_HEADER_NAME = "AWS_LAMBDA_FUNCTION_NAME" def _convert_xray_trace_id(xray_trace_id): """ @@ -57,16 +61,18 @@ def _get_xray_trace_context(): if not is_lambda_context(): return None - xray_trace_entity = xray_recorder.get_trace_entity() # xray (sub)segment + xray_trace_entity = parse_xray_header(os.environ.get(XRAY_TRACE_ID_HEADER_NAME, "")) + if xray_trace_entity is None: + return None trace_context = { - "trace-id": _convert_xray_trace_id(xray_trace_entity.trace_id), - "parent-id": _convert_xray_entity_id(xray_trace_entity.id), - "sampling-priority": _convert_xray_sampling(xray_trace_entity.sampled), + "trace-id": _convert_xray_trace_id(xray_trace_entity["trace_id"]), + "parent-id": _convert_xray_entity_id(xray_trace_entity["parent_id"]), + "sampling-priority": _convert_xray_sampling(xray_trace_entity["sampled"]), } logger.debug( "Converted trace context %s from X-Ray segment %s", trace_context, - (xray_trace_entity.trace_id, xray_trace_entity.id, xray_trace_entity.sampled), + (xray_trace_entity["trace_id"], xray_trace_entity["parent_id"], xray_trace_entity["sampled"]), ) return trace_context @@ -106,19 +112,7 @@ def create_dd_dummy_metadata_subsegment( tags into its metadata field, so the X-Ray trace can be converted to a Datadog trace in the Datadog backend with the correct context. """ - try: - xray_recorder.begin_subsegment(XraySubsegment.NAME) - subsegment = xray_recorder.current_subsegment() - subsegment.put_metadata( - subsegment_metadata_key, subsegment_metadata_value, XraySubsegment.NAMESPACE - ) - xray_recorder.end_subsegment() - except Exception as e: - logger.debug( - "failed to create dd dummy metadata subsegment with error %s", - e, - exc_info=True, - ) + send_segment(subsegment_metadata_key, subsegment_metadata_value) def extract_context_from_lambda_context(lambda_context): @@ -359,7 +353,7 @@ def is_lambda_context(): Return True if the X-Ray context is `LambdaContext`, rather than the regular `Context` (e.g., when testing lambda functions locally). """ - return type(xray_recorder.context) == LambdaContext + return os.environ.get("FUNCTION_NAME_HEADER_NAME", "") != "" def set_dd_trace_py_root(trace_context_source, merge_xray_traces): diff --git a/datadog_lambda/xray.py b/datadog_lambda/xray.py index 20fabe18..6df1ee32 100644 --- a/datadog_lambda/xray.py +++ b/datadog_lambda/xray.py @@ -1,24 +1,20 @@ import os import logging +import json +import binascii +import time -awsXrayDaemonAddressEnvVar = "AWS_XRAY_DAEMON_ADDRESS"; +from datadog_lambda.constants import XraySubsegment, TraceContextSource + +XRAY_TRACE_ID_HEADER_NAME = "_X_AMZN_TRACE_ID" +XRAY_DAEMON_ADDRESS = "AWS_XRAY_DAEMON_ADDRESS" logger = logging.getLogger(__name__) -# class XRaySender(object): -# def __init__(self): -# self.host = "localhost" -# self.port = 2000 -# sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) -# sock.setblocking(0) -# sock.connect(XrayDeamon.HOST, XrayDeamon.PORT) -# self.sock = sock - -def get_xray_host_port(awsXrayDaemonAddressEnvVar): - env_value = os.environ.get(awsXrayDaemonAddressEnvVar, "") - if env_value == "": +def get_xray_host_port(adress): + if adress == "": logger.debug("X-Ray daemon env var not set, not sending sub-segment") return None - parts = env_value.split(":") + parts = adress.split(":") if len(parts) <= 1: logger.debug("X-Ray daemon env var not set, not sending sub-segment") return None @@ -26,13 +22,13 @@ def get_xray_host_port(awsXrayDaemonAddressEnvVar): host = parts[0] return (host, port) -def send(host_port_tuple, segment): +def send(host_port_tuple, payload): sock = None try: sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setblocking(0) sock.connect(host_port_tuple[0], host_port_tuple[1]) - sock.send(segment.encode("utf-8")) + sock.send(payload.encode("utf-8")) except Exception as e_send: logger.error("Error occurred submitting to xray daemon: %s", str(e_send)) try: @@ -40,8 +36,69 @@ def send(host_port_tuple, segment): except Exception as e_close: logger.error("Error while closing the socket: %s", str(e_close)) -def build_payload(payload): +def build_segment_payload(payload): if payload is None: return None - return "{\"format\": \"json\", \"version\": 1}\n" + payload + header = json.dumps({ + "format": "json", + "version": 1 + }) + return header + "\n" + payload + +def parse_xray_header(raw_trace_id): + # Example: Root=1-5e272390-8c398be037738dc042009320;Parent=94ae789b969f1cc5;Sampled=1 + logger.debug("Reading trace context from env var %s", raw_trace_id); + if len(raw_trace_id) == 0: + return None + parts = raw_trace_id.split(";") + if len(parts) != 3: + return None + root = parts[0].replace("Root=", "") + parent = parts[1].replace("Parent=", "") + sampled = parts[2].replace("Sampled=", "") + if ( + len(root) == len(parts[0]) + or len(parent) == len(parts[1]) + or len(sampled) == len(parts[2]) + ): + return None + return { + "parent_id": parent, + "trace_id": root, + "sampled": sampled, + "source": TraceContextSource.XRAY + } + +def generate_random_id(): + return binascii.b2a_hex(os.urandom(8)).decode('utf-8') + +def build_segment(context, key, metadata): + + segment = json.dumps({ + "id": generate_random_id(), + "trace_id": context["trace_id"], + "parent_id": context["parent_id"], + "name": XraySubsegment.NAME, + "start_time": time.time(), + "end_time": time.time(), + "type": "subsegment", + "metadata": { + XraySubsegment.NAMESPACE: { + key: metadata, + } + } + }) + return segment + +def send_segment(key, metadata): + host_port_tuple = get_xray_host_port(os.environ.get(XRAY_DAEMON_ADDRESS, "")) + if host_port_tuple is None: + return None + context = parse_xray_header(os.environ.get(XRAY_TRACE_ID_HEADER_NAME,"")) + if context is None: + logger.debug("Failed to create the segment since it was not possible to get the trace context for the header") + return None + segment = build_segment(context, key, metadata) + segment_payload = build_segment_payload(segment) + send(host_port_tuple, seegment_payload) diff --git a/tests/test_tracing.py b/tests/test_tracing.py index 2a7e1581..a27438f0 100644 --- a/tests/test_tracing.py +++ b/tests/test_tracing.py @@ -1,5 +1,6 @@ import unittest import json +import os try: from unittest.mock import MagicMock, patch, call @@ -22,6 +23,12 @@ function_arn = "arn:aws:lambda:us-west-1:123457598159:function:python-layer-test" +fake_xray_header_value = ( + "Root=1-5e272390-8c398be037738dc042009320;Parent=94ae789b969f1cc5;Sampled=1" +) +fake_xray_header_value_parent_decimal = "10713633173203262661" +fake_xray_header_value_root_decimal = "3995693151288333088" + class ClientContext(object): def __init__(self, custom=None): @@ -50,17 +57,11 @@ class TestExtractAndGetDDTraceContext(unittest.TestCase): def setUp(self): global dd_tracing_enabled dd_tracing_enabled = False - patcher = patch("datadog_lambda.tracing.xray_recorder") - self.mock_xray_recorder = patcher.start() - self.mock_xray_recorder.get_trace_entity.return_value = MagicMock( - id="ffff", trace_id="1111", sampled=True - ) - self.mock_current_subsegment = MagicMock() - self.mock_xray_recorder.current_subsegment.return_value = ( - self.mock_current_subsegment - ) + os.environ["_X_AMZN_TRACE_ID"] = fake_xray_header_value + os.environ["XRAY_DAEMON_ADDRESS"] = "1.1.1.1:8888" + patcher = patch("datadog_lambda.tracing.send_segment") + self.mock_send_segment = patcher.start() self.addCleanup(patcher.stop) - patcher = patch("datadog_lambda.tracing.is_lambda_context") self.mock_is_lambda_context = patcher.start() self.mock_is_lambda_context.return_value = True @@ -69,6 +70,8 @@ def setUp(self): def tearDown(self): global dd_tracing_enabled dd_tracing_enabled = False + del os.environ["_X_AMZN_TRACE_ID"] + del os.environ["XRAY_DAEMON_ADDRESS"] def test_without_datadog_trace_headers(self): lambda_ctx = get_mock_context() @@ -76,13 +79,13 @@ def test_without_datadog_trace_headers(self): self.assertEqual(source, "xray") self.assertDictEqual( ctx, - {"trace-id": "4369", "parent-id": "65535", "sampling-priority": "2"}, + {"trace-id": fake_xray_header_value_root_decimal, "parent-id": fake_xray_header_value_parent_decimal, "sampling-priority": "2"}, ) self.assertDictEqual( get_dd_trace_context(), { - TraceHeader.TRACE_ID: "4369", - TraceHeader.PARENT_ID: "65535", + TraceHeader.TRACE_ID: fake_xray_header_value_root_decimal, + TraceHeader.PARENT_ID: fake_xray_header_value_parent_decimal, TraceHeader.SAMPLING_PRIORITY: "2", }, {}, @@ -97,13 +100,13 @@ def test_with_incomplete_datadog_trace_headers(self): self.assertEqual(source, "xray") self.assertDictEqual( ctx, - {"trace-id": "4369", "parent-id": "65535", "sampling-priority": "2"}, + {"trace-id": fake_xray_header_value_root_decimal, "parent-id": fake_xray_header_value_parent_decimal, "sampling-priority": "2"}, ) self.assertDictEqual( get_dd_trace_context(), { - TraceHeader.TRACE_ID: "4369", - TraceHeader.PARENT_ID: "65535", + TraceHeader.TRACE_ID: fake_xray_header_value_root_decimal, + TraceHeader.PARENT_ID: fake_xray_header_value_parent_decimal, TraceHeader.SAMPLING_PRIORITY: "2", }, ) @@ -129,16 +132,15 @@ def test_with_complete_datadog_trace_headers(self): get_dd_trace_context(), { TraceHeader.TRACE_ID: "123", - TraceHeader.PARENT_ID: "65535", + TraceHeader.PARENT_ID: fake_xray_header_value_parent_decimal, TraceHeader.SAMPLING_PRIORITY: "1", }, ) create_dd_dummy_metadata_subsegment(ctx, XraySubsegment.TRACE_KEY) - self.mock_xray_recorder.begin_subsegment.assert_called() - self.mock_current_subsegment.put_metadata.assert_called_with( + self.mock_send_segment.assert_called() + self.mock_send_segment.assert_called_with( XraySubsegment.TRACE_KEY, {"trace-id": "123", "parent-id": "321", "sampling-priority": "1"}, - XraySubsegment.NAMESPACE, ) def test_with_extractor_function(self): @@ -176,7 +178,7 @@ def extractor_foo(event, context): get_dd_trace_context(), { TraceHeader.TRACE_ID: "123", - TraceHeader.PARENT_ID: "65535", + TraceHeader.PARENT_ID: fake_xray_header_value_parent_decimal, TraceHeader.SAMPLING_PRIORITY: "1", }, ) @@ -201,16 +203,16 @@ def extractor_raiser(event, context): self.assertDictEqual( ctx, { - "trace-id": "4369", - "parent-id": "65535", + "trace-id": fake_xray_header_value_root_decimal, + "parent-id": fake_xray_header_value_parent_decimal, "sampling-priority": "2", }, ) self.assertDictEqual( get_dd_trace_context(), { - TraceHeader.TRACE_ID: "4369", - TraceHeader.PARENT_ID: "65535", + TraceHeader.TRACE_ID: fake_xray_header_value_root_decimal, + TraceHeader.PARENT_ID: fake_xray_header_value_parent_decimal, TraceHeader.SAMPLING_PRIORITY: "2", }, ) @@ -261,17 +263,14 @@ def test_with_sqs_distributed_datadog_trace_data(self): get_dd_trace_context(), { TraceHeader.TRACE_ID: "123", - TraceHeader.PARENT_ID: "65535", + TraceHeader.PARENT_ID: fake_xray_header_value_parent_decimal, TraceHeader.SAMPLING_PRIORITY: "1", }, ) create_dd_dummy_metadata_subsegment(ctx, XraySubsegment.TRACE_KEY) - self.mock_xray_recorder.begin_subsegment.assert_called() - self.mock_xray_recorder.end_subsegment.assert_called() - self.mock_current_subsegment.put_metadata.assert_called_with( + self.mock_send_segment.assert_called_with( XraySubsegment.TRACE_KEY, {"trace-id": "123", "parent-id": "321", "sampling-priority": "1"}, - XraySubsegment.NAMESPACE, ) def test_with_legacy_client_context_datadog_trace_data(self): @@ -298,17 +297,15 @@ def test_with_legacy_client_context_datadog_trace_data(self): get_dd_trace_context(), { TraceHeader.TRACE_ID: "666", - TraceHeader.PARENT_ID: "65535", + TraceHeader.PARENT_ID: fake_xray_header_value_parent_decimal, TraceHeader.SAMPLING_PRIORITY: "1", }, ) create_dd_dummy_metadata_subsegment(ctx, XraySubsegment.TRACE_KEY) - self.mock_xray_recorder.begin_subsegment.assert_called() - self.mock_xray_recorder.end_subsegment.assert_called() - self.mock_current_subsegment.put_metadata.assert_called_with( + self.mock_send_segment.assert_called() + self.mock_send_segment.assert_called_with( XraySubsegment.TRACE_KEY, - {"trace-id": "666", "parent-id": "777", "sampling-priority": "1"}, - XraySubsegment.NAMESPACE, + {"trace-id": "666", "parent-id": "777", "sampling-priority": "1"} ) def test_with_new_client_context_datadog_trace_data(self): @@ -333,17 +330,15 @@ def test_with_new_client_context_datadog_trace_data(self): get_dd_trace_context(), { TraceHeader.TRACE_ID: "666", - TraceHeader.PARENT_ID: "65535", + TraceHeader.PARENT_ID: fake_xray_header_value_parent_decimal, TraceHeader.SAMPLING_PRIORITY: "1", }, ) create_dd_dummy_metadata_subsegment(ctx, XraySubsegment.TRACE_KEY) - self.mock_xray_recorder.begin_subsegment.assert_called() - self.mock_xray_recorder.end_subsegment.assert_called() - self.mock_current_subsegment.put_metadata.assert_called_with( + self.mock_send_segment.assert_called() + self.mock_send_segment.assert_called_with( XraySubsegment.TRACE_KEY, - {"trace-id": "666", "parent-id": "777", "sampling-priority": "1"}, - XraySubsegment.NAMESPACE, + {"trace-id": "666", "parent-id": "777", "sampling-priority": "1"} ) def test_with_complete_datadog_trace_headers_with_mixed_casing(self): @@ -362,7 +357,7 @@ def test_with_complete_datadog_trace_headers_with_mixed_casing(self): get_dd_trace_context(), { TraceHeader.TRACE_ID: "123", - TraceHeader.PARENT_ID: "65535", + TraceHeader.PARENT_ID: fake_xray_header_value_parent_decimal, TraceHeader.SAMPLING_PRIORITY: "1", }, ) @@ -375,17 +370,15 @@ def test_with_complete_datadog_trace_headers_with_trigger_tags(self): create_dd_dummy_metadata_subsegment( trigger_tags, XraySubsegment.LAMBDA_FUNCTION_TAGS_KEY ) - self.mock_xray_recorder.begin_subsegment.assert_called() - self.mock_xray_recorder.end_subsegment.assert_called() - self.mock_current_subsegment.put_metadata.assert_has_calls( + self.mock_send_segment.assert_called() + self.mock_send_segment.assert_has_calls( [ call( XraySubsegment.LAMBDA_FUNCTION_TAGS_KEY, { "function_trigger.event_source": "sqs", "function_trigger.event_source_arn": "arn:aws:sqs:us-east-1:123456789012:MyQueue", - }, - XraySubsegment.NAMESPACE, + } ), ] ) diff --git a/tests/test_xray.py b/tests/test_xray.py index 3e9f5f17..f2cf6082 100644 --- a/tests/test_xray.py +++ b/tests/test_xray.py @@ -1,34 +1,60 @@ import os import unittest +import json + +from unittest import mock from datadog_lambda.xray import ( get_xray_host_port, - build_payload + build_segment_payload, + build_segment ) class TestXRay(unittest.TestCase): - def test_get_xray_host_port_empty_env_var(self): - result = get_xray_host_port("invalid_env_var") + def test_get_xray_host_port_empty_(self): + result = get_xray_host_port("") self.assertIsNone(result) - def test_get_xray_host_port_invalid_value_env_var(self): - os.environ["myVar"] = "invalueValue" + def test_get_xray_host_port_invalid_value(self): result = get_xray_host_port("myVar") self.assertIsNone(result) - del os.environ["myVar"] def test_get_xray_host_port_success(self): - os.environ["myVar"] = "mySuperHost:1000" - result = get_xray_host_port("myVar") + result = get_xray_host_port("mySuperHost:1000") self.assertEqual("mySuperHost", result[0]) self.assertEqual(1000, result[1]) - del os.environ["myVar"] - def test_build_payload_ok(self): + def test_build_segment_payload_ok(self): exected_text = "{\"format\": \"json\", \"version\": 1}\nmyPayload" - self.assertEqual(exected_text, build_payload("myPayload")) + self.assertEqual(exected_text, build_segment_payload("myPayload")) + + def test_build_segment_payload_no_payload(self): + self.assertIsNone(build_segment_payload(None)) + + @mock.patch('time.time', mock.MagicMock(return_value=1111)) + @mock.patch('datadog_lambda.xray.generate_random_id', mock.MagicMock(return_value="1234abcd")) + def test_build_segment(self): + context = { + "trace_id": 111000111, + "parent_id": 222000222, + } + + value = json.dumps({ + "a": "aaa", + "b": "bbb" + }) + result = build_segment(context, "myKey", "myValue") + jsonResult = json.loads(result) + metadataJson = jsonResult["metadata"] + + self.assertEqual("1234abcd",jsonResult["id"]) + self.assertEqual(1111,jsonResult["start_time"]) + self.assertEqual(1111,jsonResult["end_time"]) + self.assertEqual(111000111,jsonResult["trace_id"]) + self.assertEqual(222000222,jsonResult["parent_id"]) + self.assertEqual("datadog-metadata",jsonResult["name"]) + self.assertEqual("subsegment",jsonResult["type"]) + self.assertEqual("myValue",metadataJson["datadog"]["myKey"]) - def test_build_payload_no_payload(self): - self.assertIsNone(build_payload(None)) From 83d7914672456e8b6f90bfbc299a2464df0ab310 Mon Sep 17 00:00:00 2001 From: maxday Date: Fri, 3 Sep 2021 11:45:28 -0400 Subject: [PATCH 03/14] flake and lint --- datadog_lambda/constants.py | 3 +- datadog_lambda/tracing.py | 10 +++++-- datadog_lambda/xray.py | 58 +++++++++++++++++++++---------------- tests/test_tracing.py | 18 ++++++++---- tests/test_wrapper.py | 2 -- tests/test_xray.py | 40 +++++++++++-------------- 6 files changed, 71 insertions(+), 60 deletions(-) diff --git a/datadog_lambda/constants.py b/datadog_lambda/constants.py index 2eaa4fb5..f152ab71 100644 --- a/datadog_lambda/constants.py +++ b/datadog_lambda/constants.py @@ -35,9 +35,8 @@ class TraceContextSource(object): EVENT = "event" DDTRACE = "ddtrace" + # X-Ray deamon class XrayDeamon(object): HOST = "127.0.0.1" PORT = 2000 - - diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index 504c2408..a84e698c 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -10,13 +10,12 @@ from datadog_lambda.constants import ( SamplingPriority, TraceHeader, - XraySubsegment, TraceContextSource, ) from datadog_lambda.xray import ( send_segment, parse_xray_header, - XRAY_TRACE_ID_HEADER_NAME + XRAY_TRACE_ID_HEADER_NAME, ) from ddtrace import tracer, patch from ddtrace import __version__ as ddtrace_version @@ -32,6 +31,7 @@ FUNCTION_NAME_HEADER_NAME = "AWS_LAMBDA_FUNCTION_NAME" + def _convert_xray_trace_id(xray_trace_id): """ Convert X-Ray trace id (hex)'s last 63 bits to a Datadog trace id (int). @@ -72,7 +72,11 @@ def _get_xray_trace_context(): logger.debug( "Converted trace context %s from X-Ray segment %s", trace_context, - (xray_trace_entity["trace_id"], xray_trace_entity["parent_id"], xray_trace_entity["sampled"]), + ( + xray_trace_entity["trace_id"], + xray_trace_entity["parent_id"], + xray_trace_entity["sampled"], + ), ) return trace_context diff --git a/datadog_lambda/xray.py b/datadog_lambda/xray.py index 6df1ee32..bb9d9636 100644 --- a/datadog_lambda/xray.py +++ b/datadog_lambda/xray.py @@ -1,8 +1,9 @@ import os import logging -import json +import json import binascii import time +import socket from datadog_lambda.constants import XraySubsegment, TraceContextSource @@ -10,6 +11,7 @@ XRAY_DAEMON_ADDRESS = "AWS_XRAY_DAEMON_ADDRESS" logger = logging.getLogger(__name__) + def get_xray_host_port(adress): if adress == "": logger.debug("X-Ray daemon env var not set, not sending sub-segment") @@ -22,6 +24,7 @@ def get_xray_host_port(adress): host = parts[0] return (host, port) + def send(host_port_tuple, payload): sock = None try: @@ -36,18 +39,17 @@ def send(host_port_tuple, payload): except Exception as e_close: logger.error("Error while closing the socket: %s", str(e_close)) + def build_segment_payload(payload): if payload is None: return None - header = json.dumps({ - "format": "json", - "version": 1 - }) + header = json.dumps({"format": "json", "version": 1}) return header + "\n" + payload + def parse_xray_header(raw_trace_id): # Example: Root=1-5e272390-8c398be037738dc042009320;Parent=94ae789b969f1cc5;Sampled=1 - logger.debug("Reading trace context from env var %s", raw_trace_id); + logger.debug("Reading trace context from env var %s", raw_trace_id) if len(raw_trace_id) == 0: return None parts = raw_trace_id.split(";") @@ -66,39 +68,45 @@ def parse_xray_header(raw_trace_id): "parent_id": parent, "trace_id": root, "sampled": sampled, - "source": TraceContextSource.XRAY + "source": TraceContextSource.XRAY, } + def generate_random_id(): - return binascii.b2a_hex(os.urandom(8)).decode('utf-8') + return binascii.b2a_hex(os.urandom(8)).decode("utf-8") + def build_segment(context, key, metadata): - segment = json.dumps({ - "id": generate_random_id(), - "trace_id": context["trace_id"], - "parent_id": context["parent_id"], - "name": XraySubsegment.NAME, - "start_time": time.time(), - "end_time": time.time(), - "type": "subsegment", - "metadata": { - XraySubsegment.NAMESPACE: { - key: metadata, - } + segment = json.dumps( + { + "id": generate_random_id(), + "trace_id": context["trace_id"], + "parent_id": context["parent_id"], + "name": XraySubsegment.NAME, + "start_time": time.time(), + "end_time": time.time(), + "type": "subsegment", + "metadata": { + XraySubsegment.NAMESPACE: { + key: metadata, + } + }, } - }) + ) return segment + def send_segment(key, metadata): host_port_tuple = get_xray_host_port(os.environ.get(XRAY_DAEMON_ADDRESS, "")) if host_port_tuple is None: return None - context = parse_xray_header(os.environ.get(XRAY_TRACE_ID_HEADER_NAME,"")) + context = parse_xray_header(os.environ.get(XRAY_TRACE_ID_HEADER_NAME, "")) if context is None: - logger.debug("Failed to create the segment since it was not possible to get the trace context for the header") + logger.debug( + "Failed to create segment since it was not possible to get trace context from header" + ) return None segment = build_segment(context, key, metadata) segment_payload = build_segment_payload(segment) - send(host_port_tuple, seegment_payload) - + send(host_port_tuple, segment_payload) diff --git a/tests/test_tracing.py b/tests/test_tracing.py index a27438f0..632281d4 100644 --- a/tests/test_tracing.py +++ b/tests/test_tracing.py @@ -79,7 +79,11 @@ def test_without_datadog_trace_headers(self): self.assertEqual(source, "xray") self.assertDictEqual( ctx, - {"trace-id": fake_xray_header_value_root_decimal, "parent-id": fake_xray_header_value_parent_decimal, "sampling-priority": "2"}, + { + "trace-id": fake_xray_header_value_root_decimal, + "parent-id": fake_xray_header_value_parent_decimal, + "sampling-priority": "2", + }, ) self.assertDictEqual( get_dd_trace_context(), @@ -100,7 +104,11 @@ def test_with_incomplete_datadog_trace_headers(self): self.assertEqual(source, "xray") self.assertDictEqual( ctx, - {"trace-id": fake_xray_header_value_root_decimal, "parent-id": fake_xray_header_value_parent_decimal, "sampling-priority": "2"}, + { + "trace-id": fake_xray_header_value_root_decimal, + "parent-id": fake_xray_header_value_parent_decimal, + "sampling-priority": "2", + }, ) self.assertDictEqual( get_dd_trace_context(), @@ -305,7 +313,7 @@ def test_with_legacy_client_context_datadog_trace_data(self): self.mock_send_segment.assert_called() self.mock_send_segment.assert_called_with( XraySubsegment.TRACE_KEY, - {"trace-id": "666", "parent-id": "777", "sampling-priority": "1"} + {"trace-id": "666", "parent-id": "777", "sampling-priority": "1"}, ) def test_with_new_client_context_datadog_trace_data(self): @@ -338,7 +346,7 @@ def test_with_new_client_context_datadog_trace_data(self): self.mock_send_segment.assert_called() self.mock_send_segment.assert_called_with( XraySubsegment.TRACE_KEY, - {"trace-id": "666", "parent-id": "777", "sampling-priority": "1"} + {"trace-id": "666", "parent-id": "777", "sampling-priority": "1"}, ) def test_with_complete_datadog_trace_headers_with_mixed_casing(self): @@ -378,7 +386,7 @@ def test_with_complete_datadog_trace_headers_with_trigger_tags(self): { "function_trigger.event_source": "sqs", "function_trigger.event_source_arn": "arn:aws:sqs:us-east-1:123456789012:MyQueue", - } + }, ), ] ) diff --git a/tests/test_wrapper.py b/tests/test_wrapper.py index 587b9414..2250803c 100644 --- a/tests/test_wrapper.py +++ b/tests/test_wrapper.py @@ -132,8 +132,6 @@ def lambda_handler(event, context): del os.environ["DD_FLUSH_TO_LOG"] - - def test_errors_metric(self): @datadog_lambda_wrapper def lambda_handler(event, context): diff --git a/tests/test_xray.py b/tests/test_xray.py index f2cf6082..348b8501 100644 --- a/tests/test_xray.py +++ b/tests/test_xray.py @@ -4,14 +4,10 @@ from unittest import mock -from datadog_lambda.xray import ( - get_xray_host_port, - build_segment_payload, - build_segment -) +from datadog_lambda.xray import get_xray_host_port, build_segment_payload, build_segment + class TestXRay(unittest.TestCase): - def test_get_xray_host_port_empty_(self): result = get_xray_host_port("") self.assertIsNone(result) @@ -26,35 +22,33 @@ def test_get_xray_host_port_success(self): self.assertEqual(1000, result[1]) def test_build_segment_payload_ok(self): - exected_text = "{\"format\": \"json\", \"version\": 1}\nmyPayload" + exected_text = '{"format": "json", "version": 1}\nmyPayload' self.assertEqual(exected_text, build_segment_payload("myPayload")) def test_build_segment_payload_no_payload(self): self.assertIsNone(build_segment_payload(None)) - @mock.patch('time.time', mock.MagicMock(return_value=1111)) - @mock.patch('datadog_lambda.xray.generate_random_id', mock.MagicMock(return_value="1234abcd")) + @mock.patch("time.time", mock.MagicMock(return_value=1111)) + @mock.patch( + "datadog_lambda.xray.generate_random_id", + mock.MagicMock(return_value="1234abcd"), + ) def test_build_segment(self): context = { "trace_id": 111000111, "parent_id": 222000222, } - value = json.dumps({ - "a": "aaa", - "b": "bbb" - }) + value = json.dumps({"a": "aaa", "b": "bbb"}) result = build_segment(context, "myKey", "myValue") jsonResult = json.loads(result) metadataJson = jsonResult["metadata"] - self.assertEqual("1234abcd",jsonResult["id"]) - self.assertEqual(1111,jsonResult["start_time"]) - self.assertEqual(1111,jsonResult["end_time"]) - self.assertEqual(111000111,jsonResult["trace_id"]) - self.assertEqual(222000222,jsonResult["parent_id"]) - self.assertEqual("datadog-metadata",jsonResult["name"]) - self.assertEqual("subsegment",jsonResult["type"]) - self.assertEqual("myValue",metadataJson["datadog"]["myKey"]) - - + self.assertEqual("1234abcd", jsonResult["id"]) + self.assertEqual(1111, jsonResult["start_time"]) + self.assertEqual(1111, jsonResult["end_time"]) + self.assertEqual(111000111, jsonResult["trace_id"]) + self.assertEqual(222000222, jsonResult["parent_id"]) + self.assertEqual("datadog-metadata", jsonResult["name"]) + self.assertEqual("subsegment", jsonResult["type"]) + self.assertEqual("myValue", metadataJson["datadog"]["myKey"]) From b3b8a356df515626e7017d70c5150f6ad4ef4957 Mon Sep 17 00:00:00 2001 From: maxday Date: Fri, 3 Sep 2021 11:53:42 -0400 Subject: [PATCH 04/14] lint --- datadog_lambda/constants.py | 6 +++--- datadog_lambda/tracing.py | 6 ++++-- datadog_lambda/xray.py | 12 +++++++----- tests/test_tracing.py | 2 -- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/datadog_lambda/constants.py b/datadog_lambda/constants.py index f152ab71..08536534 100644 --- a/datadog_lambda/constants.py +++ b/datadog_lambda/constants.py @@ -37,6 +37,6 @@ class TraceContextSource(object): # X-Ray deamon -class XrayDeamon(object): - HOST = "127.0.0.1" - PORT = 2000 +class XrayDaemon(object): + XRAY_TRACE_ID_HEADER_NAME = "_X_AMZN_TRACE_ID" + XRAY_DAEMON_ADDRESS = "AWS_XRAY_DAEMON_ADDRESS" diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index a84e698c..e343634c 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -11,11 +11,11 @@ SamplingPriority, TraceHeader, TraceContextSource, + XrayDaemon, ) from datadog_lambda.xray import ( send_segment, parse_xray_header, - XRAY_TRACE_ID_HEADER_NAME, ) from ddtrace import tracer, patch from ddtrace import __version__ as ddtrace_version @@ -61,7 +61,9 @@ def _get_xray_trace_context(): if not is_lambda_context(): return None - xray_trace_entity = parse_xray_header(os.environ.get(XRAY_TRACE_ID_HEADER_NAME, "")) + xray_trace_entity = parse_xray_header( + os.environ.get(XrayDaemon.XRAY_TRACE_ID_HEADER_NAME, "") + ) if xray_trace_entity is None: return None trace_context = { diff --git a/datadog_lambda/xray.py b/datadog_lambda/xray.py index bb9d9636..571baff0 100644 --- a/datadog_lambda/xray.py +++ b/datadog_lambda/xray.py @@ -5,10 +5,8 @@ import time import socket -from datadog_lambda.constants import XraySubsegment, TraceContextSource +from datadog_lambda.constants import XrayDaemon, XraySubsegment, TraceContextSource -XRAY_TRACE_ID_HEADER_NAME = "_X_AMZN_TRACE_ID" -XRAY_DAEMON_ADDRESS = "AWS_XRAY_DAEMON_ADDRESS" logger = logging.getLogger(__name__) @@ -98,10 +96,14 @@ def build_segment(context, key, metadata): def send_segment(key, metadata): - host_port_tuple = get_xray_host_port(os.environ.get(XRAY_DAEMON_ADDRESS, "")) + host_port_tuple = get_xray_host_port( + os.environ.get(XrayDaemon.XRAY_DAEMON_ADDRESS, "") + ) if host_port_tuple is None: return None - context = parse_xray_header(os.environ.get(XRAY_TRACE_ID_HEADER_NAME, "")) + context = parse_xray_header( + os.environ.get(XrayDaemon.XRAY_TRACE_ID_HEADER_NAME, "") + ) if context is None: logger.debug( "Failed to create segment since it was not possible to get trace context from header" diff --git a/tests/test_tracing.py b/tests/test_tracing.py index 632281d4..82e11f3f 100644 --- a/tests/test_tracing.py +++ b/tests/test_tracing.py @@ -58,7 +58,6 @@ def setUp(self): global dd_tracing_enabled dd_tracing_enabled = False os.environ["_X_AMZN_TRACE_ID"] = fake_xray_header_value - os.environ["XRAY_DAEMON_ADDRESS"] = "1.1.1.1:8888" patcher = patch("datadog_lambda.tracing.send_segment") self.mock_send_segment = patcher.start() self.addCleanup(patcher.stop) @@ -71,7 +70,6 @@ def tearDown(self): global dd_tracing_enabled dd_tracing_enabled = False del os.environ["_X_AMZN_TRACE_ID"] - del os.environ["XRAY_DAEMON_ADDRESS"] def test_without_datadog_trace_headers(self): lambda_ctx = get_mock_context() From ed5f65d2c525acb9896e4fcde4ad2f8e07c10677 Mon Sep 17 00:00:00 2001 From: maxday Date: Fri, 3 Sep 2021 11:58:01 -0400 Subject: [PATCH 05/14] clean --- datadog_lambda/constants.py | 1 + datadog_lambda/tracing.py | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/datadog_lambda/constants.py b/datadog_lambda/constants.py index 08536534..d2c85378 100644 --- a/datadog_lambda/constants.py +++ b/datadog_lambda/constants.py @@ -40,3 +40,4 @@ class TraceContextSource(object): class XrayDaemon(object): XRAY_TRACE_ID_HEADER_NAME = "_X_AMZN_TRACE_ID" XRAY_DAEMON_ADDRESS = "AWS_XRAY_DAEMON_ADDRESS" + FUNCTION_NAME_HEADER_NAME = "AWS_LAMBDA_FUNCTION_NAME" diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index e343634c..9870f756 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -29,8 +29,6 @@ propagator = HTTPPropagator() -FUNCTION_NAME_HEADER_NAME = "AWS_LAMBDA_FUNCTION_NAME" - def _convert_xray_trace_id(xray_trace_id): """ @@ -359,7 +357,7 @@ def is_lambda_context(): Return True if the X-Ray context is `LambdaContext`, rather than the regular `Context` (e.g., when testing lambda functions locally). """ - return os.environ.get("FUNCTION_NAME_HEADER_NAME", "") != "" + return os.environ.get(XrayDaemon.FUNCTION_NAME_HEADER_NAME, "") != "" def set_dd_trace_py_root(trace_context_source, merge_xray_traces): From 999a7353f9137e447f936c828262e672fb991be7 Mon Sep 17 00:00:00 2001 From: maxday Date: Fri, 3 Sep 2021 11:58:46 -0400 Subject: [PATCH 06/14] tests --- tests/test_wrapper.py | 99 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/tests/test_wrapper.py b/tests/test_wrapper.py index 2250803c..f7190276 100644 --- a/tests/test_wrapper.py +++ b/tests/test_wrapper.py @@ -132,6 +132,105 @@ def lambda_handler(event, context): del os.environ["DD_FLUSH_TO_LOG"] + def test_datadog_lambda_wrapper_flush_in_thread(self): + # force ThreadStats to flush in thread + import datadog_lambda.metric as metric_module + + metric_module.lambda_stats.stop() + metric_module.lambda_stats = ThreadStatsWriter(True) + + @datadog_lambda_wrapper + def lambda_handler(event, context): + import time + + lambda_metric("test.metric", 100) + time.sleep(11) + # assert flushing in the thread + self.assertEqual(self.mock_threadstats_flush_distributions.call_count, 1) + lambda_metric("test.metric", 200) + + lambda_event = {} + lambda_handler(lambda_event, get_mock_context()) + + # assert another flushing in the end + self.assertEqual(self.mock_threadstats_flush_distributions.call_count, 2) + + # reset ThreadStats + metric_module.lambda_stats.stop() + metric_module.lambda_stats = ThreadStatsWriter(False) + + def test_datadog_lambda_wrapper_not_flush_in_thread(self): + # force ThreadStats to not flush in thread + import datadog_lambda.metric as metric_module + + metric_module.lambda_stats.stop() + metric_module.lambda_stats = ThreadStatsWriter(False) + + @datadog_lambda_wrapper + def lambda_handler(event, context): + import time + + lambda_metric("test.metric", 100) + time.sleep(11) + # assert no flushing in the thread + self.assertEqual(self.mock_threadstats_flush_distributions.call_count, 0) + lambda_metric("test.metric", 200) + + lambda_event = {} + lambda_handler(lambda_event, get_mock_context()) + + # assert flushing in the end + self.assertEqual(self.mock_threadstats_flush_distributions.call_count, 1) + + # reset ThreadStats + metric_module.lambda_stats.stop() + metric_module.lambda_stats = ThreadStatsWriter(False) + + def test_datadog_lambda_wrapper_inject_correlation_ids(self): + os.environ["DD_LOGS_INJECTION"] = "True" + + @datadog_lambda_wrapper + def lambda_handler(event, context): + lambda_metric("test.metric", 100) + + lambda_event = {} + lambda_handler(lambda_event, get_mock_context()) + + self.mock_set_correlation_ids.assert_called() + self.mock_inject_correlation_ids.assert_called() + + del os.environ["DD_LOGS_INJECTION"] + + def test_invocations_metric(self): + @datadog_lambda_wrapper + def lambda_handler(event, context): + lambda_metric("test.metric", 100) + + lambda_event = {} + + lambda_handler(lambda_event, get_mock_context()) + + self.mock_write_metric_point_to_stdout.assert_has_calls( + [ + call( + "aws.lambda.enhanced.invocations", + 1, + tags=[ + "region:us-west-1", + "account_id:123457598159", + "functionname:python-layer-test", + "resource:python-layer-test:1", + "cold_start:true", + "memorysize:256", + "runtime:python2.7", + "datadog_lambda:v6.6.6", + "dd_lambda_layer:datadog-python27_0.1.0", + ], + timestamp=None, + ) + ] + ) + def test_errors_metric(self): @datadog_lambda_wrapper def lambda_handler(event, context): From 8072ed4346734e68ff216a8b11d45f253e497304 Mon Sep 17 00:00:00 2001 From: maxday Date: Fri, 3 Sep 2021 11:59:45 -0400 Subject: [PATCH 07/14] clean license + setup --- LICENSE-3rdparty.csv | 2 -- setup.py | 1 - 2 files changed, 3 deletions(-) diff --git a/LICENSE-3rdparty.csv b/LICENSE-3rdparty.csv index e34808e4..e15ac6e5 100644 --- a/LICENSE-3rdparty.csv +++ b/LICENSE-3rdparty.csv @@ -1,6 +1,4 @@ Component,Origin,License,Copyright -aws-xray-sdk-python,github.com/aws/aws-xray-sdk-python,Apache-2.0, flake8,gitlab.com/pycqa/flake8,MIT,"Copyright (C) 2011-2013 Tarek Ziade . Copyright (C) 2012-2016 Ian Cordasco ." nose2,github.com/nose-devs/nose2,BSD-2-Clause,"Copyright (c) 2012, Jason Pellerin. All rights reserved." -requests,github.com/kennethreitz/requests,Apache-2.0,"Copyright 2018 Kenneth Reitz" wrapt,github.com/GrahamDumpleton/wrapt,BSD-2-Clause,"Copyright (c) 2013-2019, Graham Dumpleton" \ No newline at end of file diff --git a/setup.py b/setup.py index c8332351..31e4f394 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,6 @@ packages=["datadog_lambda"], python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4", install_requires=[ - "aws-xray-sdk==2.8.0", "datadog==0.41.0", "ddtrace==0.48.0", "wrapt==1.11.2", From 117209f302bcd815cec2b2415903e9360c5ccad0 Mon Sep 17 00:00:00 2001 From: maxday Date: Fri, 3 Sep 2021 12:02:19 -0400 Subject: [PATCH 08/14] fix 2.7 --- tests/test_xray.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/test_xray.py b/tests/test_xray.py index 348b8501..922c1f4b 100644 --- a/tests/test_xray.py +++ b/tests/test_xray.py @@ -2,7 +2,10 @@ import unittest import json -from unittest import mock +try: + from unittest.mock import patch +except ImportError: + from mock import patch from datadog_lambda.xray import get_xray_host_port, build_segment_payload, build_segment From ab29cee43188630021c23dd85c9ee34daed03b02 Mon Sep 17 00:00:00 2001 From: maxday Date: Fri, 3 Sep 2021 12:04:02 -0400 Subject: [PATCH 09/14] fix 2.7 --- tests/test_xray.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_xray.py b/tests/test_xray.py index 922c1f4b..964e09bd 100644 --- a/tests/test_xray.py +++ b/tests/test_xray.py @@ -3,9 +3,9 @@ import json try: - from unittest.mock import patch + from unittest.mock import patch, mock except ImportError: - from mock import patch + from mock import patch, mock from datadog_lambda.xray import get_xray_host_port, build_segment_payload, build_segment From 6139e39eba2633050b57a0e619950d70475761a2 Mon Sep 17 00:00:00 2001 From: maxday Date: Fri, 3 Sep 2021 12:07:43 -0400 Subject: [PATCH 10/14] fix tests --- datadog_lambda/xray.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/datadog_lambda/xray.py b/datadog_lambda/xray.py index 571baff0..696223e2 100644 --- a/datadog_lambda/xray.py +++ b/datadog_lambda/xray.py @@ -41,8 +41,7 @@ def send(host_port_tuple, payload): def build_segment_payload(payload): if payload is None: return None - header = json.dumps({"format": "json", "version": 1}) - return header + "\n" + payload + return "{\"format\": \"json\", \"version\": 1}" + "\n" + payload def parse_xray_header(raw_trace_id): From 15374e06836817ea3634c1140f9af658b96d90b1 Mon Sep 17 00:00:00 2001 From: maxday Date: Fri, 3 Sep 2021 12:08:47 -0400 Subject: [PATCH 11/14] lint --- datadog_lambda/xray.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datadog_lambda/xray.py b/datadog_lambda/xray.py index 696223e2..e08041d1 100644 --- a/datadog_lambda/xray.py +++ b/datadog_lambda/xray.py @@ -41,7 +41,7 @@ def send(host_port_tuple, payload): def build_segment_payload(payload): if payload is None: return None - return "{\"format\": \"json\", \"version\": 1}" + "\n" + payload + return '{"format": "json", "version": 1}' + "\n" + payload def parse_xray_header(raw_trace_id): From 331ab134e9742766c0be71e9b5a6349f54c5f84e Mon Sep 17 00:00:00 2001 From: maxday Date: Fri, 3 Sep 2021 12:16:55 -0400 Subject: [PATCH 12/14] fix mock --- tests/test_xray.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_xray.py b/tests/test_xray.py index 964e09bd..7493075c 100644 --- a/tests/test_xray.py +++ b/tests/test_xray.py @@ -3,9 +3,9 @@ import json try: - from unittest.mock import patch, mock + from unittest.mock import MagicMock, patch, call except ImportError: - from mock import patch, mock + from mock import MagicMock, patch, call from datadog_lambda.xray import get_xray_host_port, build_segment_payload, build_segment @@ -31,10 +31,10 @@ def test_build_segment_payload_ok(self): def test_build_segment_payload_no_payload(self): self.assertIsNone(build_segment_payload(None)) - @mock.patch("time.time", mock.MagicMock(return_value=1111)) - @mock.patch( + @patch("time.time", mock.MagicMock(return_value=1111)) + @patch( "datadog_lambda.xray.generate_random_id", - mock.MagicMock(return_value="1234abcd"), + MagicMock(return_value="1234abcd"), ) def test_build_segment(self): context = { From 5d098a1d423f73e7511175c779e01e82fa5058b8 Mon Sep 17 00:00:00 2001 From: maxday Date: Fri, 3 Sep 2021 13:28:37 -0400 Subject: [PATCH 13/14] fix tuple --- datadog_lambda/xray.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datadog_lambda/xray.py b/datadog_lambda/xray.py index e08041d1..d4836fae 100644 --- a/datadog_lambda/xray.py +++ b/datadog_lambda/xray.py @@ -28,7 +28,7 @@ def send(host_port_tuple, payload): try: sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setblocking(0) - sock.connect(host_port_tuple[0], host_port_tuple[1]) + sock.connect(host_port_tuple) sock.send(payload.encode("utf-8")) except Exception as e_send: logger.error("Error occurred submitting to xray daemon: %s", str(e_send)) From ded279358008674d397e7dea5566689085c5b6f1 Mon Sep 17 00:00:00 2001 From: maxday Date: Fri, 3 Sep 2021 13:50:58 -0400 Subject: [PATCH 14/14] fix magicmock --- tests/test_xray.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_xray.py b/tests/test_xray.py index 7493075c..ba22928d 100644 --- a/tests/test_xray.py +++ b/tests/test_xray.py @@ -31,7 +31,7 @@ def test_build_segment_payload_ok(self): def test_build_segment_payload_no_payload(self): self.assertIsNone(build_segment_payload(None)) - @patch("time.time", mock.MagicMock(return_value=1111)) + @patch("time.time", MagicMock(return_value=1111)) @patch( "datadog_lambda.xray.generate_random_id", MagicMock(return_value="1234abcd"),