From 7c127a31eb817489b8ca396dfe67a19c36f18be6 Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Tue, 29 Oct 2024 14:29:39 -0400 Subject: [PATCH 01/24] add logic to extract traceID from _datadog header --- datadog_lambda/constants.py | 4 ++-- datadog_lambda/tracing.py | 33 +++++++++++++++++--------- tests/test_tracing.py | 47 ++++++++++++++++++++++++++++++++++--- 3 files changed, 68 insertions(+), 16 deletions(-) diff --git a/datadog_lambda/constants.py b/datadog_lambda/constants.py index fd8afb3e..6ab62738 100644 --- a/datadog_lambda/constants.py +++ b/datadog_lambda/constants.py @@ -3,9 +3,8 @@ # This product includes software developed at Datadog (https://www.datadoghq.com/). # Copyright 2019 Datadog, Inc. -# Datadog trace sampling priority - +# Datadog trace sampling priority class SamplingPriority(object): USER_REJECT = -1 AUTO_REJECT = 0 @@ -18,6 +17,7 @@ class TraceHeader(object): TRACE_ID = "x-datadog-trace-id" PARENT_ID = "x-datadog-parent-id" SAMPLING_PRIORITY = "x-datadog-sampling-priority" + TAGS = "x-datadog-tags" # X-Ray subsegment to save Datadog trace metadata diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index 0aded4de..f28c36f6 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -24,6 +24,7 @@ TraceContextSource, XrayDaemon, Headers, + TraceHeader, ) from datadog_lambda.xray import ( send_segment, @@ -380,10 +381,26 @@ def extract_context_from_step_functions(event, lambda_context): execution_id = event.get("Execution").get("Id") state_name = event.get("State").get("Name") state_entered_time = event.get("State").get("EnteredTime") - # returning 128 bits since 128bit traceId will be break up into - # traditional traceId and _dd.p.tid tag - # https://github.com/DataDog/dd-trace-py/blob/3e34d21cb9b5e1916e549047158cb119317b96ab/ddtrace/propagation/http.py#L232-L240 - trace_id = _deterministic_sha256_hash(execution_id, LOWER_64_BITS) + meta = {} + + if "_datadog" in event: + # use the trace ID from the top-most parent when it exists + trace_header = event.get("_datadog") + trace_id = trace_header.get(TraceHeader.TRACE_ID) + tags = trace_header.get(TraceHeader.TAGS) + for tag in tags.split(","): + tag_key, tag_val = tag.split("=") + meta[tag_key] = tag_val + else: + # returning 128 bits since 128bit traceId will be break up into + # traditional traceId and _dd.p.tid tag + # https://github.com/DataDog/dd-trace-py/blob/3e34d21cb9b5e1916e549047158cb119317b96ab/ddtrace/propagation/http.py#L232-L240 + trace_id = _deterministic_sha256_hash(execution_id, LOWER_64_BITS) + # take the higher 64 bits as _dd.p.tid tag and use hex to encode + # [2:] to remove '0x' in the hex str + meta["_dd.p.tid"] = hex( + _deterministic_sha256_hash(execution_id, HIGHER_64_BITS) + )[2:] parent_id = _deterministic_sha256_hash( f"{execution_id}#{state_name}#{state_entered_time}", HIGHER_64_BITS @@ -394,13 +411,7 @@ def extract_context_from_step_functions(event, lambda_context): trace_id=trace_id, span_id=parent_id, sampling_priority=sampling_priority, - # take the higher 64 bits as _dd.p.tid tag and use hex to encode - # [2:] to remove '0x' in the hex str - meta={ - "_dd.p.tid": hex( - _deterministic_sha256_hash(execution_id, HIGHER_64_BITS) - )[2:] - }, + meta=meta, ) except Exception as e: logger.debug("The Step Functions trace extractor returned with error %s", e) diff --git a/tests/test_tracing.py b/tests/test_tracing.py index 0fb2ee31..c8a42dab 100644 --- a/tests/test_tracing.py +++ b/tests/test_tracing.py @@ -617,7 +617,7 @@ def test_with_complete_datadog_trace_headers_with_trigger_tags(self): @with_trace_propagation_style("datadog") def test_step_function_trace_data(self): lambda_ctx = get_mock_context() - sqs_event = { + sf_event = { "Execution": { "Id": "665c417c-1237-4742-aaca-8b3becbb9e75", }, @@ -627,7 +627,7 @@ def test_step_function_trace_data(self): "EnteredTime": "Mon Nov 13 12:43:33 PST 2023", }, } - ctx, source, event_source = extract_dd_trace_context(sqs_event, lambda_ctx) + ctx, source, event_source = extract_dd_trace_context(sf_event, lambda_ctx) self.assertEqual(source, "event") expected_context = Context( trace_id=3675572987363469717, @@ -642,7 +642,48 @@ def test_step_function_trace_data(self): TraceHeader.TRACE_ID: "3675572987363469717", TraceHeader.PARENT_ID: "10713633173203262661", TraceHeader.SAMPLING_PRIORITY: "1", - "x-datadog-tags": "_dd.p.tid=e987c84b36b11ab", + TraceHeader.TAGS: "_dd.p.tid=e987c84b36b11ab", + }, + ) + create_dd_dummy_metadata_subsegment(ctx, XraySubsegment.TRACE_KEY) + self.mock_send_segment.assert_called_with( + XraySubsegment.TRACE_KEY, + expected_context, + ) + + @with_trace_propagation_style("datadog") + def test_step_function_trace_data(self): + lambda_ctx = get_mock_context() + sf_event = { + "Execution": { + "Id": "665c417c-1237-4742-aaca-8b3becbb9e75", + }, + "StateMachine": {}, + "State": { + "Name": "my-awesome-state", + "EnteredTime": "Mon Nov 13 12:43:33 PST 2023", + }, + "_datadog": { + "x-datadog-trace-id": "4061173386180447114", + "x-datadog-tags": "_dd.p.tid=aac3639aa724716", + }, + } + ctx, source, event_source = extract_dd_trace_context(sf_event, lambda_ctx) + self.assertEqual(source, "event") + expected_context = Context( + trace_id=4061173386180447114, + span_id=6880978411788117524, + sampling_priority=1, + meta={"_dd.p.tid": "aac3639aa724716"}, + ) + self.assertEqual(ctx, expected_context) + self.assertEqual( + get_dd_trace_context(), + { + TraceHeader.TRACE_ID: "4061173386180447114", + TraceHeader.PARENT_ID: "10713633173203262661", + TraceHeader.SAMPLING_PRIORITY: "1", + TraceHeader.TAGS: "_dd.p.tid=aac3639aa724716", }, ) create_dd_dummy_metadata_subsegment(ctx, XraySubsegment.TRACE_KEY) From 8658dea2bff07731cad14b563150278f1f48be3f Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Tue, 29 Oct 2024 14:36:46 -0400 Subject: [PATCH 02/24] rename test --- tests/test_tracing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tracing.py b/tests/test_tracing.py index c8a42dab..b4fe21ed 100644 --- a/tests/test_tracing.py +++ b/tests/test_tracing.py @@ -652,7 +652,7 @@ def test_step_function_trace_data(self): ) @with_trace_propagation_style("datadog") - def test_step_function_trace_data(self): + def test_step_function_trace_data_with_header(self): lambda_ctx = get_mock_context() sf_event = { "Execution": { From 3eccb202a870bd380bb51c79e61e1518ff41585a Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Tue, 29 Oct 2024 14:45:01 -0400 Subject: [PATCH 03/24] fix type --- datadog_lambda/tracing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index f28c36f6..21c5df0d 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -386,7 +386,7 @@ def extract_context_from_step_functions(event, lambda_context): if "_datadog" in event: # use the trace ID from the top-most parent when it exists trace_header = event.get("_datadog") - trace_id = trace_header.get(TraceHeader.TRACE_ID) + trace_id = int(trace_header.get(TraceHeader.TRACE_ID)) tags = trace_header.get(TraceHeader.TAGS) for tag in tags.split(","): tag_key, tag_val = tag.split("=") From 97b189ab31d2d35dc3e4c78a1d7b00e2e4ab2781 Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Wed, 30 Oct 2024 14:56:39 -0400 Subject: [PATCH 04/24] added root arn case --- datadog_lambda/tracing.py | 19 ++++++++++++------ tests/test_tracing.py | 42 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index 21c5df0d..dce27f7c 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -384,13 +384,20 @@ def extract_context_from_step_functions(event, lambda_context): meta = {} if "_datadog" in event: - # use the trace ID from the top-most parent when it exists trace_header = event.get("_datadog") - trace_id = int(trace_header.get(TraceHeader.TRACE_ID)) - tags = trace_header.get(TraceHeader.TAGS) - for tag in tags.split(","): - tag_key, tag_val = tag.split("=") - meta[tag_key] = tag_val + if TraceHeader.TRACE_ID in trace_header: + # use the trace ID from the top-most parent when it exists + trace_id = int(trace_header.get(TraceHeader.TRACE_ID)) + tags = trace_header.get(TraceHeader.TAGS, "") + for tag in tags.split(","): + tag_key, tag_val = tag.split("=") + meta[tag_key] = tag_val + elif "x-datadog-execution-arn" in trace_header: + root_execution_id = trace_header.get("x-datadog-execution-arn") + trace_id = _deterministic_sha256_hash(root_execution_id, LOWER_64_BITS) + meta["_dd.p.tid"] = hex( + _deterministic_sha256_hash(root_execution_id, HIGHER_64_BITS) + )[2:] else: # returning 128 bits since 128bit traceId will be break up into # traditional traceId and _dd.p.tid tag diff --git a/tests/test_tracing.py b/tests/test_tracing.py index b4fe21ed..c0307b52 100644 --- a/tests/test_tracing.py +++ b/tests/test_tracing.py @@ -652,7 +652,7 @@ def test_step_function_trace_data(self): ) @with_trace_propagation_style("datadog") - def test_step_function_trace_data_with_header(self): + def test_step_function_trace_data_with_trace_header(self): lambda_ctx = get_mock_context() sf_event = { "Execution": { @@ -692,6 +692,46 @@ def test_step_function_trace_data_with_header(self): expected_context, ) + @with_trace_propagation_style("datadog") + def test_step_function_trace_data_with_arn_header(self): + lambda_ctx = get_mock_context() + sf_event = { + "Execution": { + "Id": "665c417c-1237-4742-aaca-8b3becbb9e75", + }, + "StateMachine": {}, + "State": { + "Name": "my-awesome-state", + "EnteredTime": "Mon Nov 13 12:43:33 PST 2023", + }, + "_datadog": { + "x-datadog-execution-arn": "ca7383bc-e370-4a85-a266-a4686bd7d00f" + }, + } + ctx, source, event_source = extract_dd_trace_context(sf_event, lambda_ctx) + self.assertEqual(source, "event") + expected_context = Context( + trace_id=6970872619724504833, + span_id=6880978411788117524, + sampling_priority=1, + meta={"_dd.p.tid": "71dab8f4d4629263"}, + ) + self.assertEqual(ctx, expected_context) + self.assertEqual( + get_dd_trace_context(), + { + TraceHeader.TRACE_ID: "6970872619724504833", + TraceHeader.PARENT_ID: "10713633173203262661", + TraceHeader.SAMPLING_PRIORITY: "1", + TraceHeader.TAGS: "_dd.p.tid=71dab8f4d4629263", + }, + ) + create_dd_dummy_metadata_subsegment(ctx, XraySubsegment.TRACE_KEY) + self.mock_send_segment.assert_called_with( + XraySubsegment.TRACE_KEY, + expected_context, + ) + def test_is_legacy_lambda_step_function(self): sf_event = { "Payload": { From eaa09f382232f7e76fc6172c1ea7d517f42b3adc Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Wed, 30 Oct 2024 15:09:39 -0400 Subject: [PATCH 05/24] trigger ci From 2baec69f713bdaec9a4185072c65886b2188570c Mon Sep 17 00:00:00 2001 From: Nicholas Hulston Date: Tue, 29 Oct 2024 14:12:38 -0400 Subject: [PATCH 06/24] Add `http.route` tags for API Gateway (#524) Add route tags --- datadog_lambda/trigger.py | 6 ++++++ .../integration/snapshots/logs/async-metrics_python310.log | 2 ++ .../integration/snapshots/logs/async-metrics_python311.log | 2 ++ .../integration/snapshots/logs/async-metrics_python312.log | 2 ++ tests/integration/snapshots/logs/async-metrics_python38.log | 2 ++ tests/integration/snapshots/logs/async-metrics_python39.log | 2 ++ tests/integration/snapshots/logs/sync-metrics_python310.log | 2 ++ tests/integration/snapshots/logs/sync-metrics_python311.log | 2 ++ tests/integration/snapshots/logs/sync-metrics_python312.log | 2 ++ tests/integration/snapshots/logs/sync-metrics_python38.log | 2 ++ tests/integration/snapshots/logs/sync-metrics_python39.log | 2 ++ tests/test_trigger.py | 3 +++ 12 files changed, 29 insertions(+) diff --git a/datadog_lambda/trigger.py b/datadog_lambda/trigger.py index 68531ebf..64eff1a0 100644 --- a/datadog_lambda/trigger.py +++ b/datadog_lambda/trigger.py @@ -299,6 +299,12 @@ def extract_http_tags(event): if headers and headers.get("Referer"): http_tags["http.referer"] = headers.get("Referer") + # Try to get `routeKey` from API GW v2; otherwise try to get `resource` from API GW v1 + route = event.get("routeKey") or event.get("resource") + if route: + # "GET /my/endpoint" = > "/my/endpoint" + http_tags["http.route"] = route.split(" ")[-1] + return http_tags diff --git a/tests/integration/snapshots/logs/async-metrics_python310.log b/tests/integration/snapshots/logs/async-metrics_python310.log index 704e89b5..40c23c68 100644 --- a/tests/integration/snapshots/logs/async-metrics_python310.log +++ b/tests/integration/snapshots/logs/async-metrics_python310.log @@ -106,6 +106,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.us-east-2.amazonaws.com", "http.url_details.path": "/Prod/", "http.method": "GET", + "http.route": "/", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, @@ -605,6 +606,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.eu-west-1.amazonaws.com", "http.url_details.path": "/httpapi/get", "http.method": "GET", + "http.route": "/httpapi/get", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, diff --git a/tests/integration/snapshots/logs/async-metrics_python311.log b/tests/integration/snapshots/logs/async-metrics_python311.log index b97628ac..f1f12db4 100644 --- a/tests/integration/snapshots/logs/async-metrics_python311.log +++ b/tests/integration/snapshots/logs/async-metrics_python311.log @@ -106,6 +106,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.us-east-2.amazonaws.com", "http.url_details.path": "/Prod/", "http.method": "GET", + "http.route": "/", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, @@ -605,6 +606,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.eu-west-1.amazonaws.com", "http.url_details.path": "/httpapi/get", "http.method": "GET", + "http.route": "/httpapi/get", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, diff --git a/tests/integration/snapshots/logs/async-metrics_python312.log b/tests/integration/snapshots/logs/async-metrics_python312.log index 79dbefc1..3bc69cca 100644 --- a/tests/integration/snapshots/logs/async-metrics_python312.log +++ b/tests/integration/snapshots/logs/async-metrics_python312.log @@ -106,6 +106,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.us-east-2.amazonaws.com", "http.url_details.path": "/Prod/", "http.method": "GET", + "http.route": "/", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, @@ -605,6 +606,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.eu-west-1.amazonaws.com", "http.url_details.path": "/httpapi/get", "http.method": "GET", + "http.route": "/httpapi/get", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, diff --git a/tests/integration/snapshots/logs/async-metrics_python38.log b/tests/integration/snapshots/logs/async-metrics_python38.log index 3b9d7c76..fdc6b192 100644 --- a/tests/integration/snapshots/logs/async-metrics_python38.log +++ b/tests/integration/snapshots/logs/async-metrics_python38.log @@ -106,6 +106,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.us-east-2.amazonaws.com", "http.url_details.path": "/Prod/", "http.method": "GET", + "http.route": "/", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, @@ -605,6 +606,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.eu-west-1.amazonaws.com", "http.url_details.path": "/httpapi/get", "http.method": "GET", + "http.route": "/httpapi/get", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, diff --git a/tests/integration/snapshots/logs/async-metrics_python39.log b/tests/integration/snapshots/logs/async-metrics_python39.log index 4e820246..c6c68290 100644 --- a/tests/integration/snapshots/logs/async-metrics_python39.log +++ b/tests/integration/snapshots/logs/async-metrics_python39.log @@ -106,6 +106,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.us-east-2.amazonaws.com", "http.url_details.path": "/Prod/", "http.method": "GET", + "http.route": "/", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, @@ -605,6 +606,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.eu-west-1.amazonaws.com", "http.url_details.path": "/httpapi/get", "http.method": "GET", + "http.route": "/httpapi/get", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, diff --git a/tests/integration/snapshots/logs/sync-metrics_python310.log b/tests/integration/snapshots/logs/sync-metrics_python310.log index 339c821c..5d9262ce 100644 --- a/tests/integration/snapshots/logs/sync-metrics_python310.log +++ b/tests/integration/snapshots/logs/sync-metrics_python310.log @@ -86,6 +86,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.us-east-2.amazonaws.com", "http.url_details.path": "/Prod/", "http.method": "GET", + "http.route": "/", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, @@ -642,6 +643,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.eu-west-1.amazonaws.com", "http.url_details.path": "/httpapi/get", "http.method": "GET", + "http.route": "/httpapi/get", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, diff --git a/tests/integration/snapshots/logs/sync-metrics_python311.log b/tests/integration/snapshots/logs/sync-metrics_python311.log index 878b0d64..e93a4d0e 100644 --- a/tests/integration/snapshots/logs/sync-metrics_python311.log +++ b/tests/integration/snapshots/logs/sync-metrics_python311.log @@ -86,6 +86,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.us-east-2.amazonaws.com", "http.url_details.path": "/Prod/", "http.method": "GET", + "http.route": "/", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, @@ -642,6 +643,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.eu-west-1.amazonaws.com", "http.url_details.path": "/httpapi/get", "http.method": "GET", + "http.route": "/httpapi/get", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, diff --git a/tests/integration/snapshots/logs/sync-metrics_python312.log b/tests/integration/snapshots/logs/sync-metrics_python312.log index c4dc17bc..c912cede 100644 --- a/tests/integration/snapshots/logs/sync-metrics_python312.log +++ b/tests/integration/snapshots/logs/sync-metrics_python312.log @@ -86,6 +86,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.us-east-2.amazonaws.com", "http.url_details.path": "/Prod/", "http.method": "GET", + "http.route": "/", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, @@ -642,6 +643,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.eu-west-1.amazonaws.com", "http.url_details.path": "/httpapi/get", "http.method": "GET", + "http.route": "/httpapi/get", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, diff --git a/tests/integration/snapshots/logs/sync-metrics_python38.log b/tests/integration/snapshots/logs/sync-metrics_python38.log index 3e756430..74a1e06b 100644 --- a/tests/integration/snapshots/logs/sync-metrics_python38.log +++ b/tests/integration/snapshots/logs/sync-metrics_python38.log @@ -86,6 +86,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.us-east-2.amazonaws.com", "http.url_details.path": "/Prod/", "http.method": "GET", + "http.route": "/", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, @@ -642,6 +643,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.eu-west-1.amazonaws.com", "http.url_details.path": "/httpapi/get", "http.method": "GET", + "http.route": "/httpapi/get", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, diff --git a/tests/integration/snapshots/logs/sync-metrics_python39.log b/tests/integration/snapshots/logs/sync-metrics_python39.log index ceffe679..19f0e84c 100644 --- a/tests/integration/snapshots/logs/sync-metrics_python39.log +++ b/tests/integration/snapshots/logs/sync-metrics_python39.log @@ -86,6 +86,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.us-east-2.amazonaws.com", "http.url_details.path": "/Prod/", "http.method": "GET", + "http.route": "/", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, @@ -642,6 +643,7 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "http.url": "XXXX.execute-api.eu-west-1.amazonaws.com", "http.url_details.path": "/httpapi/get", "http.method": "GET", + "http.route": "/httpapi/get", "http.status_code": "200", "_dd.base_service": "integration-tests-python" }, diff --git a/tests/test_trigger.py b/tests/test_trigger.py index 59178b1e..c1e7f5d7 100644 --- a/tests/test_trigger.py +++ b/tests/test_trigger.py @@ -258,6 +258,7 @@ def test_extract_trigger_tags_api_gateway(self): "http.url": "70ixmpl4fl.execute-api.us-east-2.amazonaws.com", "http.url_details.path": "/prod/path/to/resource", "http.method": "POST", + "http.route": "/{proxy+}", }, ) @@ -276,6 +277,7 @@ def test_extract_trigger_tags_api_gateway_non_proxy(self): "http.url": "lgxbo6a518.execute-api.eu-west-1.amazonaws.com", "http.url_details.path": "/dev/http/get", "http.method": "GET", + "http.route": "/http/get", }, ) @@ -342,6 +344,7 @@ def test_extract_trigger_tags_api_gateway_http_api(self): "http.url": "x02yirxc7a.execute-api.eu-west-1.amazonaws.com", "http.url_details.path": "/httpapi/get", "http.method": "GET", + "http.route": "/httpapi/get", }, ) From 3c4014bb711e1995f8285e65a3a43660ec3a6197 Mon Sep 17 00:00:00 2001 From: Aleksandr Pasechnik Date: Wed, 30 Oct 2024 15:17:11 -0400 Subject: [PATCH 07/24] feat: [SVLS-5677] DynamoDB Stream event span pointers (#522) --- datadog_lambda/span_pointers.py | 75 +++- poetry.lock | 387 +++++++++--------- pyproject.toml | 2 +- tests/Dockerfile | 5 + .../logs/async-metrics_python310.log | 48 ++- .../logs/async-metrics_python311.log | 48 ++- .../logs/async-metrics_python312.log | 48 ++- .../snapshots/logs/async-metrics_python38.log | 48 ++- .../snapshots/logs/async-metrics_python39.log | 48 ++- .../snapshots/logs/sync-metrics_python310.log | 48 ++- .../snapshots/logs/sync-metrics_python311.log | 48 ++- .../snapshots/logs/sync-metrics_python312.log | 48 ++- .../snapshots/logs/sync-metrics_python38.log | 48 ++- .../snapshots/logs/sync-metrics_python39.log | 48 ++- tests/test_span_pointers.py | 61 +++ 15 files changed, 799 insertions(+), 211 deletions(-) diff --git a/datadog_lambda/span_pointers.py b/datadog_lambda/span_pointers.py index 4c33975f..669257bd 100644 --- a/datadog_lambda/span_pointers.py +++ b/datadog_lambda/span_pointers.py @@ -2,7 +2,10 @@ import logging from typing import List -from ddtrace._trace.utils_botocore.span_pointers import ( +from ddtrace._trace.utils_botocore.span_pointers.dynamodb import ( + _aws_dynamodb_item_span_pointer_description, +) +from ddtrace._trace.utils_botocore.span_pointers.s3 import ( _aws_s3_object_span_pointer_description, ) from ddtrace._trace._span_pointer import _SpanPointerDirection @@ -21,10 +24,13 @@ def calculate_span_pointers( if event_source.equals(EventTypes.S3): return _calculate_s3_span_pointers_for_event(event) + elif event_source.equals(EventTypes.DYNAMODB): + return _calculate_dynamodb_span_pointers_for_event(event) + except Exception as e: logger.warning( "failed to calculate span pointers for event: %s", - str(e), + e, ) return [] @@ -69,7 +75,7 @@ def _calculate_s3_span_pointers_for_object_created_s3_information( except KeyError as e: logger.warning( "missing s3 information required to make a span pointer: %s", - str(e), + e, ) return [] @@ -86,6 +92,67 @@ def _calculate_s3_span_pointers_for_object_created_s3_information( except Exception as e: logger.warning( "failed to generate S3 span pointer: %s", - str(e), + e, + ) + return [] + + +def _calculate_dynamodb_span_pointers_for_event(event) -> List[_SpanPointerDescription]: + # Example event: + # https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html + + return list( + chain.from_iterable( + _calculate_dynamodb_span_pointers_for_event_record(record) + for record in event.get("Records", []) + ) + ) + + +def _calculate_dynamodb_span_pointers_for_event_record( + record, +) -> List[_SpanPointerDescription]: + try: + table_name = _extract_table_name_from_dynamodb_stream_record(record) + primary_key = record["dynamodb"]["Keys"] + + except Exception as e: + logger.warning( + "missing DynamoDB information required to make a span pointer: %s", + e, ) return [] + + try: + return [ + _aws_dynamodb_item_span_pointer_description( + pointer_direction=_SpanPointerDirection.UPSTREAM, + table_name=table_name, + primary_key=primary_key, + ) + ] + + except Exception as e: + logger.warning( + "failed to generate DynamoDB span pointer: %s", + e, + ) + return [] + + +def _extract_table_name_from_dynamodb_stream_record(record) -> str: + # Example eventSourceARN: + # arn:aws:dynamodb:us-east-2:123456789012:table/my-table/stream/2024-06-10T19:26:16.525 + event_source_arn = record["eventSourceARN"] + + [_arn, _aws, _dynamodb, _region, _account, dynamodb_info] = event_source_arn.split( + ":", maxsplit=5 + ) + if _arn != "arn" or _aws != "aws" or _dynamodb != "dynamodb": + raise ValueError(f"unexpected eventSourceARN format: {event_source_arn}") + + [_table, table_name, _stream, _timestamp] = dynamodb_info.split("/") + if _table != "table" or _stream != "stream": + raise ValueError(f"unexpected eventSourceARN format: {event_source_arn}") + + return table_name diff --git a/poetry.lock b/poetry.lock index e9557200..c87fea84 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,17 +2,17 @@ [[package]] name = "boto3" -version = "1.35.31" +version = "1.35.51" description = "The AWS SDK for Python" optional = true python-versions = ">=3.8" files = [ - {file = "boto3-1.35.31-py3-none-any.whl", hash = "sha256:2e9af74d10d8af7610a8d8468d2914961f116912a024fce17351825260385a52"}, - {file = "boto3-1.35.31.tar.gz", hash = "sha256:8c593af260c4ea3eb6f079c09908f94494ca2222aa4e40a7ff490fab1cee8b39"}, + {file = "boto3-1.35.51-py3-none-any.whl", hash = "sha256:c922f6a18958af9d8af0489d6d8503b517029d8159b26aa4859a8294561c72e9"}, + {file = "boto3-1.35.51.tar.gz", hash = "sha256:a57c6c7012ecb40c43e565a6f7a891f39efa990ff933eab63cd456f7501c2731"}, ] [package.dependencies] -botocore = ">=1.35.31,<1.36.0" +botocore = ">=1.35.51,<1.36.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.10.0,<0.11.0" @@ -21,13 +21,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.35.31" +version = "1.35.51" description = "Low-level, data-driven core of boto 3." optional = true python-versions = ">=3.8" files = [ - {file = "botocore-1.35.31-py3-none-any.whl", hash = "sha256:4cee814875bc78656aef4011d3d6b2231e96f53ea3661ee428201afb579d5c31"}, - {file = "botocore-1.35.31.tar.gz", hash = "sha256:f7bfa910cf2cbcc8c2307c1cf7b93495d614c2d699883417893e0a337fe4eb63"}, + {file = "botocore-1.35.51-py3-none-any.whl", hash = "sha256:4d65b00111bd12b98e9f920ecab602cf619cc6a6d0be6e5dd53f517e4b92901c"}, + {file = "botocore-1.35.51.tar.gz", hash = "sha256:a9b3d1da76b3e896ad74605c01d88f596324a3337393d4bfbfa0d6c35822ca9c"}, ] [package.dependencies] @@ -39,17 +39,17 @@ urllib3 = [ ] [package.extras] -crt = ["awscrt (==0.21.5)"] +crt = ["awscrt (==0.22.0)"] [[package]] name = "bytecode" -version = "0.15.1" +version = "0.16.0" description = "Python module to generate and modify bytecode" optional = false python-versions = ">=3.8" files = [ - {file = "bytecode-0.15.1-py3-none-any.whl", hash = "sha256:0a1dc340cac823cff605609b8b214f7f9bf80418c6b9e0fc8c6db1793c27137d"}, - {file = "bytecode-0.15.1.tar.gz", hash = "sha256:7263239a8d3f70fc7c303862b20cd2c6788052e37ce0a26e67309d280e985984"}, + {file = "bytecode-0.16.0-py3-none-any.whl", hash = "sha256:76080b7c0eb9e7e17f961d61fd06e933aa47f3b753770a3249537439d8203a25"}, + {file = "bytecode-0.16.0.tar.gz", hash = "sha256:06676a3c3bccc9d3dc73ee625650ea57df2bc117358826f4f290f0e1faa42292"}, ] [package.dependencies] @@ -68,101 +68,116 @@ files = [ [[package]] name = "charset-normalizer" -version = "3.3.2" +version = "3.4.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"}, + {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, + {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, ] [[package]] @@ -192,71 +207,71 @@ requests = ">=2.6.0" [[package]] name = "ddtrace" -version = "2.14.1" +version = "2.15.0" description = "Datadog APM client library" optional = false python-versions = ">=3.7" files = [ - {file = "ddtrace-2.14.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:45006561033362ae3bf8619e4e23b5f044c1d85ab75f60bfada9cb26b50f3136"}, - {file = "ddtrace-2.14.1-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:ec918f63a49f426f0b8507ed045752d31a4fbac6058861dab37e59ea21ec14e6"}, - {file = "ddtrace-2.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6dbef64063312afac39fe3c46aa848e0191b741a31664ce994445c76beb49aa5"}, - {file = "ddtrace-2.14.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aff1e0749d8bda9e7ec68a3d7c847a02fc6cca8f8a0444c7d33d8c11d6cb9d28"}, - {file = "ddtrace-2.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9cec95ed8e442efdab682e54b4d200d100c028207a2597fc0e879518f08495b2"}, - {file = "ddtrace-2.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:33d0437a4a4e71ae1defb58d940d3efddb3372201bc5ae0ecb960bc5b1684453"}, - {file = "ddtrace-2.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:66e07bca5bcdb16231bdaf6f848b9d2ab677ab6569185cf33ffceac1406123fb"}, - {file = "ddtrace-2.14.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:6257295f04950773929ab2586a6b1193015dffdf2e1f915decfb8cce99e7be3e"}, - {file = "ddtrace-2.14.1-cp310-cp310-win32.whl", hash = "sha256:e57d43bb848a40f4b5efacb3ebece41ddfc4d40b4fb9e5d1b49d43fd33565666"}, - {file = "ddtrace-2.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:e595d2acba589f2881809c3a1e8302a8ddbfc9d49a546eadf9fb57ee18e39472"}, - {file = "ddtrace-2.14.1-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:bd5c7274978625688b4eece12deb19704c2ba16187e1e8c35a76b312b6ee587f"}, - {file = "ddtrace-2.14.1-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:901e57ed636fbf5b5d002b0348f33d502779cc31d75ac703b63e0b6a84085c07"}, - {file = "ddtrace-2.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20c4cd8ae87bef85542984ac203f5dd20359daf3a5d7f3f6f7f69736adb0c79e"}, - {file = "ddtrace-2.14.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ad1fbb0705ff096184e3e5013c6e8f3b7181847ddfb18ea7f8311c3913a5734"}, - {file = "ddtrace-2.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a57bb3f8e1bce2e19e3e7effa244bd6cf34a8203692f222c775d8b7d0cd17fa"}, - {file = "ddtrace-2.14.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c8e071118dc999d66b94bbe4d927967c76f97a6d10579d75881ee0ecde97baa8"}, - {file = "ddtrace-2.14.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:08edf6315429f7b46c760f8726e1f4dd1538c9afd2c02861b5341fd78c39ae5a"}, - {file = "ddtrace-2.14.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:707a7c4a0af62234b0d0a8480d9b0c534d57f25a22f554842bceacbd6ad11f96"}, - {file = "ddtrace-2.14.1-cp311-cp311-win32.whl", hash = "sha256:d52e5cecfddd9b0155792f8f2dc8060337d692a37b24cf8dd862b3026797c1cb"}, - {file = "ddtrace-2.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:761cbfc629636d38a166f8b8eb5425bdbb29aeaad093095230078257e75572cc"}, - {file = "ddtrace-2.14.1-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:b7e128001653ad1e24a6705251110c49f8017cb22071de3b77b43bf77978d90b"}, - {file = "ddtrace-2.14.1-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:18133ea923613214dfff790a48f4a0cfdfc642804bdb4e3b3e7176848f6b1d8f"}, - {file = "ddtrace-2.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d59eb2995eec053a7301a07c34795db06ce12b1b86ce787afa3c67ec3bcf6a"}, - {file = "ddtrace-2.14.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8b4aa9aa17f64f2f8e33b9133c5929eebc82773bdf4f739472a4308595bede1e"}, - {file = "ddtrace-2.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70f78d588a8a11c5b5b12612100fd0e05eb6e85d9c33848555e151b20fa5f2c3"}, - {file = "ddtrace-2.14.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3cafa9a6663bef1a3caee783f21f5a94c6bb77cf9ab62b9ec6f7c160cdd012aa"}, - {file = "ddtrace-2.14.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4a9385b52405d069a7cf0d17917a9efafb7261e3d77fe6a3366840e4978e70d9"}, - {file = "ddtrace-2.14.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:219ccfd16c0117ab2b26249acb0c88cc0eb0d9543d422ac0ba8f0bfaddb1be2f"}, - {file = "ddtrace-2.14.1-cp312-cp312-win32.whl", hash = "sha256:97c154e3fb9312fdc926d42204f6aa6966d51a834ef48b5f1655ad8d37b8ee32"}, - {file = "ddtrace-2.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:0286787a6d883606351b2c59ea21deefdeb80cf07f80d37cf86aef8dd1f17637"}, - {file = "ddtrace-2.14.1-cp37-cp37m-macosx_12_0_x86_64.whl", hash = "sha256:294583ef333a9cbe5f8ec4906f37dd9dad27d5007a848d291908c1f6df5dabbe"}, - {file = "ddtrace-2.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e863f82f3911242bbcac1c1f9575ba025dae0fc00c57d949b14ca62a27f6dc10"}, - {file = "ddtrace-2.14.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8fee112bd030daf73a26845ebeeb94d2fbdd6aff716643cbad2cf7c68fe722c1"}, - {file = "ddtrace-2.14.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6705f094130d39f9024831273790d240d1af00c18055377fd7084af693ada600"}, - {file = "ddtrace-2.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ae3461dac55604e035e8fecaf1ae5ef65a3bb0cd6c212966df54316ed46c144e"}, - {file = "ddtrace-2.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7bd0d58fd9b06c1c8b07ce8dd186261f5c102d1c56cebff740874e01dc5936ae"}, - {file = "ddtrace-2.14.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:5a67f9e97571de6f942f20d6d2f2882b7f257b182a73837ae9dd2b9e1376882b"}, - {file = "ddtrace-2.14.1-cp37-cp37m-win32.whl", hash = "sha256:0a823207f4b9035cc879d58e9b2121b20d803bf6b5ac1d9359393298625aae10"}, - {file = "ddtrace-2.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9c33cae0222ade654a77a371ed00d8f62cf37c556effebe19a4e0bfb036775a4"}, - {file = "ddtrace-2.14.1-cp38-cp38-macosx_12_0_universal2.whl", hash = "sha256:2bf270159b34c665cdfb9aaac1f7f449dae8665006302a82c97960b74d00dadd"}, - {file = "ddtrace-2.14.1-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:177ebdb00433aedeefb827e62b65900b8f80781d4b787cd26d219360cebfc1cc"}, - {file = "ddtrace-2.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a189b7b4645056cca7e60bd7c66bd88d8561a61326214f6ba7b0299c1b192f74"}, - {file = "ddtrace-2.14.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e444b5d398fb93270740ae43e181ba2693529feb0bbef196525cc6a8981cd0b4"}, - {file = "ddtrace-2.14.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39085a8499dbf078081a0ab48fb9e3912386a99325fa70875c07b93325c8e22e"}, - {file = "ddtrace-2.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c60cba86266502635e0078e0017884c2d685381ce4f009884e49a384bbec100b"}, - {file = "ddtrace-2.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8a777b6579ca47b7111481d16d1b7fb83ce4356ffc15d3baf38cc5fd28ec1ff0"}, - {file = "ddtrace-2.14.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:8061bad8fc33981c5d1bd424047595016cc1bf08329492852dd737fcd19516c0"}, - {file = "ddtrace-2.14.1-cp38-cp38-win32.whl", hash = "sha256:1cfc9200b68f48eaa1382efcb73a66757d44891d2b35707d92b2787d0a710277"}, - {file = "ddtrace-2.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:9e4ca8d072412d9a1052130cb163f665d01b2314c741bb4809e5bcb1621a9ea3"}, - {file = "ddtrace-2.14.1-cp39-cp39-macosx_12_0_universal2.whl", hash = "sha256:2d5d333050abad107eabf2a322753869e0cda4a7daef58b1704ea19cb7b60649"}, - {file = "ddtrace-2.14.1-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:3dc5731a22a35726c1e32873e86972e0b36ad44bf4d0c848d4ea0970995889bc"}, - {file = "ddtrace-2.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3acb996ea7096f6ceebee9e4c84d61e583c7c3f222de6f2ee55981234d74338"}, - {file = "ddtrace-2.14.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cbe96ca1985b10e26a920e1a201416fe247f80abb534833a74a43c927c0d69b"}, - {file = "ddtrace-2.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b7f2483b46a973a1b2271ac2dbf537d3d9e1ab1ed529fc1d3a82cc7b2643dd6"}, - {file = "ddtrace-2.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:019e0606b2bb38a2d38695165195bf18b23334bd9083a2805bbbec1a48a952d5"}, - {file = "ddtrace-2.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:55cbb14cd48548ebbacc6abff1b5a226531bc5a36dd063e235b0da8b544ee04f"}, - {file = "ddtrace-2.14.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:79b01d499a2cf34d8bdf871c82b33d295f4a3d8ab1b25b2e650094d8b0ad7b07"}, - {file = "ddtrace-2.14.1-cp39-cp39-win32.whl", hash = "sha256:55c9a18c8d1443a6ffa788427f6d7450676eb54619631b31f0220fd16351b4c6"}, - {file = "ddtrace-2.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:905c7c84681e6ffd59680a8cb9ac5883699a7c4f3ed00b4c8cc25a8b50a60633"}, - {file = "ddtrace-2.14.1.tar.gz", hash = "sha256:9d7a443824ed84eac2923b8655c45d07aff374088f562dedbb4e7734122bbad5"}, + {file = "ddtrace-2.15.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:8e95399bcbbef7653329ca34f4ec47b49c8364f90097b781982b41ad39c9d9cc"}, + {file = "ddtrace-2.15.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:42f34571041e92f6326819c543d114059ab381a4e73a4f90c803a74aff750421"}, + {file = "ddtrace-2.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e9a043a0c8e4f4ad2ef5820ad5a75e66eff0f10223768a697302c27b0f3fbed"}, + {file = "ddtrace-2.15.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20706878d973b046a032d7e44b4314f9c6fbf3329942664ca5f4949119625644"}, + {file = "ddtrace-2.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a51d604d1f647eff82f5ae2a14c924a2164ded3d2217dbf5b2787f2384a11a"}, + {file = "ddtrace-2.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c3ccb04acddf37dcc6458949dbe91a1f230deaf30cf386501c2e6b20986a37bf"}, + {file = "ddtrace-2.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6004a1fc48ff6f564d35c790e002bdb7ce39a904126d9d3ce3696b9586ce6ad8"}, + {file = "ddtrace-2.15.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e4a676ddb3c03149545a21d874ae846d3a467dbc37ba253681deecccb5cfae03"}, + {file = "ddtrace-2.15.0-cp310-cp310-win32.whl", hash = "sha256:cfa81e4d7897dd335a79c0c727001797f9a3ffea6c4f1444335fd6bb7694cd97"}, + {file = "ddtrace-2.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:0ad47afc29f66bece98a166e808dc07d197a78098c81546417e0455d3cf10b31"}, + {file = "ddtrace-2.15.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:8e2da75e5bd550fc04415a2446536a3d31c2c28bbfc44ecb2435058693e71329"}, + {file = "ddtrace-2.15.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:d41abf53aeab1248ef5a4c58366fe5e67522cc1995727724f1c8e3c5acdd0150"}, + {file = "ddtrace-2.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30a8960cc062eabbaf4a37febcf5e68e9984100cd345bce4fa1c65366290d0eb"}, + {file = "ddtrace-2.15.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8fbf939613d2c81bcd04b7d9e854b4391e26b9c21c6b719ecfbdeb19e6c35089"}, + {file = "ddtrace-2.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f528fe2d90f2f549ce9ca699b45889b92698005f8d356d54cdff2730ee608798"}, + {file = "ddtrace-2.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:721eddd72f5d062a7da5bcd6f9f06010368b75648b6b54661949ee22ee5b0fe5"}, + {file = "ddtrace-2.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9d0649f0b3e590e119c63ed553120acaea54e511ee495f4ab7d7c1ef2d2ec778"}, + {file = "ddtrace-2.15.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7c21f909aec4d666ad08dd26e42afa07ec560e2e157b4abdbec92b9f3ffa2ab4"}, + {file = "ddtrace-2.15.0-cp311-cp311-win32.whl", hash = "sha256:dc0b0d42f96da8f70a5bd64247392c3a10c16e03633098f6ad5fef8894655d6a"}, + {file = "ddtrace-2.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:09953ad48275eb5281c642454d3403db413eb957cb7935d80951580982339831"}, + {file = "ddtrace-2.15.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:29cc10454b4c3ea25dfd41b008916d37d19b87f18145a47e7a82bb8dce696ba1"}, + {file = "ddtrace-2.15.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:1ecebd2ac49395a58e7649bcb8e2a65055b2edc35a347350cb71c062f2031bf2"}, + {file = "ddtrace-2.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e2e6fa42b99093205dec28f0be320f537ce8e70caca00e61e49d9d0898639e0"}, + {file = "ddtrace-2.15.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a69a43621052a82fa832ca005cc20d1408d94f5822e0a1484a48c94b1fd25654"}, + {file = "ddtrace-2.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:456ff1ed2f844d44be33429becfb6175252399d1f97507972ab02146a6b694b2"}, + {file = "ddtrace-2.15.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0872179e321986b7b67c6192469fdfe6b394c08e86852d21907ff8d7f1c212d5"}, + {file = "ddtrace-2.15.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4125abc8a11add44c15a5f57f71e25fd5dca02af5696ec49336ec8ad9c11b15e"}, + {file = "ddtrace-2.15.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0363c2aaf59b0421ed3717989c65f8104e95c2007a656333f9cccd2f10d310a1"}, + {file = "ddtrace-2.15.0-cp312-cp312-win32.whl", hash = "sha256:d7c48d8532ff54e6ce9dd9ff018390cbca2b8bb17d2c9dc190fafdd397ce5395"}, + {file = "ddtrace-2.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:ad891608cbe28749600ddd279cb48aec8b756a87152405fac7e625e535cf0a53"}, + {file = "ddtrace-2.15.0-cp37-cp37m-macosx_12_0_x86_64.whl", hash = "sha256:5a41317eefd81ba33a779b96841508727791ee70c02d39bdaf90815a4c008c93"}, + {file = "ddtrace-2.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b89cf3b05fd858586651dc9db0037345c82bcd57369259620ea0681c56dcdf2"}, + {file = "ddtrace-2.15.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24091734498774cf733611904d5619c07753c4fcc97e3fd52ff0716b74bc1aeb"}, + {file = "ddtrace-2.15.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ddbae2ebcc54cfbd9c8fa58555e7f74ee290ff2aa4ade3b3832b48e5426402c"}, + {file = "ddtrace-2.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a137e538166c195dd2f2052860c5798c5cfdba87c6113eab8b86d34810a1d938"}, + {file = "ddtrace-2.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:23339bf3f6ba951cbfedbe6b126c66241872d699fc2a34e5e73c5f90f496755d"}, + {file = "ddtrace-2.15.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:15e2a0edb5ca42b56ee1be36183c11148884e97a8dacb1f7fe7dedd3d68fd423"}, + {file = "ddtrace-2.15.0-cp37-cp37m-win32.whl", hash = "sha256:74a0ea0e109171274728a6820b4476fbe33224a6e8e46d600f572fb8fcd93af8"}, + {file = "ddtrace-2.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edf49f1c4dd975cf44e8f6fc33442e78f2c356bdca59edc8df0c0294238dbb9f"}, + {file = "ddtrace-2.15.0-cp38-cp38-macosx_12_0_universal2.whl", hash = "sha256:970271047fccaed427e6b8d23904e530377338de2fdef7e81ce643eae23e022b"}, + {file = "ddtrace-2.15.0-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:656e92c4be00ffffea588541999151131af225aa73c28ce208fb280f2bdcc559"}, + {file = "ddtrace-2.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f665047da8e23b5d94cb7aabdb9176240e2108ac2f0e034677ce81be2372729"}, + {file = "ddtrace-2.15.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a59d17228af3eb1f7f9ef8a08f20f0485628f1b2b9e104811e3182bab982ed9"}, + {file = "ddtrace-2.15.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f4c8271621eeaee5b4f30e8dd03f61de1bbca30cfd0da7ad57dd468ff46bbb6"}, + {file = "ddtrace-2.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:830471742c76fc77412e432c4d396318c0146e7f9dc8cb24a03043cf956bb034"}, + {file = "ddtrace-2.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:db7520b1234fcc78c12323ddb436703100754524607a104459f0063c343418e3"}, + {file = "ddtrace-2.15.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:490e34dd2ff15b08856c9b496cad3ffa0f3a1ad3501c21d0541acd0eb27f6603"}, + {file = "ddtrace-2.15.0-cp38-cp38-win32.whl", hash = "sha256:b0202d9e2ea76d9004dc25f09cc80e861ef2c8ded36179496db5a910be67665f"}, + {file = "ddtrace-2.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:a996c2965f8533596e0c873eba26b68272e494127b5acb07f8040f3a5d906fbe"}, + {file = "ddtrace-2.15.0-cp39-cp39-macosx_12_0_universal2.whl", hash = "sha256:87307d9d55b786c67eebec93274cfeed9326c2608161ad9202dee7da4a6ef9a5"}, + {file = "ddtrace-2.15.0-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:181de5041b0490e70a294f0e6c5014bb9bdba7e31cf031f13f2c21687088a3d0"}, + {file = "ddtrace-2.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8564cbab6571e396d11d7876f34fb99faa5d68ce38774f92825dd1c76001fca"}, + {file = "ddtrace-2.15.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4af2510ce33adf71235c2d80873afa093d1f360976969cdd068c08c86692b253"}, + {file = "ddtrace-2.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:588d5eda7bfa9eb8296af86c089f8b7ec2e4e641e5af1e46d1204115b376d7ee"}, + {file = "ddtrace-2.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0653b483c55cac027e0fe2fd4e0cadcad966bc8b0d3d1a90b0ef820cad8d8d27"}, + {file = "ddtrace-2.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:856222d9237ba6281f39b242e1e840b0434c2008e91c27cb2a7cb3cf0d32fc94"}, + {file = "ddtrace-2.15.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:90da30ee34163fd85a7f021244cd0282905e50d6651a176d4f8a886e2fad5a21"}, + {file = "ddtrace-2.15.0-cp39-cp39-win32.whl", hash = "sha256:38d184fff1fb1d65d61ae7594d364e1acfd57b50fa2e0ce62096959b2c61c316"}, + {file = "ddtrace-2.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:b635d086070fd34548de7bb72f2537243415259db7ed97bbe9f4515172dec0ad"}, + {file = "ddtrace-2.15.0.tar.gz", hash = "sha256:45101c2fa0db8eb67516a66f6cd8ac77a624c3736389d8b75fce0273af4d2e97"}, ] [package.dependencies] @@ -295,13 +310,13 @@ dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] [[package]] name = "envier" -version = "0.5.2" +version = "0.6.1" description = "Python application configuration via the environment" optional = false python-versions = ">=3.7" files = [ - {file = "envier-0.5.2-py3-none-any.whl", hash = "sha256:65099cf3aa9b3b3b4b92db2f7d29e2910672e085b76f7e587d2167561a834add"}, - {file = "envier-0.5.2.tar.gz", hash = "sha256:4e7e398cb09a8dd360508ef7e12511a152355426d2544b8487a34dad27cc20ad"}, + {file = "envier-0.6.1-py3-none-any.whl", hash = "sha256:73609040a76be48bbcb97074d9969666484aa0de706183a6e9ef773156a8a6a9"}, + {file = "envier-0.6.1.tar.gz", hash = "sha256:3309a01bb3d8850c9e7a31a5166d5a836846db2faecb79b9cb32654dd50ca9f9"}, ] [package.extras] @@ -446,22 +461,22 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "protobuf" -version = "5.28.2" +version = "5.28.3" description = "" optional = false python-versions = ">=3.8" files = [ - {file = "protobuf-5.28.2-cp310-abi3-win32.whl", hash = "sha256:eeea10f3dc0ac7e6b4933d32db20662902b4ab81bf28df12218aa389e9c2102d"}, - {file = "protobuf-5.28.2-cp310-abi3-win_amd64.whl", hash = "sha256:2c69461a7fcc8e24be697624c09a839976d82ae75062b11a0972e41fd2cd9132"}, - {file = "protobuf-5.28.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a8b9403fc70764b08d2f593ce44f1d2920c5077bf7d311fefec999f8c40f78b7"}, - {file = "protobuf-5.28.2-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:35cfcb15f213449af7ff6198d6eb5f739c37d7e4f1c09b5d0641babf2cc0c68f"}, - {file = "protobuf-5.28.2-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:5e8a95246d581eef20471b5d5ba010d55f66740942b95ba9b872d918c459452f"}, - {file = "protobuf-5.28.2-cp38-cp38-win32.whl", hash = "sha256:87317e9bcda04a32f2ee82089a204d3a2f0d3c8aeed16568c7daf4756e4f1fe0"}, - {file = "protobuf-5.28.2-cp38-cp38-win_amd64.whl", hash = "sha256:c0ea0123dac3399a2eeb1a1443d82b7afc9ff40241433296769f7da42d142ec3"}, - {file = "protobuf-5.28.2-cp39-cp39-win32.whl", hash = "sha256:ca53faf29896c526863366a52a8f4d88e69cd04ec9571ed6082fa117fac3ab36"}, - {file = "protobuf-5.28.2-cp39-cp39-win_amd64.whl", hash = "sha256:8ddc60bf374785fb7cb12510b267f59067fa10087325b8e1855b898a0d81d276"}, - {file = "protobuf-5.28.2-py3-none-any.whl", hash = "sha256:52235802093bd8a2811abbe8bf0ab9c5f54cca0a751fdd3f6ac2a21438bffece"}, - {file = "protobuf-5.28.2.tar.gz", hash = "sha256:59379674ff119717404f7454647913787034f03fe7049cbef1d74a97bb4593f0"}, + {file = "protobuf-5.28.3-cp310-abi3-win32.whl", hash = "sha256:0c4eec6f987338617072592b97943fdbe30d019c56126493111cf24344c1cc24"}, + {file = "protobuf-5.28.3-cp310-abi3-win_amd64.whl", hash = "sha256:91fba8f445723fcf400fdbe9ca796b19d3b1242cd873907979b9ed71e4afe868"}, + {file = "protobuf-5.28.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a3f6857551e53ce35e60b403b8a27b0295f7d6eb63d10484f12bc6879c715687"}, + {file = "protobuf-5.28.3-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:3fa2de6b8b29d12c61911505d893afe7320ce7ccba4df913e2971461fa36d584"}, + {file = "protobuf-5.28.3-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:712319fbdddb46f21abb66cd33cb9e491a5763b2febd8f228251add221981135"}, + {file = "protobuf-5.28.3-cp38-cp38-win32.whl", hash = "sha256:3e6101d095dfd119513cde7259aa703d16c6bbdfae2554dfe5cfdbe94e32d548"}, + {file = "protobuf-5.28.3-cp38-cp38-win_amd64.whl", hash = "sha256:27b246b3723692bf1068d5734ddaf2fccc2cdd6e0c9b47fe099244d80200593b"}, + {file = "protobuf-5.28.3-cp39-cp39-win32.whl", hash = "sha256:135658402f71bbd49500322c0f736145731b16fc79dc8f367ab544a17eab4535"}, + {file = "protobuf-5.28.3-cp39-cp39-win_amd64.whl", hash = "sha256:70585a70fc2dd4818c51287ceef5bdba6387f88a578c86d47bb34669b5552c36"}, + {file = "protobuf-5.28.3-py3-none-any.whl", hash = "sha256:cee1757663fa32a1ee673434fcf3bf24dd54763c79690201208bafec62f19eed"}, + {file = "protobuf-5.28.3.tar.gz", hash = "sha256:64badbc49180a5e401f373f9ce7ab1d18b63f7dd4a9cdc43c92b9f0b481cef7b"}, ] [[package]] @@ -576,13 +591,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "s3transfer" -version = "0.10.2" +version = "0.10.3" description = "An Amazon S3 Transfer Manager" optional = true python-versions = ">=3.8" files = [ - {file = "s3transfer-0.10.2-py3-none-any.whl", hash = "sha256:eca1c20de70a39daee580aef4986996620f365c4e0fda6a86100231d62f1bf69"}, - {file = "s3transfer-0.10.2.tar.gz", hash = "sha256:0711534e9356d3cc692fdde846b4a1e4b0cb6519971860796e6bc4c7aea00ef6"}, + {file = "s3transfer-0.10.3-py3-none-any.whl", hash = "sha256:263ed587a5803c6c708d3ce44dc4dfedaab4c1a32e8329bab818933d79ddcf5d"}, + {file = "s3transfer-0.10.3.tar.gz", hash = "sha256:4f50ed74ab84d474ce614475e0b8d5047ff080810aac5d01ea25231cfc944b0c"}, ] [package.dependencies] @@ -825,13 +840,13 @@ files = [ [[package]] name = "xmltodict" -version = "0.13.0" +version = "0.14.2" description = "Makes working with XML feel like you are working with JSON" optional = false -python-versions = ">=3.4" +python-versions = ">=3.6" files = [ - {file = "xmltodict-0.13.0-py2.py3-none-any.whl", hash = "sha256:aa89e8fd76320154a40d19a0df04a4695fb9dc5ba977cbb68ab3e4eb225e7852"}, - {file = "xmltodict-0.13.0.tar.gz", hash = "sha256:341595a488e3e01a85a9d8911d8912fd922ede5fecc4dce437eb4b6c8d037e56"}, + {file = "xmltodict-0.14.2-py2.py3-none-any.whl", hash = "sha256:20cc7d723ed729276e808f26fb6b3599f786cbc37e06c65e192ba77c40f20aac"}, + {file = "xmltodict-0.14.2.tar.gz", hash = "sha256:201e7c28bb210e374999d1dde6382923ab0ed1a8a5faeece48ab525b7810a553"}, ] [[package]] @@ -859,4 +874,4 @@ dev = ["boto3", "flake8", "pytest", "pytest-benchmark", "requests"] [metadata] lock-version = "2.0" python-versions = ">=3.8.0,<4" -content-hash = "46554f78374b2b0f1d4ea85f984b2a35ffe481f981c360c2f16d534d6c9eb660" +content-hash = "10fb256b161b7afe015b278c9c937cfbf4f5c53227455ded8251ae62d5f6c587" diff --git a/pyproject.toml b/pyproject.toml index 396b731e..3dab65a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ classifiers = [ python = ">=3.8.0,<4" datadog = ">=0.41.0,<1.0.0" wrapt = "^1.11.2" -ddtrace = ">=2.14.1" +ddtrace = ">=2.15.0" ujson = ">=5.9.0" boto3 = { version = "^1.34.0", optional = true } requests = { version ="^2.22.0", optional = true } diff --git a/tests/Dockerfile b/tests/Dockerfile index 948de1bc..7b96ab89 100644 --- a/tests/Dockerfile +++ b/tests/Dockerfile @@ -3,6 +3,11 @@ FROM python:$python_version ENV PYTHONDONTWRITEBYTECODE True +# Add Rust compiler which is needed to build dd-trace-py from source +RUN curl https://sh.rustup.rs -sSf | \ + sh -s -- --default-toolchain stable -y +ENV PATH=/root/.cargo/bin:$PATH + RUN mkdir -p /test/datadog_lambda WORKDIR /test diff --git a/tests/integration/snapshots/logs/async-metrics_python310.log b/tests/integration/snapshots/logs/async-metrics_python310.log index 40c23c68..b3b94ca4 100644 --- a/tests/integration/snapshots/logs/async-metrics_python310.log +++ b/tests/integration/snapshots/logs/async-metrics_python310.log @@ -279,7 +279,39 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", @@ -942,7 +974,19 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.s3.object", + "ptr.dir": "u", + "ptr.hash": "1dc3e5d00dae48c1f07d95371a747788", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", diff --git a/tests/integration/snapshots/logs/async-metrics_python311.log b/tests/integration/snapshots/logs/async-metrics_python311.log index f1f12db4..5ea440b3 100644 --- a/tests/integration/snapshots/logs/async-metrics_python311.log +++ b/tests/integration/snapshots/logs/async-metrics_python311.log @@ -279,7 +279,39 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", @@ -942,7 +974,19 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.s3.object", + "ptr.dir": "u", + "ptr.hash": "1dc3e5d00dae48c1f07d95371a747788", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", diff --git a/tests/integration/snapshots/logs/async-metrics_python312.log b/tests/integration/snapshots/logs/async-metrics_python312.log index 3bc69cca..ceaaa759 100644 --- a/tests/integration/snapshots/logs/async-metrics_python312.log +++ b/tests/integration/snapshots/logs/async-metrics_python312.log @@ -279,7 +279,39 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", @@ -942,7 +974,19 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.s3.object", + "ptr.dir": "u", + "ptr.hash": "1dc3e5d00dae48c1f07d95371a747788", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", diff --git a/tests/integration/snapshots/logs/async-metrics_python38.log b/tests/integration/snapshots/logs/async-metrics_python38.log index fdc6b192..3ce5c99d 100644 --- a/tests/integration/snapshots/logs/async-metrics_python38.log +++ b/tests/integration/snapshots/logs/async-metrics_python38.log @@ -279,7 +279,39 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", @@ -942,7 +974,19 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.s3.object", + "ptr.dir": "u", + "ptr.hash": "1dc3e5d00dae48c1f07d95371a747788", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", diff --git a/tests/integration/snapshots/logs/async-metrics_python39.log b/tests/integration/snapshots/logs/async-metrics_python39.log index c6c68290..ede453ff 100644 --- a/tests/integration/snapshots/logs/async-metrics_python39.log +++ b/tests/integration/snapshots/logs/async-metrics_python39.log @@ -279,7 +279,39 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", @@ -942,7 +974,19 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.s3.object", + "ptr.dir": "u", + "ptr.hash": "1dc3e5d00dae48c1f07d95371a747788", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", diff --git a/tests/integration/snapshots/logs/sync-metrics_python310.log b/tests/integration/snapshots/logs/sync-metrics_python310.log index 5d9262ce..540ce081 100644 --- a/tests/integration/snapshots/logs/sync-metrics_python310.log +++ b/tests/integration/snapshots/logs/sync-metrics_python310.log @@ -278,7 +278,39 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", @@ -1017,7 +1049,19 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.s3.object", + "ptr.dir": "u", + "ptr.hash": "1dc3e5d00dae48c1f07d95371a747788", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", diff --git a/tests/integration/snapshots/logs/sync-metrics_python311.log b/tests/integration/snapshots/logs/sync-metrics_python311.log index e93a4d0e..68b930db 100644 --- a/tests/integration/snapshots/logs/sync-metrics_python311.log +++ b/tests/integration/snapshots/logs/sync-metrics_python311.log @@ -278,7 +278,39 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", @@ -1017,7 +1049,19 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.s3.object", + "ptr.dir": "u", + "ptr.hash": "1dc3e5d00dae48c1f07d95371a747788", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", diff --git a/tests/integration/snapshots/logs/sync-metrics_python312.log b/tests/integration/snapshots/logs/sync-metrics_python312.log index c912cede..9e4d916e 100644 --- a/tests/integration/snapshots/logs/sync-metrics_python312.log +++ b/tests/integration/snapshots/logs/sync-metrics_python312.log @@ -278,7 +278,39 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", @@ -1017,7 +1049,19 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.s3.object", + "ptr.dir": "u", + "ptr.hash": "1dc3e5d00dae48c1f07d95371a747788", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", diff --git a/tests/integration/snapshots/logs/sync-metrics_python38.log b/tests/integration/snapshots/logs/sync-metrics_python38.log index 74a1e06b..6c7b3c50 100644 --- a/tests/integration/snapshots/logs/sync-metrics_python38.log +++ b/tests/integration/snapshots/logs/sync-metrics_python38.log @@ -278,7 +278,39 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", @@ -1017,7 +1049,19 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.s3.object", + "ptr.dir": "u", + "ptr.hash": "1dc3e5d00dae48c1f07d95371a747788", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", diff --git a/tests/integration/snapshots/logs/sync-metrics_python39.log b/tests/integration/snapshots/logs/sync-metrics_python39.log index 19f0e84c..26db0d4b 100644 --- a/tests/integration/snapshots/logs/sync-metrics_python39.log +++ b/tests/integration/snapshots/logs/sync-metrics_python39.log @@ -278,7 +278,39 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + }, + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.dynamodb.item", + "ptr.dir": "u", + "ptr.hash": "e2af34d333891f765c7f02d2da80895e", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", @@ -1017,7 +1049,19 @@ HTTP GET https://www.datadoghq.com/ Headers: ["Accept-Encoding:gzip, deflate","A "metrics": { "_dd.top_level": 1 }, - "type": "serverless" + "type": "serverless", + "span_links": [ + { + "trace_id": "XXXX", + "span_id": "XXXX", + "attributes": { + "ptr.kind": "aws.s3.object", + "ptr.dir": "u", + "ptr.hash": "1dc3e5d00dae48c1f07d95371a747788", + "link.kind": "span-pointer" + } + } + ] }, { "trace_id": "XXXX", diff --git a/tests/test_span_pointers.py b/tests/test_span_pointers.py index f8181d44..8073a704 100644 --- a/tests/test_span_pointers.py +++ b/tests/test_span_pointers.py @@ -80,6 +80,67 @@ class SpanPointersCase(NamedTuple): }, span_pointers=[], ), + SpanPointersCase( + name="empty dynamodb event", + event_source=_EventSource(EventTypes.DYNAMODB), + event={}, + span_pointers=[], + ), + SpanPointersCase( + name="sensible dynamodb event", + event_source=_EventSource(EventTypes.DYNAMODB), + event={ + "Records": [ + { + "eventSourceARN": "arn:aws:dynamodb:us-west-2:123456789012:table/some-table/stream/2015-06-27T00:48:05.899", + "dynamodb": { + "Keys": { + "some-key": {"S": "some-value"}, + }, + }, + }, + { + "eventSourceARN": "arn:aws:dynamodb:us-west-2:123456789012:table/some-table/stream/2015-06-27T00:48:05.899", + "dynamodb": { + "Keys": { + "some-key": {"S": "some-other-value"}, + }, + }, + }, + ], + }, + span_pointers=[ + _SpanPointerDescription( + pointer_kind="aws.dynamodb.item", + pointer_direction=_SpanPointerDirection.UPSTREAM, + pointer_hash="7f1aee721472bcb48701d45c7c7f7821", + extra_attributes={}, + ), + _SpanPointerDescription( + pointer_kind="aws.dynamodb.item", + pointer_direction=_SpanPointerDirection.UPSTREAM, + pointer_hash="36b820424312a6069bd3f2185f1af584", + extra_attributes={}, + ), + ], + ), + SpanPointersCase( + name="malformed dynamodb event", + event_source=_EventSource(EventTypes.DYNAMODB), + event={ + "Records": [ + { + "eventSourceARN": "arn:aws:dynamodb:us-west-2:123456789012:table/some-table", # missing stream info + "dynamodb": { + "Keys": { + "some-key": {"S": "some-value"}, + }, + }, + }, + ], + }, + span_pointers=[], + ), ], ids=lambda test_case: test_case.name, ) From 6f54a00563ef6855b2950d8cdafbfdc178ec948c Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Wed, 30 Oct 2024 15:09:39 -0400 Subject: [PATCH 08/24] trigger ci From 25780a84a1f4cb611345a7a52705e3a9d3497ff5 Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Mon, 4 Nov 2024 16:28:11 -0500 Subject: [PATCH 09/24] use default propagator.extract --- datadog_lambda/tracing.py | 17 +++++++++++------ tests/test_tracing.py | 24 +++++++++++++----------- tests/test_xray.py | 12 ++++++------ 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index dce27f7c..4ed391d7 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -383,22 +383,27 @@ def extract_context_from_step_functions(event, lambda_context): state_entered_time = event.get("State").get("EnteredTime") meta = {} + trace_id = None if "_datadog" in event: trace_header = event.get("_datadog") - if TraceHeader.TRACE_ID in trace_header: - # use the trace ID from the top-most parent when it exists - trace_id = int(trace_header.get(TraceHeader.TRACE_ID)) + explicit_context = propagator.extract(trace_header) + if _is_context_complete(explicit_context): tags = trace_header.get(TraceHeader.TAGS, "") for tag in tags.split(","): tag_key, tag_val = tag.split("=") meta[tag_key] = tag_val - elif "x-datadog-execution-arn" in trace_header: - root_execution_id = trace_header.get("x-datadog-execution-arn") + explicit_context.span_id = _deterministic_sha256_hash( + f"{execution_id}#{state_name}#{state_entered_time}", HIGHER_64_BITS + ) + return explicit_context + if "x-datadog-execution-arn" in trace_header: + root_execution_id = trace_header.get("x-datadog-root-execution-arn") trace_id = _deterministic_sha256_hash(root_execution_id, LOWER_64_BITS) meta["_dd.p.tid"] = hex( _deterministic_sha256_hash(root_execution_id, HIGHER_64_BITS) )[2:] - else: + + if not trace_id: # returning 128 bits since 128bit traceId will be break up into # traditional traceId and _dd.p.tid tag # https://github.com/DataDog/dd-trace-py/blob/3e34d21cb9b5e1916e549047158cb119317b96ab/ddtrace/propagation/http.py#L232-L240 diff --git a/tests/test_tracing.py b/tests/test_tracing.py index c0307b52..e3970581 100644 --- a/tests/test_tracing.py +++ b/tests/test_tracing.py @@ -664,26 +664,28 @@ def test_step_function_trace_data_with_trace_header(self): "EnteredTime": "Mon Nov 13 12:43:33 PST 2023", }, "_datadog": { - "x-datadog-trace-id": "4061173386180447114", - "x-datadog-tags": "_dd.p.tid=aac3639aa724716", + "x-datadog-trace-id": "11742251842529032210", + "x-datadog-parent-id": "13977111940858727778", + "x-datadog-sampling-priority": "1", + "x-datadog-tags": "_dd.p.dm=-0,_dd.p.tid=6728f8ec00000000" }, } ctx, source, event_source = extract_dd_trace_context(sf_event, lambda_ctx) self.assertEqual(source, "event") expected_context = Context( - trace_id=4061173386180447114, + trace_id=137123224175615787006624409899264538642, span_id=6880978411788117524, sampling_priority=1, - meta={"_dd.p.tid": "aac3639aa724716"}, + meta={'_dd.p.dm': '-0', "_dd.p.tid": "6728f8ec00000000"}, ) self.assertEqual(ctx, expected_context) self.assertEqual( get_dd_trace_context(), { - TraceHeader.TRACE_ID: "4061173386180447114", + TraceHeader.TRACE_ID: "11742251842529032210", TraceHeader.PARENT_ID: "10713633173203262661", TraceHeader.SAMPLING_PRIORITY: "1", - TraceHeader.TAGS: "_dd.p.tid=aac3639aa724716", + TraceHeader.TAGS: "_dd.p.dm=-0,_dd.p.tid=6728f8ec00000000", }, ) create_dd_dummy_metadata_subsegment(ctx, XraySubsegment.TRACE_KEY) @@ -705,25 +707,25 @@ def test_step_function_trace_data_with_arn_header(self): "EnteredTime": "Mon Nov 13 12:43:33 PST 2023", }, "_datadog": { - "x-datadog-execution-arn": "ca7383bc-e370-4a85-a266-a4686bd7d00f" + "x-datadog-root-execution-arn": "ca7383bc-e370-4a85-a266-a4686bd7d00f" }, } ctx, source, event_source = extract_dd_trace_context(sf_event, lambda_ctx) self.assertEqual(source, "event") expected_context = Context( - trace_id=6970872619724504833, + trace_id=3675572987363469717, span_id=6880978411788117524, sampling_priority=1, - meta={"_dd.p.tid": "71dab8f4d4629263"}, + meta={"_dd.p.tid": "e987c84b36b11ab"}, ) self.assertEqual(ctx, expected_context) self.assertEqual( get_dd_trace_context(), { - TraceHeader.TRACE_ID: "6970872619724504833", + TraceHeader.TRACE_ID: "3675572987363469717", TraceHeader.PARENT_ID: "10713633173203262661", TraceHeader.SAMPLING_PRIORITY: "1", - TraceHeader.TAGS: "_dd.p.tid=71dab8f4d4629263", + TraceHeader.TAGS: "_dd.p.tid=e987c84b36b11ab", }, ) create_dd_dummy_metadata_subsegment(ctx, XraySubsegment.TRACE_KEY) diff --git a/tests/test_xray.py b/tests/test_xray.py index 7f33f891..8177e46e 100644 --- a/tests/test_xray.py +++ b/tests/test_xray.py @@ -34,9 +34,9 @@ def test_get_xray_host_port_success(self): def test_send_segment_sampled_out(self): os.environ["AWS_XRAY_DAEMON_ADDRESS"] = "fake-agent.com:8080" - os.environ[ - "_X_AMZN_TRACE_ID" - ] = "Root=1-5e272390-8c398be037738dc042009320;Parent=94ae789b969f1cc5;Sampled=0;Lineage=c6c5b1b9:0" + os.environ["_X_AMZN_TRACE_ID"] = ( + "Root=1-5e272390-8c398be037738dc042009320;Parent=94ae789b969f1cc5;Sampled=0;Lineage=c6c5b1b9:0" + ) with patch( "datadog_lambda.xray.sock.send", MagicMock(return_value=None) @@ -47,9 +47,9 @@ def test_send_segment_sampled_out(self): def test_send_segment_sampled(self): os.environ["AWS_XRAY_DAEMON_ADDRESS"] = "fake-agent.com:8080" - os.environ[ - "_X_AMZN_TRACE_ID" - ] = "Root=1-5e272390-8c398be037738dc042009320;Parent=94ae789b969f1cc5;Sampled=1;Lineage=c6c5b1b9:0" + os.environ["_X_AMZN_TRACE_ID"] = ( + "Root=1-5e272390-8c398be037738dc042009320;Parent=94ae789b969f1cc5;Sampled=1;Lineage=c6c5b1b9:0" + ) with patch( "datadog_lambda.xray.sock.send", MagicMock(return_value=None) ) as mock_send: From 85a157fa1c40a7a0491541ed91f319f190a7a957 Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Mon, 4 Nov 2024 17:03:44 -0500 Subject: [PATCH 10/24] lint --- tests/test_tracing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_tracing.py b/tests/test_tracing.py index e3970581..be93ec6b 100644 --- a/tests/test_tracing.py +++ b/tests/test_tracing.py @@ -667,7 +667,7 @@ def test_step_function_trace_data_with_trace_header(self): "x-datadog-trace-id": "11742251842529032210", "x-datadog-parent-id": "13977111940858727778", "x-datadog-sampling-priority": "1", - "x-datadog-tags": "_dd.p.dm=-0,_dd.p.tid=6728f8ec00000000" + "x-datadog-tags": "_dd.p.dm=-0,_dd.p.tid=6728f8ec00000000", }, } ctx, source, event_source = extract_dd_trace_context(sf_event, lambda_ctx) @@ -676,7 +676,7 @@ def test_step_function_trace_data_with_trace_header(self): trace_id=137123224175615787006624409899264538642, span_id=6880978411788117524, sampling_priority=1, - meta={'_dd.p.dm': '-0', "_dd.p.tid": "6728f8ec00000000"}, + meta={"_dd.p.dm": "-0", "_dd.p.tid": "6728f8ec00000000"}, ) self.assertEqual(ctx, expected_context) self.assertEqual( From aad3cd802e37f3dbc93a2356f4711b519788a332 Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Mon, 4 Nov 2024 17:06:42 -0500 Subject: [PATCH 11/24] lint --- tests/test_xray.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test_xray.py b/tests/test_xray.py index 8177e46e..7f33f891 100644 --- a/tests/test_xray.py +++ b/tests/test_xray.py @@ -34,9 +34,9 @@ def test_get_xray_host_port_success(self): def test_send_segment_sampled_out(self): os.environ["AWS_XRAY_DAEMON_ADDRESS"] = "fake-agent.com:8080" - os.environ["_X_AMZN_TRACE_ID"] = ( - "Root=1-5e272390-8c398be037738dc042009320;Parent=94ae789b969f1cc5;Sampled=0;Lineage=c6c5b1b9:0" - ) + os.environ[ + "_X_AMZN_TRACE_ID" + ] = "Root=1-5e272390-8c398be037738dc042009320;Parent=94ae789b969f1cc5;Sampled=0;Lineage=c6c5b1b9:0" with patch( "datadog_lambda.xray.sock.send", MagicMock(return_value=None) @@ -47,9 +47,9 @@ def test_send_segment_sampled_out(self): def test_send_segment_sampled(self): os.environ["AWS_XRAY_DAEMON_ADDRESS"] = "fake-agent.com:8080" - os.environ["_X_AMZN_TRACE_ID"] = ( - "Root=1-5e272390-8c398be037738dc042009320;Parent=94ae789b969f1cc5;Sampled=1;Lineage=c6c5b1b9:0" - ) + os.environ[ + "_X_AMZN_TRACE_ID" + ] = "Root=1-5e272390-8c398be037738dc042009320;Parent=94ae789b969f1cc5;Sampled=1;Lineage=c6c5b1b9:0" with patch( "datadog_lambda.xray.sock.send", MagicMock(return_value=None) ) as mock_send: From c3681de3c904e6915500e3ff635f0317a78a4b12 Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Wed, 6 Nov 2024 11:33:12 -0500 Subject: [PATCH 12/24] updated to use trace/parent hash from _datadog --- datadog_lambda/tracing.py | 51 +++++++++++++++-------------- datadog_lambda/trigger.py | 4 ++- tests/test_tracing.py | 69 ++++++++++++++++----------------------- 3 files changed, 59 insertions(+), 65 deletions(-) diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index 4ed391d7..2e056733 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -358,8 +358,10 @@ def extract_context_from_kinesis_event(event, lambda_context): def _deterministic_sha256_hash(s: str, part: str) -> (int, int): - sha256_hash = hashlib.sha256(s.encode()).hexdigest() + return _sha256_to_binary_part(hashlib.sha256(s.encode()).hexdigest(), part) + +def _sha256_to_binary_part(sha256_hash: str, part: str) -> (int, int): # First two chars is '0b'. zfill to ensure 256 bits, but we only care about the first 128 bits binary_hash = bin(int(sha256_hash, 16))[2:].zfill(256) if part == HIGHER_64_BITS: @@ -378,32 +380,33 @@ def extract_context_from_step_functions(event, lambda_context): into lambda's event dict. """ try: - execution_id = event.get("Execution").get("Id") - state_name = event.get("State").get("Name") - state_entered_time = event.get("State").get("EnteredTime") meta = {} - trace_id = None if "_datadog" in event: - trace_header = event.get("_datadog") - explicit_context = propagator.extract(trace_header) - if _is_context_complete(explicit_context): - tags = trace_header.get(TraceHeader.TAGS, "") - for tag in tags.split(","): - tag_key, tag_val = tag.split("=") - meta[tag_key] = tag_val - explicit_context.span_id = _deterministic_sha256_hash( - f"{execution_id}#{state_name}#{state_entered_time}", HIGHER_64_BITS + dd_data = event.get("_datadog") + parent_id = _sha256_to_binary_part( + dd_data.get("x-datadog-parent-id-hash"), HIGHER_64_BITS + ) + if "x-datadog-trace-id" in dd_data: # lambda root + dd_data["x-datadog-parent-id"] = str(parent_id) + explicit_context = propagator.extract(dd_data) + if _is_context_complete(explicit_context): + return explicit_context + else: + return None + else: # sfn root + trace_id = _sha256_to_binary_part( + dd_data.get("x-datadog-trace-id-hash"), LOWER_64_BITS ) - return explicit_context - if "x-datadog-execution-arn" in trace_header: - root_execution_id = trace_header.get("x-datadog-root-execution-arn") - trace_id = _deterministic_sha256_hash(root_execution_id, LOWER_64_BITS) meta["_dd.p.tid"] = hex( - _deterministic_sha256_hash(root_execution_id, HIGHER_64_BITS) + _sha256_to_binary_part( + dd_data.get("x-datadog-trace-id-hash"), HIGHER_64_BITS + ) )[2:] - - if not trace_id: + else: + execution_id = event.get("Execution").get("Id") + state_name = event.get("State").get("Name") + state_entered_time = event.get("State").get("EnteredTime") # returning 128 bits since 128bit traceId will be break up into # traditional traceId and _dd.p.tid tag # https://github.com/DataDog/dd-trace-py/blob/3e34d21cb9b5e1916e549047158cb119317b96ab/ddtrace/propagation/http.py#L232-L240 @@ -414,9 +417,9 @@ def extract_context_from_step_functions(event, lambda_context): _deterministic_sha256_hash(execution_id, HIGHER_64_BITS) )[2:] - parent_id = _deterministic_sha256_hash( - f"{execution_id}#{state_name}#{state_entered_time}", HIGHER_64_BITS - ) + parent_id = _deterministic_sha256_hash( + f"{execution_id}#{state_name}#{state_entered_time}", HIGHER_64_BITS + ) sampling_priority = SamplingPriority.AUTO_KEEP return Context( diff --git a/datadog_lambda/trigger.py b/datadog_lambda/trigger.py index 64eff1a0..18b8dfb1 100644 --- a/datadog_lambda/trigger.py +++ b/datadog_lambda/trigger.py @@ -146,7 +146,9 @@ def parse_event_source(event: dict) -> _EventSource: if event.get("source") == "aws.events" or has_event_categories: event_source = _EventSource(EventTypes.CLOUDWATCH_EVENTS) - if "Execution" in event and "StateMachine" in event and "State" in event: + if ( + "_datadog" in event and event.get("_datadog").get("serverless-version") == "v2" + ) or ("Execution" in event and "StateMachine" in event and "State" in event): event_source = _EventSource(EventTypes.STEPFUNCTIONS) event_record = get_first_record(event) diff --git a/tests/test_tracing.py b/tests/test_tracing.py index be93ec6b..6fecc28f 100644 --- a/tests/test_tracing.py +++ b/tests/test_tracing.py @@ -617,7 +617,7 @@ def test_with_complete_datadog_trace_headers_with_trigger_tags(self): @with_trace_propagation_style("datadog") def test_step_function_trace_data(self): lambda_ctx = get_mock_context() - sf_event = { + sfn_event = { "Execution": { "Id": "665c417c-1237-4742-aaca-8b3becbb9e75", }, @@ -627,7 +627,7 @@ def test_step_function_trace_data(self): "EnteredTime": "Mon Nov 13 12:43:33 PST 2023", }, } - ctx, source, event_source = extract_dd_trace_context(sf_event, lambda_ctx) + ctx, source, event_source = extract_dd_trace_context(sfn_event, lambda_ctx) self.assertEqual(source, "event") expected_context = Context( trace_id=3675572987363469717, @@ -652,40 +652,35 @@ def test_step_function_trace_data(self): ) @with_trace_propagation_style("datadog") - def test_step_function_trace_data_with_trace_header(self): + def test_step_function_trace_data_lambda_root(self): lambda_ctx = get_mock_context() - sf_event = { - "Execution": { - "Id": "665c417c-1237-4742-aaca-8b3becbb9e75", - }, - "StateMachine": {}, - "State": { - "Name": "my-awesome-state", - "EnteredTime": "Mon Nov 13 12:43:33 PST 2023", - }, + sfn_event = { "_datadog": { - "x-datadog-trace-id": "11742251842529032210", - "x-datadog-parent-id": "13977111940858727778", + "x-datadog-trace-id": "5821803790426892636", "x-datadog-sampling-priority": "1", - "x-datadog-tags": "_dd.p.dm=-0,_dd.p.tid=6728f8ec00000000", - }, + "x-datadog-tags": "_dd.p.dm=-0,_dd.p.tid=672a7cb100000000", + "traceparent": "00-672a7cb10000000050cb33b3c06ae95c-5fda9d8d1d1373f9-01", + "tracestate": "dd=p:5fda9d8d1d1373f9;s:1;t.dm:-0;t.tid:672a7cb100000000", + "x-datadog-parent-id-hash": "a926584eba705d6ec904c54db2ecc4d4a2c91e7dabe7ce87ac26edb43388fbc5", + "serverless-version": "v2", + } } - ctx, source, event_source = extract_dd_trace_context(sf_event, lambda_ctx) + ctx, source, event_source = extract_dd_trace_context(sfn_event, lambda_ctx) self.assertEqual(source, "event") expected_context = Context( - trace_id=137123224175615787006624409899264538642, - span_id=6880978411788117524, + trace_id=137131089076080415507232535361568303452, + span_id=2965154499828669806, sampling_priority=1, - meta={"_dd.p.dm": "-0", "_dd.p.tid": "6728f8ec00000000"}, + meta={"_dd.p.dm": "-0", "_dd.p.tid": "672a7cb100000000"}, ) self.assertEqual(ctx, expected_context) self.assertEqual( get_dd_trace_context(), { - TraceHeader.TRACE_ID: "11742251842529032210", + TraceHeader.TRACE_ID: "5821803790426892636", TraceHeader.PARENT_ID: "10713633173203262661", TraceHeader.SAMPLING_PRIORITY: "1", - TraceHeader.TAGS: "_dd.p.dm=-0,_dd.p.tid=6728f8ec00000000", + TraceHeader.TAGS: "_dd.p.dm=-0,_dd.p.tid=672a7cb100000000", }, ) create_dd_dummy_metadata_subsegment(ctx, XraySubsegment.TRACE_KEY) @@ -695,37 +690,31 @@ def test_step_function_trace_data_with_trace_header(self): ) @with_trace_propagation_style("datadog") - def test_step_function_trace_data_with_arn_header(self): + def test_step_function_trace_data_sfn_root(self): lambda_ctx = get_mock_context() - sf_event = { - "Execution": { - "Id": "665c417c-1237-4742-aaca-8b3becbb9e75", - }, - "StateMachine": {}, - "State": { - "Name": "my-awesome-state", - "EnteredTime": "Mon Nov 13 12:43:33 PST 2023", - }, + sfn_event = { "_datadog": { - "x-datadog-root-execution-arn": "ca7383bc-e370-4a85-a266-a4686bd7d00f" - }, + "x-datadog-trace-id-hash": "fed93f8c162880cb9aa90fcd1f8395383835841d5470d30215f3dd52906ebc58", + "x-datadog-parent-id-hash": "c5eb94cc9220ab5783e1db53debd54b8c93f6f2a3eae1c680d7b849f2d34e551", + "serverless-version": "v2" + } } - ctx, source, event_source = extract_dd_trace_context(sf_event, lambda_ctx) + ctx, source, event_source = extract_dd_trace_context(sfn_event, lambda_ctx) self.assertEqual(source, "event") expected_context = Context( - trace_id=3675572987363469717, - span_id=6880978411788117524, + trace_id=1921084089721656632, + span_id=5038284214489885527, sampling_priority=1, - meta={"_dd.p.tid": "e987c84b36b11ab"}, + meta={"_dd.p.tid": "7ed93f8c162880cb"}, ) self.assertEqual(ctx, expected_context) self.assertEqual( get_dd_trace_context(), { - TraceHeader.TRACE_ID: "3675572987363469717", + TraceHeader.TRACE_ID: "1921084089721656632", TraceHeader.PARENT_ID: "10713633173203262661", TraceHeader.SAMPLING_PRIORITY: "1", - TraceHeader.TAGS: "_dd.p.tid=e987c84b36b11ab", + TraceHeader.TAGS: "_dd.p.tid=7ed93f8c162880cb", }, ) create_dd_dummy_metadata_subsegment(ctx, XraySubsegment.TRACE_KEY) From 7d1d4752790ed5dfa6e9ed624f50be7268d7035f Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Wed, 6 Nov 2024 12:31:49 -0500 Subject: [PATCH 13/24] lint --- tests/test_tracing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tracing.py b/tests/test_tracing.py index 6fecc28f..b6a1cf55 100644 --- a/tests/test_tracing.py +++ b/tests/test_tracing.py @@ -696,7 +696,7 @@ def test_step_function_trace_data_sfn_root(self): "_datadog": { "x-datadog-trace-id-hash": "fed93f8c162880cb9aa90fcd1f8395383835841d5470d30215f3dd52906ebc58", "x-datadog-parent-id-hash": "c5eb94cc9220ab5783e1db53debd54b8c93f6f2a3eae1c680d7b849f2d34e551", - "serverless-version": "v2" + "serverless-version": "v2", } } ctx, source, event_source = extract_dd_trace_context(sfn_event, lambda_ctx) From e9a7d46d03f9a4cae32877c343c237901e46a4b7 Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Wed, 6 Nov 2024 12:35:33 -0500 Subject: [PATCH 14/24] skip is context complete check --- datadog_lambda/tracing.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index 2e056733..942b0768 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -389,11 +389,7 @@ def extract_context_from_step_functions(event, lambda_context): ) if "x-datadog-trace-id" in dd_data: # lambda root dd_data["x-datadog-parent-id"] = str(parent_id) - explicit_context = propagator.extract(dd_data) - if _is_context_complete(explicit_context): - return explicit_context - else: - return None + return propagator.extract(dd_data) else: # sfn root trace_id = _sha256_to_binary_part( dd_data.get("x-datadog-trace-id-hash"), LOWER_64_BITS From a6464b4eb88b21186bc64039a2842e6539412f92 Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Wed, 6 Nov 2024 12:40:36 -0500 Subject: [PATCH 15/24] remove unused import --- datadog_lambda/tracing.py | 1 - 1 file changed, 1 deletion(-) diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index 942b0768..23e9dc81 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -24,7 +24,6 @@ TraceContextSource, XrayDaemon, Headers, - TraceHeader, ) from datadog_lambda.xray import ( send_segment, From 068c2fc707fffe64f0663089d93782ae34fda5db Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Mon, 11 Nov 2024 11:23:38 -0500 Subject: [PATCH 16/24] fix legacy lambda parsing with new header --- datadog_lambda/tracing.py | 10 ++++++++-- tests/test_tracing.py | 11 +++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index 23e9dc81..950c4401 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -432,8 +432,13 @@ def is_legacy_lambda_step_function(event): """ Check if the event is a step function that called a legacy lambda """ - event = event.get("Payload", {}) - return "Execution" in event and "StateMachine" in event and "State" in event + if not isinstance(event, dict) or "Payload" not in event: + return False + + event = event.get("Payload") + return "_datadog" in event or ( + "Execution" in event and "StateMachine" in event and "State" in event + ) def extract_context_custom_extractor(extractor, event, lambda_context): @@ -688,6 +693,7 @@ def create_inferred_span( event_source: _EventSource = None, decode_authorizer_context: bool = True, ): + logger.debug("abhinav event %s", event) if event_source is None: event_source = parse_event_source(event) try: diff --git a/tests/test_tracing.py b/tests/test_tracing.py index b6a1cf55..d2060ef2 100644 --- a/tests/test_tracing.py +++ b/tests/test_tracing.py @@ -738,6 +738,17 @@ def test_is_legacy_lambda_step_function(self): } self.assertTrue(is_legacy_lambda_step_function(sf_event)) + sf_event = { + "Payload": { + "_datadog": { + "x-datadog-trace-id-hash": "fed93f8c162880cb9aa90fcd1f8395383835841d5470d30215f3dd52906ebc58", + "x-datadog-parent-id-hash": "c5eb94cc9220ab5783e1db53debd54b8c93f6f2a3eae1c680d7b849f2d34e551", + "serverless-version": "v2", + } + } + } + self.assertTrue(is_legacy_lambda_step_function(sf_event)) + sf_event = { "Execution": { "Id": "665c417c-1237-4742-aaca-8b3becbb9e75", From 00850d8ac3fd3e73011bd3531c10b1630ab99063 Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Tue, 12 Nov 2024 10:15:13 -0500 Subject: [PATCH 17/24] using context object instead of pre-hashed values --- datadog_lambda/tracing.py | 58 +++++++++++++++++++++++++-------------- tests/test_tracing.py | 38 +++++++++++++++++-------- 2 files changed, 63 insertions(+), 33 deletions(-) diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index 950c4401..82657309 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -356,11 +356,8 @@ def extract_context_from_kinesis_event(event, lambda_context): return extract_context_from_lambda_context(lambda_context) -def _deterministic_sha256_hash(s: str, part: str) -> (int, int): - return _sha256_to_binary_part(hashlib.sha256(s.encode()).hexdigest(), part) - - -def _sha256_to_binary_part(sha256_hash: str, part: str) -> (int, int): +def _deterministic_sha256_hash(s: str, part: str) -> int: + sha256_hash = hashlib.sha256(s.encode()).hexdigest() # First two chars is '0b'. zfill to ensure 256 bits, but we only care about the first 128 bits binary_hash = bin(int(sha256_hash, 16))[2:].zfill(256) if part == HIGHER_64_BITS: @@ -373,35 +370,56 @@ def _sha256_to_binary_part(sha256_hash: str, part: str) -> (int, int): return result +def _parse_high_64_bits(trace_tags: str) -> str: + # todo: testme + if trace_tags: + for tag in trace_tags.split(","): + if "_dd.p.tid=" in tag: + return tag.split("=")[1] + + return "" + + +def _sfn_context_to_parent_id(context: dict) -> int: + # todo: testme + execution_id = context.get("Execution").get("Id") + state_name = context.get("State").get("Name") + state_entered_time = context.get("State").get("EnteredTime") + + return _deterministic_sha256_hash( + f"{execution_id}#{state_name}#{state_entered_time}", HIGHER_64_BITS + ) + + def extract_context_from_step_functions(event, lambda_context): """ Only extract datadog trace context when Step Functions Context Object is injected into lambda's event dict. """ + # todo: update docstring try: meta = {} + dd_data = event.get("_datadog") - if "_datadog" in event: - dd_data = event.get("_datadog") - parent_id = _sha256_to_binary_part( - dd_data.get("x-datadog-parent-id-hash"), HIGHER_64_BITS - ) + if dd_data and dd_data.get("serverless-version") == "v2": if "x-datadog-trace-id" in dd_data: # lambda root - dd_data["x-datadog-parent-id"] = str(parent_id) - return propagator.extract(dd_data) + trace_id = dd_data.get("x-datadog-trace-id") + high_64_bit_trace_id = _parse_high_64_bits(dd_data.get("x-datadog-tags")) + if high_64_bit_trace_id: + meta["_dd.p.tid"] = high_64_bit_trace_id else: # sfn root - trace_id = _sha256_to_binary_part( - dd_data.get("x-datadog-trace-id-hash"), LOWER_64_BITS + trace_id = _deterministic_sha256_hash( + dd_data.get("RootExecutionId"), LOWER_64_BITS ) meta["_dd.p.tid"] = hex( - _sha256_to_binary_part( - dd_data.get("x-datadog-trace-id-hash"), HIGHER_64_BITS + _deterministic_sha256_hash( + dd_data.get("RootExecutionId"), HIGHER_64_BITS ) )[2:] + + parent_id = _sfn_context_to_parent_id(dd_data) else: execution_id = event.get("Execution").get("Id") - state_name = event.get("State").get("Name") - state_entered_time = event.get("State").get("EnteredTime") # returning 128 bits since 128bit traceId will be break up into # traditional traceId and _dd.p.tid tag # https://github.com/DataDog/dd-trace-py/blob/3e34d21cb9b5e1916e549047158cb119317b96ab/ddtrace/propagation/http.py#L232-L240 @@ -412,9 +430,7 @@ def extract_context_from_step_functions(event, lambda_context): _deterministic_sha256_hash(execution_id, HIGHER_64_BITS) )[2:] - parent_id = _deterministic_sha256_hash( - f"{execution_id}#{state_name}#{state_entered_time}", HIGHER_64_BITS - ) + parent_id = _sfn_context_to_parent_id(event) sampling_priority = SamplingPriority.AUTO_KEEP return Context( diff --git a/tests/test_tracing.py b/tests/test_tracing.py index d2060ef2..74c56814 100644 --- a/tests/test_tracing.py +++ b/tests/test_tracing.py @@ -656,22 +656,29 @@ def test_step_function_trace_data_lambda_root(self): lambda_ctx = get_mock_context() sfn_event = { "_datadog": { + "Execution": { + "Id": "665c417c-1237-4742-aaca-8b3becbb9e75", + }, + "StateMachine": {}, + "State": { + "Name": "my-awesome-state", + "EnteredTime": "Mon Nov 13 12:43:33 PST 2023", + }, "x-datadog-trace-id": "5821803790426892636", "x-datadog-sampling-priority": "1", "x-datadog-tags": "_dd.p.dm=-0,_dd.p.tid=672a7cb100000000", "traceparent": "00-672a7cb10000000050cb33b3c06ae95c-5fda9d8d1d1373f9-01", "tracestate": "dd=p:5fda9d8d1d1373f9;s:1;t.dm:-0;t.tid:672a7cb100000000", - "x-datadog-parent-id-hash": "a926584eba705d6ec904c54db2ecc4d4a2c91e7dabe7ce87ac26edb43388fbc5", "serverless-version": "v2", } } ctx, source, event_source = extract_dd_trace_context(sfn_event, lambda_ctx) self.assertEqual(source, "event") expected_context = Context( - trace_id=137131089076080415507232535361568303452, - span_id=2965154499828669806, + trace_id=5821803790426892636, + span_id=6880978411788117524, sampling_priority=1, - meta={"_dd.p.dm": "-0", "_dd.p.tid": "672a7cb100000000"}, + meta={"_dd.p.tid": "672a7cb100000000"}, ) self.assertEqual(ctx, expected_context) self.assertEqual( @@ -680,7 +687,7 @@ def test_step_function_trace_data_lambda_root(self): TraceHeader.TRACE_ID: "5821803790426892636", TraceHeader.PARENT_ID: "10713633173203262661", TraceHeader.SAMPLING_PRIORITY: "1", - TraceHeader.TAGS: "_dd.p.dm=-0,_dd.p.tid=672a7cb100000000", + TraceHeader.TAGS: "_dd.p.tid=672a7cb100000000", }, ) create_dd_dummy_metadata_subsegment(ctx, XraySubsegment.TRACE_KEY) @@ -694,27 +701,34 @@ def test_step_function_trace_data_sfn_root(self): lambda_ctx = get_mock_context() sfn_event = { "_datadog": { - "x-datadog-trace-id-hash": "fed93f8c162880cb9aa90fcd1f8395383835841d5470d30215f3dd52906ebc58", - "x-datadog-parent-id-hash": "c5eb94cc9220ab5783e1db53debd54b8c93f6f2a3eae1c680d7b849f2d34e551", + "Execution": { + "Id": "665c417c-1237-4742-aaca-8b3becbb9e75", + }, + "StateMachine": {}, + "State": { + "Name": "my-awesome-state", + "EnteredTime": "Mon Nov 13 12:43:33 PST 2023", + }, + "RootExecutionId": "4875aba4-ae31-4a4c-bf8a-63e9eee31dad", "serverless-version": "v2", } } ctx, source, event_source = extract_dd_trace_context(sfn_event, lambda_ctx) self.assertEqual(source, "event") expected_context = Context( - trace_id=1921084089721656632, - span_id=5038284214489885527, + trace_id=4521899030418994483, + span_id=6880978411788117524, sampling_priority=1, - meta={"_dd.p.tid": "7ed93f8c162880cb"}, + meta={"_dd.p.tid": "12d1270d99cc5e03"}, ) self.assertEqual(ctx, expected_context) self.assertEqual( get_dd_trace_context(), { - TraceHeader.TRACE_ID: "1921084089721656632", + TraceHeader.TRACE_ID: "4521899030418994483", TraceHeader.PARENT_ID: "10713633173203262661", TraceHeader.SAMPLING_PRIORITY: "1", - TraceHeader.TAGS: "_dd.p.tid=7ed93f8c162880cb", + TraceHeader.TAGS: "_dd.p.tid=12d1270d99cc5e03", }, ) create_dd_dummy_metadata_subsegment(ctx, XraySubsegment.TRACE_KEY) From 832ae1bf0babd753cfe129fa7bff1192f2e44cf9 Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Tue, 12 Nov 2024 11:58:13 -0500 Subject: [PATCH 18/24] fixed trigger tags and tests --- datadog_lambda/tracing.py | 7 ++++--- datadog_lambda/trigger.py | 8 ++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index 82657309..0c7cf75c 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -403,8 +403,10 @@ def extract_context_from_step_functions(event, lambda_context): if dd_data and dd_data.get("serverless-version") == "v2": if "x-datadog-trace-id" in dd_data: # lambda root - trace_id = dd_data.get("x-datadog-trace-id") - high_64_bit_trace_id = _parse_high_64_bits(dd_data.get("x-datadog-tags")) + trace_id = int(dd_data.get("x-datadog-trace-id")) + high_64_bit_trace_id = _parse_high_64_bits( + dd_data.get("x-datadog-tags") + ) if high_64_bit_trace_id: meta["_dd.p.tid"] = high_64_bit_trace_id else: # sfn root @@ -709,7 +711,6 @@ def create_inferred_span( event_source: _EventSource = None, decode_authorizer_context: bool = True, ): - logger.debug("abhinav event %s", event) if event_source is None: event_source = parse_event_source(event) try: diff --git a/datadog_lambda/trigger.py b/datadog_lambda/trigger.py index 18b8dfb1..7210bb5b 100644 --- a/datadog_lambda/trigger.py +++ b/datadog_lambda/trigger.py @@ -256,6 +256,14 @@ def parse_event_source_arn(source: _EventSource, event: dict, context: Any) -> s if source.event_type == EventTypes.CLOUDWATCH_EVENTS and event.get("resources"): return event.get("resources")[0] + # todo: testme + # e.g. arn:aws:states:us-east-1:123456789012:stateMachine:stateMachineName + if source.event_type == EventTypes.STEPFUNCTIONS: + context = event + if "_datadog" in event: + context = event.get("_datadog") + return context.get("StateMachine").get("Id") + def get_event_source_arn(source: _EventSource, event: dict, context: Any) -> str: event_source_arn = event.get("eventSourceARN") or event.get("eventSourceArn") From e2e732bba5b9b9be02d8e0d46959c7e1d1f20371 Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Wed, 13 Nov 2024 15:01:38 -0500 Subject: [PATCH 19/24] pull sfn trace id generation out into a helper --- datadog_lambda/tracing.py | 48 ++++++++++++++++++++------------------- tests/test_tracing.py | 44 ----------------------------------- 2 files changed, 25 insertions(+), 67 deletions(-) diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index 0c7cf75c..919a19a8 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -380,8 +380,8 @@ def _parse_high_64_bits(trace_tags: str) -> str: return "" -def _sfn_context_to_parent_id(context: dict) -> int: - # todo: testme +# todo: testme +def _generate_sfn_parent_id(context: dict) -> int: execution_id = context.get("Execution").get("Id") state_name = context.get("State").get("Name") state_entered_time = context.get("State").get("EnteredTime") @@ -391,6 +391,18 @@ def _sfn_context_to_parent_id(context: dict) -> int: ) +# take the higher 64 bits as _dd.p.tid tag and use hex to encode +# [2:] to remove '0x' in the hex str +# todo testme +# returning 128 bits since 128bit traceId will be break up into +# traditional traceId and _dd.p.tid tag +# https://github.com/DataDog/dd-trace-py/blob/3e34d21cb9b5e1916e549047158cb119317b96ab/ddtrace/propagation/http.py#L232-L240 +def _generate_sfn_trace_id(pre_hash: str, part: str): + if part == HIGHER_64_BITS: + return hex(_deterministic_sha256_hash(pre_hash, part))[2:] + return _deterministic_sha256_hash(pre_hash, part) + + def extract_context_from_step_functions(event, lambda_context): """ Only extract datadog trace context when Step Functions Context Object is injected @@ -410,29 +422,18 @@ def extract_context_from_step_functions(event, lambda_context): if high_64_bit_trace_id: meta["_dd.p.tid"] = high_64_bit_trace_id else: # sfn root - trace_id = _deterministic_sha256_hash( - dd_data.get("RootExecutionId"), LOWER_64_BITS + root_execution_id = dd_data.get("RootExecutionId") + trace_id = _generate_sfn_trace_id(root_execution_id, LOWER_64_BITS) + meta["_dd.p.tid"] = _generate_sfn_trace_id( + root_execution_id, HIGHER_64_BITS ) - meta["_dd.p.tid"] = hex( - _deterministic_sha256_hash( - dd_data.get("RootExecutionId"), HIGHER_64_BITS - ) - )[2:] - parent_id = _sfn_context_to_parent_id(dd_data) + parent_id = _generate_sfn_parent_id(dd_data) else: execution_id = event.get("Execution").get("Id") - # returning 128 bits since 128bit traceId will be break up into - # traditional traceId and _dd.p.tid tag - # https://github.com/DataDog/dd-trace-py/blob/3e34d21cb9b5e1916e549047158cb119317b96ab/ddtrace/propagation/http.py#L232-L240 - trace_id = _deterministic_sha256_hash(execution_id, LOWER_64_BITS) - # take the higher 64 bits as _dd.p.tid tag and use hex to encode - # [2:] to remove '0x' in the hex str - meta["_dd.p.tid"] = hex( - _deterministic_sha256_hash(execution_id, HIGHER_64_BITS) - )[2:] - - parent_id = _sfn_context_to_parent_id(event) + trace_id = _generate_sfn_trace_id(execution_id, LOWER_64_BITS) + meta["_dd.p.tid"] = _generate_sfn_trace_id(execution_id, HIGHER_64_BITS) + parent_id = _generate_sfn_parent_id(event) sampling_priority = SamplingPriority.AUTO_KEEP return Context( @@ -454,8 +455,9 @@ def is_legacy_lambda_step_function(event): return False event = event.get("Payload") - return "_datadog" in event or ( - "Execution" in event and "StateMachine" in event and "State" in event + return isinstance(event, dict) and ( + "_datadog" in event + or ("Execution" in event and "StateMachine" in event and "State" in event) ) diff --git a/tests/test_tracing.py b/tests/test_tracing.py index 520c706c..896ada6a 100644 --- a/tests/test_tracing.py +++ b/tests/test_tracing.py @@ -665,10 +665,7 @@ def test_step_function_trace_data_lambda_root(self): "EnteredTime": "Mon Nov 13 12:43:33 PST 2023", }, "x-datadog-trace-id": "5821803790426892636", - "x-datadog-sampling-priority": "1", "x-datadog-tags": "_dd.p.dm=-0,_dd.p.tid=672a7cb100000000", - "traceparent": "00-672a7cb10000000050cb33b3c06ae95c-5fda9d8d1d1373f9-01", - "tracestate": "dd=p:5fda9d8d1d1373f9;s:1;t.dm:-0;t.tid:672a7cb100000000", "serverless-version": "v2", } } @@ -737,47 +734,6 @@ def test_step_function_trace_data_sfn_root(self): expected_context, ) - def test_is_legacy_lambda_step_function(self): - sf_event = { - "Payload": { - "Execution": { - "Id": "665c417c-1237-4742-aaca-8b3becbb9e75", - }, - "StateMachine": {}, - "State": { - "Name": "my-awesome-state", - "EnteredTime": "Mon Nov 13 12:43:33 PST 2023", - }, - } - } - self.assertTrue(is_legacy_lambda_step_function(sf_event)) - - sf_event = { - "Payload": { - "_datadog": { - "x-datadog-trace-id-hash": "fed93f8c162880cb9aa90fcd1f8395383835841d5470d30215f3dd52906ebc58", - "x-datadog-parent-id-hash": "c5eb94cc9220ab5783e1db53debd54b8c93f6f2a3eae1c680d7b849f2d34e551", - "serverless-version": "v2", - } - } - } - self.assertTrue(is_legacy_lambda_step_function(sf_event)) - - sf_event = { - "Execution": { - "Id": "665c417c-1237-4742-aaca-8b3becbb9e75", - }, - "StateMachine": {}, - "State": { - "Name": "my-awesome-state", - "EnteredTime": "Mon Nov 13 12:43:33 PST 2023", - }, - } - self.assertFalse(is_legacy_lambda_step_function(sf_event)) - - other_event = ["foo", "bar"] - self.assertFalse(is_legacy_lambda_step_function(other_event)) - class TestXRayContextConversion(unittest.TestCase): def test_convert_xray_trace_id(self): From 3bfc1e757b301bd2f22e52d7b9f2579a95885512 Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Wed, 13 Nov 2024 15:34:12 -0500 Subject: [PATCH 20/24] added unit tests --- datadog_lambda/tracing.py | 33 ++++++++++++++++---------- datadog_lambda/trigger.py | 1 - tests/event_samples/stepfunctions.json | 26 ++++++++++++++++++++ tests/test_trigger.py | 29 ++++++++++++++++++++++ 4 files changed, 76 insertions(+), 13 deletions(-) create mode 100644 tests/event_samples/stepfunctions.json diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index 919a19a8..45febc2e 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -371,7 +371,10 @@ def _deterministic_sha256_hash(s: str, part: str) -> int: def _parse_high_64_bits(trace_tags: str) -> str: - # todo: testme + """ + Parse a list of trace tags such as [_dd.p.tid=66bcb5eb00000000,_dd.p.dm=-0] and return the value of the _dd.p.tid + tag or an empty string if not found. + """ if trace_tags: for tag in trace_tags.split(","): if "_dd.p.tid=" in tag: @@ -380,7 +383,6 @@ def _parse_high_64_bits(trace_tags: str) -> str: return "" -# todo: testme def _generate_sfn_parent_id(context: dict) -> int: execution_id = context.get("Execution").get("Id") state_name = context.get("State").get("Name") @@ -391,24 +393,31 @@ def _generate_sfn_parent_id(context: dict) -> int: ) -# take the higher 64 bits as _dd.p.tid tag and use hex to encode -# [2:] to remove '0x' in the hex str -# todo testme -# returning 128 bits since 128bit traceId will be break up into -# traditional traceId and _dd.p.tid tag -# https://github.com/DataDog/dd-trace-py/blob/3e34d21cb9b5e1916e549047158cb119317b96ab/ddtrace/propagation/http.py#L232-L240 -def _generate_sfn_trace_id(pre_hash: str, part: str): +def _generate_sfn_trace_id(execution_id: str, part: str): + """ + Take the SHA-256 hash of the execution_id to calculate the trace ID. If the high 64 bits are specified, we take + those bits and use hex to encode it. We also remove the first two characters as they will be '0x in the hex string. + + We care about full 128 bits because they will break up into traditional traceID and _dd.p.tid tag. + https://github.com/DataDog/dd-trace-py/blob/3e34d21cb9b5e1916e549047158cb119317b96ab/ddtrace/propagation/http.py#L232-L240 + """ if part == HIGHER_64_BITS: - return hex(_deterministic_sha256_hash(pre_hash, part))[2:] - return _deterministic_sha256_hash(pre_hash, part) + return hex(_deterministic_sha256_hash(execution_id, part))[2:] + return _deterministic_sha256_hash(execution_id, part) def extract_context_from_step_functions(event, lambda_context): """ Only extract datadog trace context when Step Functions Context Object is injected into lambda's event dict. + + If '_datadog' header is present, we have two cases: + 1. Root is a Lambda and we use its traceID + 2. Root is a SFN, and we use its executionARN to calculate the traceID + We calculate the parentID the same in both cases by using the parent SFN's context object. + + Otherwise, we're dealing with the legacy case where we only have the parent SFN's context object. """ - # todo: update docstring try: meta = {} dd_data = event.get("_datadog") diff --git a/datadog_lambda/trigger.py b/datadog_lambda/trigger.py index 7210bb5b..589504fe 100644 --- a/datadog_lambda/trigger.py +++ b/datadog_lambda/trigger.py @@ -256,7 +256,6 @@ def parse_event_source_arn(source: _EventSource, event: dict, context: Any) -> s if source.event_type == EventTypes.CLOUDWATCH_EVENTS and event.get("resources"): return event.get("resources")[0] - # todo: testme # e.g. arn:aws:states:us-east-1:123456789012:stateMachine:stateMachineName if source.event_type == EventTypes.STEPFUNCTIONS: context = event diff --git a/tests/event_samples/stepfunctions.json b/tests/event_samples/stepfunctions.json new file mode 100644 index 00000000..5cc3a1f3 --- /dev/null +++ b/tests/event_samples/stepfunctions.json @@ -0,0 +1,26 @@ +{ + "Records": [ + { + "_datadog": { + "Execution": { + "Id": "arn:aws:states:ca-central-1:425362996713:execution:MyStateMachine-wsx8chv4d:1356a963-42a5-48b0-ba3f-73bde559a50c", + "StartTime": "2024-11-13T16:46:47.715Z", + "Name": "1356a963-42a5-48b0-ba3f-73bde559a50c", + "RoleArn": "arn:aws:iam::425362996713:role/service-role/StepFunctions-MyStateMachine-wsx8chv4d-role-1su0fkfd3", + "RedriveCount": 0 + }, + "StateMachine": { + "Id": "arn:aws:states:ca-central-1:425362996713:stateMachine:MyStateMachine-wsx8chv4d", + "Name": "MyStateMachine-wsx8chv4d" + }, + "State": { + "Name": "Lambda Invoke", + "EnteredTime": "2024-11-13T16:46:47.740Z", + "RetryCount": 0 + }, + "RootExecutionId": "arn:aws:states:ca-central-1:425362996713:execution:MyStateMachine-wsx8chv4d:1356a963-42a5-48b0-ba3f-73bde559a50c", + "serverless-version": "v2" + } + } + ] +} diff --git a/tests/test_trigger.py b/tests/test_trigger.py index c1e7f5d7..d2ac0e7c 100644 --- a/tests/test_trigger.py +++ b/tests/test_trigger.py @@ -230,6 +230,20 @@ def test_event_source_sqs(self): "arn:aws:sqs:eu-west-1:601427279990:InferredSpansQueueNode", ) + def test_event_source_stepfunctions(self): + event_sample_source = "stepfunctions" + test_file = event_samples + event_sample_source + ".json" + with open(test_file, "r") as event: + event = json.load(event) + ctx = get_mock_context() + event_source = parse_event_source(event) + event_source_arn = get_event_source_arn(event_source, event, ctx) + self.assertEqual(event_source.to_string(), event_sample_source) + self.assertEqual( + event_source_arn, + "arn:aws:states:ca-central-1:425362996713:stateMachine:MyStateMachine-wsx8chv4d", + ) + def test_event_source_unsupported(self): event_sample_source = "custom" test_file = event_samples + event_sample_source + ".json" @@ -485,6 +499,21 @@ def test_extract_trigger_tags_sqs(self): }, ) + def test_extract_trigger_tags_stepfunctions(self): + event_sample_source = "stepfunctions" + test_file = event_samples + event_sample_source + ".json" + ctx = get_mock_context() + with open(test_file, "r") as event: + event = json.load(event) + tags = extract_trigger_tags(event, ctx) + self.assertEqual( + tags, + { + "function_trigger.event_source": "stepfunctions", + "function_trigger.event_source_arn": "arn:aws:states:ca-central-1:425362996713:stateMachine:MyStateMachine-wsx8chv4d", + }, + ) + def test_extract_trigger_tags_unsupported(self): event_sample_source = "custom" test_file = event_samples + event_sample_source + ".json" From 6abb3f319baffbb7fdc97701764eaa6928b7dea6 Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Wed, 13 Nov 2024 15:49:21 -0500 Subject: [PATCH 21/24] update test data --- datadog_lambda/tracing.py | 13 ++++---- tests/event_samples/stepfunctions.json | 44 ++++++++++++-------------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index 45febc2e..62dfc4f7 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -372,8 +372,8 @@ def _deterministic_sha256_hash(s: str, part: str) -> int: def _parse_high_64_bits(trace_tags: str) -> str: """ - Parse a list of trace tags such as [_dd.p.tid=66bcb5eb00000000,_dd.p.dm=-0] and return the value of the _dd.p.tid - tag or an empty string if not found. + Parse a list of trace tags such as [_dd.p.tid=66bcb5eb00000000,_dd.p.dm=-0] and return the + value of the _dd.p.tid tag or an empty string if not found. """ if trace_tags: for tag in trace_tags.split(","): @@ -395,11 +395,11 @@ def _generate_sfn_parent_id(context: dict) -> int: def _generate_sfn_trace_id(execution_id: str, part: str): """ - Take the SHA-256 hash of the execution_id to calculate the trace ID. If the high 64 bits are specified, we take - those bits and use hex to encode it. We also remove the first two characters as they will be '0x in the hex string. + Take the SHA-256 hash of the execution_id to calculate the trace ID. If the high 64 bits are + specified, we take those bits and use hex to encode it. We also remove the first two characters + as they will be '0x in the hex string. We care about full 128 bits because they will break up into traditional traceID and _dd.p.tid tag. - https://github.com/DataDog/dd-trace-py/blob/3e34d21cb9b5e1916e549047158cb119317b96ab/ddtrace/propagation/http.py#L232-L240 """ if part == HIGHER_64_BITS: return hex(_deterministic_sha256_hash(execution_id, part))[2:] @@ -416,7 +416,8 @@ def extract_context_from_step_functions(event, lambda_context): 2. Root is a SFN, and we use its executionARN to calculate the traceID We calculate the parentID the same in both cases by using the parent SFN's context object. - Otherwise, we're dealing with the legacy case where we only have the parent SFN's context object. + Otherwise, we're dealing with the legacy case where we only have the parent SFN's context + object. """ try: meta = {} diff --git a/tests/event_samples/stepfunctions.json b/tests/event_samples/stepfunctions.json index 5cc3a1f3..624ed774 100644 --- a/tests/event_samples/stepfunctions.json +++ b/tests/event_samples/stepfunctions.json @@ -1,26 +1,22 @@ { - "Records": [ - { - "_datadog": { - "Execution": { - "Id": "arn:aws:states:ca-central-1:425362996713:execution:MyStateMachine-wsx8chv4d:1356a963-42a5-48b0-ba3f-73bde559a50c", - "StartTime": "2024-11-13T16:46:47.715Z", - "Name": "1356a963-42a5-48b0-ba3f-73bde559a50c", - "RoleArn": "arn:aws:iam::425362996713:role/service-role/StepFunctions-MyStateMachine-wsx8chv4d-role-1su0fkfd3", - "RedriveCount": 0 - }, - "StateMachine": { - "Id": "arn:aws:states:ca-central-1:425362996713:stateMachine:MyStateMachine-wsx8chv4d", - "Name": "MyStateMachine-wsx8chv4d" - }, - "State": { - "Name": "Lambda Invoke", - "EnteredTime": "2024-11-13T16:46:47.740Z", - "RetryCount": 0 - }, - "RootExecutionId": "arn:aws:states:ca-central-1:425362996713:execution:MyStateMachine-wsx8chv4d:1356a963-42a5-48b0-ba3f-73bde559a50c", - "serverless-version": "v2" - } - } - ] + "_datadog": { + "Execution": { + "Id": "arn:aws:states:ca-central-1:425362996713:execution:MyStateMachine-wsx8chv4d:1356a963-42a5-48b0-ba3f-73bde559a50c", + "StartTime": "2024-11-13T16:46:47.715Z", + "Name": "1356a963-42a5-48b0-ba3f-73bde559a50c", + "RoleArn": "arn:aws:iam::425362996713:role/service-role/StepFunctions-MyStateMachine-wsx8chv4d-role-1su0fkfd3", + "RedriveCount": 0 + }, + "StateMachine": { + "Id": "arn:aws:states:ca-central-1:425362996713:stateMachine:MyStateMachine-wsx8chv4d", + "Name": "MyStateMachine-wsx8chv4d" + }, + "State": { + "Name": "Lambda Invoke", + "EnteredTime": "2024-11-13T16:46:47.740Z", + "RetryCount": 0 + }, + "RootExecutionId": "arn:aws:states:ca-central-1:425362996713:execution:MyStateMachine-wsx8chv4d:1356a963-42a5-48b0-ba3f-73bde559a50c", + "serverless-version": "v2" + } } From cae62b1b71ae17e3b44bc34984f4c97d712451d1 Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Wed, 13 Nov 2024 15:54:46 -0500 Subject: [PATCH 22/24] rename stepfunctions to states --- datadog_lambda/tracing.py | 3 ++- tests/event_samples/{stepfunctions.json => states.json} | 0 tests/test_trigger.py | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) rename tests/event_samples/{stepfunctions.json => states.json} (100%) diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index 62dfc4f7..a6467d91 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -399,7 +399,8 @@ def _generate_sfn_trace_id(execution_id: str, part: str): specified, we take those bits and use hex to encode it. We also remove the first two characters as they will be '0x in the hex string. - We care about full 128 bits because they will break up into traditional traceID and _dd.p.tid tag. + We care about full 128 bits because they will break up into traditional traceID and + _dd.p.tid tag. """ if part == HIGHER_64_BITS: return hex(_deterministic_sha256_hash(execution_id, part))[2:] diff --git a/tests/event_samples/stepfunctions.json b/tests/event_samples/states.json similarity index 100% rename from tests/event_samples/stepfunctions.json rename to tests/event_samples/states.json diff --git a/tests/test_trigger.py b/tests/test_trigger.py index d2ac0e7c..be028a23 100644 --- a/tests/test_trigger.py +++ b/tests/test_trigger.py @@ -231,7 +231,7 @@ def test_event_source_sqs(self): ) def test_event_source_stepfunctions(self): - event_sample_source = "stepfunctions" + event_sample_source = "states" test_file = event_samples + event_sample_source + ".json" with open(test_file, "r") as event: event = json.load(event) @@ -500,7 +500,7 @@ def test_extract_trigger_tags_sqs(self): ) def test_extract_trigger_tags_stepfunctions(self): - event_sample_source = "stepfunctions" + event_sample_source = "states" test_file = event_samples + event_sample_source + ".json" ctx = get_mock_context() with open(test_file, "r") as event: @@ -509,7 +509,7 @@ def test_extract_trigger_tags_stepfunctions(self): self.assertEqual( tags, { - "function_trigger.event_source": "stepfunctions", + "function_trigger.event_source": "states", "function_trigger.event_source_arn": "arn:aws:states:ca-central-1:425362996713:stateMachine:MyStateMachine-wsx8chv4d", }, ) From 49dbaf297f09692d7ec9fec707ea73ce71638a2b Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Thu, 14 Nov 2024 10:41:39 -0500 Subject: [PATCH 23/24] update current serverless version to v1 --- datadog_lambda/tracing.py | 2 +- datadog_lambda/trigger.py | 2 +- tests/event_samples/states.json | 2 +- tests/test_tracing.py | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/datadog_lambda/tracing.py b/datadog_lambda/tracing.py index a6467d91..5ed306a3 100644 --- a/datadog_lambda/tracing.py +++ b/datadog_lambda/tracing.py @@ -424,7 +424,7 @@ def extract_context_from_step_functions(event, lambda_context): meta = {} dd_data = event.get("_datadog") - if dd_data and dd_data.get("serverless-version") == "v2": + if dd_data and dd_data.get("serverless-version") == "v1": if "x-datadog-trace-id" in dd_data: # lambda root trace_id = int(dd_data.get("x-datadog-trace-id")) high_64_bit_trace_id = _parse_high_64_bits( diff --git a/datadog_lambda/trigger.py b/datadog_lambda/trigger.py index 589504fe..d57d4c35 100644 --- a/datadog_lambda/trigger.py +++ b/datadog_lambda/trigger.py @@ -147,7 +147,7 @@ def parse_event_source(event: dict) -> _EventSource: event_source = _EventSource(EventTypes.CLOUDWATCH_EVENTS) if ( - "_datadog" in event and event.get("_datadog").get("serverless-version") == "v2" + "_datadog" in event and event.get("_datadog").get("serverless-version") == "v1" ) or ("Execution" in event and "StateMachine" in event and "State" in event): event_source = _EventSource(EventTypes.STEPFUNCTIONS) diff --git a/tests/event_samples/states.json b/tests/event_samples/states.json index 624ed774..778fe437 100644 --- a/tests/event_samples/states.json +++ b/tests/event_samples/states.json @@ -17,6 +17,6 @@ "RetryCount": 0 }, "RootExecutionId": "arn:aws:states:ca-central-1:425362996713:execution:MyStateMachine-wsx8chv4d:1356a963-42a5-48b0-ba3f-73bde559a50c", - "serverless-version": "v2" + "serverless-version": "v1" } } diff --git a/tests/test_tracing.py b/tests/test_tracing.py index 896ada6a..d0db05cd 100644 --- a/tests/test_tracing.py +++ b/tests/test_tracing.py @@ -666,7 +666,7 @@ def test_step_function_trace_data_lambda_root(self): }, "x-datadog-trace-id": "5821803790426892636", "x-datadog-tags": "_dd.p.dm=-0,_dd.p.tid=672a7cb100000000", - "serverless-version": "v2", + "serverless-version": "v1", } } ctx, source, event_source = extract_dd_trace_context(sfn_event, lambda_ctx) @@ -707,7 +707,7 @@ def test_step_function_trace_data_sfn_root(self): "EnteredTime": "Mon Nov 13 12:43:33 PST 2023", }, "RootExecutionId": "4875aba4-ae31-4a4c-bf8a-63e9eee31dad", - "serverless-version": "v2", + "serverless-version": "v1", } } ctx, source, event_source = extract_dd_trace_context(sfn_event, lambda_ctx) From c47fc622979724e9a8dae86158da57077da63003 Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Thu, 14 Nov 2024 10:46:04 -0500 Subject: [PATCH 24/24] Update trigger comment Co-authored-by: kimi <47579703+kimi-p@users.noreply.github.com> --- datadog_lambda/trigger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datadog_lambda/trigger.py b/datadog_lambda/trigger.py index d57d4c35..11759a0a 100644 --- a/datadog_lambda/trigger.py +++ b/datadog_lambda/trigger.py @@ -256,7 +256,7 @@ def parse_event_source_arn(source: _EventSource, event: dict, context: Any) -> s if source.event_type == EventTypes.CLOUDWATCH_EVENTS and event.get("resources"): return event.get("resources")[0] - # e.g. arn:aws:states:us-east-1:123456789012:stateMachine:stateMachineName + # Returning state machine arn as event source arn. if source.event_type == EventTypes.STEPFUNCTIONS: context = event if "_datadog" in event: